1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.wm; 18 19 import static android.app.ActivityTaskManager.INVALID_TASK_ID; 20 import static android.app.AppOpsManager.MODE_ALLOWED; 21 import static android.app.AppOpsManager.MODE_DEFAULT; 22 import static android.app.AppOpsManager.OP_NONE; 23 import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM; 24 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; 25 import static android.content.pm.ActivityInfo.CONFIG_WINDOW_CONFIGURATION; 26 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; 27 import static android.graphics.GraphicsProtos.dumpPointProto; 28 import static android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS; 29 import static android.os.PowerManager.DRAW_WAKE_LOCK; 30 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; 31 import static android.view.SurfaceControl.Transaction; 32 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT; 33 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME; 34 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION; 35 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE; 36 import static android.view.WindowInsets.Type.navigationBars; 37 import static android.view.WindowInsets.Type.systemBars; 38 import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; 39 import static android.view.WindowLayout.UNSPECIFIED_LENGTH; 40 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; 41 import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW; 42 import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON; 43 import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; 44 import static android.view.WindowManager.LayoutParams.FLAG_BLUR_BEHIND; 45 import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND; 46 import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD; 47 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 48 import static android.view.WindowManager.LayoutParams.FLAG_SCALED; 49 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; 50 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; 51 import static android.view.WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON; 52 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW; 53 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; 54 import static android.view.WindowManager.LayoutParams.MATCH_PARENT; 55 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NOT_MAGNIFIABLE; 56 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION; 57 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_APPLICATION_OVERLAY; 58 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY; 59 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; 60 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST; 61 import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; 62 import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS; 63 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY; 64 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA; 65 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY; 66 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; 67 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; 68 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; 69 import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS; 70 import static android.view.WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY; 71 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; 72 import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION; 73 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_CONSUMER; 74 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; 75 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; 76 import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG; 77 import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY; 78 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; 79 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL; 80 import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE; 81 import static android.view.WindowManager.LayoutParams.TYPE_PHONE; 82 import static android.view.WindowManager.LayoutParams.TYPE_POINTER; 83 import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION; 84 import static android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE; 85 import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION; 86 import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT; 87 import static android.view.WindowManager.LayoutParams.TYPE_SEARCH_BAR; 88 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; 89 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL; 90 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL; 91 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG; 92 import static android.view.WindowManager.LayoutParams.TYPE_TOAST; 93 import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY; 94 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; 95 import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType; 96 import static android.view.WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME; 97 import static android.view.WindowManagerPolicyConstants.TYPE_LAYER_MULTIPLIER; 98 import static android.view.WindowManagerPolicyConstants.TYPE_LAYER_OFFSET; 99 100 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE; 101 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ANIM; 102 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS; 103 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_BACK_PREVIEW; 104 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS; 105 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT; 106 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION; 107 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_RESIZE; 108 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW; 109 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_SYNC_ENGINE; 110 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_INSETS; 111 import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS; 112 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 113 import static com.android.server.policy.WindowManagerPolicy.TRANSIT_ENTER; 114 import static com.android.server.policy.WindowManagerPolicy.TRANSIT_EXIT; 115 import static com.android.server.policy.WindowManagerPolicy.TRANSIT_PREVIEW_DONE; 116 import static com.android.server.wm.AnimationSpecProto.MOVE; 117 import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING; 118 import static com.android.server.wm.DisplayContent.logsGestureExclusionRestrictions; 119 import static com.android.server.wm.IdentifierProto.HASH_CODE; 120 import static com.android.server.wm.IdentifierProto.TITLE; 121 import static com.android.server.wm.IdentifierProto.USER_ID; 122 import static com.android.server.wm.MoveAnimationSpecProto.DURATION_MS; 123 import static com.android.server.wm.MoveAnimationSpecProto.FROM; 124 import static com.android.server.wm.MoveAnimationSpecProto.TO; 125 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_ALL; 126 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION; 127 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS; 128 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_STARTING_REVEAL; 129 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION; 130 import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS; 131 import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; 132 import static com.android.server.wm.WindowContainerChildProto.WINDOW; 133 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG; 134 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_CONFIGURATION; 135 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD; 136 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_POWER; 137 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE; 138 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; 139 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; 140 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 141 import static com.android.server.wm.WindowManagerService.H.WINDOW_STATE_BLAST_SYNC_TIMEOUT; 142 import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION; 143 import static com.android.server.wm.WindowManagerService.MY_PID; 144 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL; 145 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_REMOVING_FOCUS; 146 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES; 147 import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_TIMEOUT; 148 import static com.android.server.wm.WindowStateAnimator.COMMIT_DRAW_PENDING; 149 import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING; 150 import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN; 151 import static com.android.server.wm.WindowStateAnimator.PRESERVED_SURFACE_LAYER; 152 import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW; 153 import static com.android.server.wm.WindowStateProto.ANIMATING_EXIT; 154 import static com.android.server.wm.WindowStateProto.ANIMATOR; 155 import static com.android.server.wm.WindowStateProto.ATTRIBUTES; 156 import static com.android.server.wm.WindowStateProto.DESTROYING; 157 import static com.android.server.wm.WindowStateProto.DISPLAY_ID; 158 import static com.android.server.wm.WindowStateProto.FORCE_SEAMLESS_ROTATION; 159 import static com.android.server.wm.WindowStateProto.GIVEN_CONTENT_INSETS; 160 import static com.android.server.wm.WindowStateProto.GLOBAL_SCALE; 161 import static com.android.server.wm.WindowStateProto.HAS_COMPAT_SCALE; 162 import static com.android.server.wm.WindowStateProto.HAS_SURFACE; 163 import static com.android.server.wm.WindowStateProto.IS_ON_SCREEN; 164 import static com.android.server.wm.WindowStateProto.IS_READY_FOR_DISPLAY; 165 import static com.android.server.wm.WindowStateProto.IS_VISIBLE; 166 import static com.android.server.wm.WindowStateProto.KEEP_CLEAR_AREAS; 167 import static com.android.server.wm.WindowStateProto.MERGED_LOCAL_INSETS_SOURCES; 168 import static com.android.server.wm.WindowStateProto.PENDING_SEAMLESS_ROTATION; 169 import static com.android.server.wm.WindowStateProto.REMOVED; 170 import static com.android.server.wm.WindowStateProto.REMOVE_ON_EXIT; 171 import static com.android.server.wm.WindowStateProto.REQUESTED_HEIGHT; 172 import static com.android.server.wm.WindowStateProto.REQUESTED_VISIBLE_TYPES; 173 import static com.android.server.wm.WindowStateProto.REQUESTED_WIDTH; 174 import static com.android.server.wm.WindowStateProto.STACK_ID; 175 import static com.android.server.wm.WindowStateProto.SURFACE_INSETS; 176 import static com.android.server.wm.WindowStateProto.SURFACE_POSITION; 177 import static com.android.server.wm.WindowStateProto.UNRESTRICTED_KEEP_CLEAR_AREAS; 178 import static com.android.server.wm.WindowStateProto.VIEW_VISIBILITY; 179 import static com.android.server.wm.WindowStateProto.WINDOW_CONTAINER; 180 import static com.android.server.wm.WindowStateProto.WINDOW_FRAMES; 181 import static com.android.window.flags.Flags.explicitRefreshRateHints; 182 import static com.android.window.flags.Flags.secureWindowState; 183 import static com.android.window.flags.Flags.surfaceTrustedOverlay; 184 185 import android.annotation.CallSuper; 186 import android.annotation.NonNull; 187 import android.annotation.Nullable; 188 import android.app.ActivityTaskManager; 189 import android.app.AppOpsManager; 190 import android.app.admin.DevicePolicyCache; 191 import android.app.servertransaction.WindowStateInsetsControlChangeItem; 192 import android.app.servertransaction.WindowStateResizeItem; 193 import android.content.Context; 194 import android.content.res.Configuration; 195 import android.graphics.Matrix; 196 import android.graphics.PixelFormat; 197 import android.graphics.Point; 198 import android.graphics.Rect; 199 import android.graphics.RectF; 200 import android.graphics.Region; 201 import android.gui.TouchOcclusionMode; 202 import android.os.Binder; 203 import android.os.Build; 204 import android.os.Debug; 205 import android.os.IBinder; 206 import android.os.PowerManager; 207 import android.os.RemoteCallbackList; 208 import android.os.RemoteException; 209 import android.os.SystemClock; 210 import android.os.Trace; 211 import android.os.WorkSource; 212 import android.provider.Settings; 213 import android.util.ArraySet; 214 import android.util.DisplayMetrics; 215 import android.util.MergedConfiguration; 216 import android.util.Slog; 217 import android.util.SparseArray; 218 import android.util.TimeUtils; 219 import android.util.proto.ProtoOutputStream; 220 import android.view.Display; 221 import android.view.DisplayInfo; 222 import android.view.IWindow; 223 import android.view.IWindowFocusObserver; 224 import android.view.IWindowId; 225 import android.view.InputChannel; 226 import android.view.InputWindowHandle; 227 import android.view.InsetsSource; 228 import android.view.InsetsSourceControl; 229 import android.view.InsetsState; 230 import android.view.Surface; 231 import android.view.Surface.Rotation; 232 import android.view.SurfaceControl; 233 import android.view.SurfaceSession; 234 import android.view.View; 235 import android.view.ViewDebug; 236 import android.view.ViewTreeObserver; 237 import android.view.WindowInfo; 238 import android.view.WindowInsets; 239 import android.view.WindowInsets.Type.InsetsType; 240 import android.view.WindowManager; 241 import android.view.animation.Animation; 242 import android.view.animation.AnimationUtils; 243 import android.view.animation.Interpolator; 244 import android.view.inputmethod.ImeTracker; 245 import android.window.ActivityWindowInfo; 246 import android.window.ClientWindowFrames; 247 import android.window.OnBackInvokedCallbackInfo; 248 249 import com.android.internal.annotations.VisibleForTesting; 250 import com.android.internal.policy.KeyInterceptionInfo; 251 import com.android.internal.protolog.common.LogLevel; 252 import com.android.internal.protolog.common.ProtoLog; 253 import com.android.internal.util.FrameworkStatsLog; 254 import com.android.internal.util.ToBooleanFunction; 255 import com.android.server.policy.WindowManagerPolicy; 256 import com.android.server.wm.LocalAnimationAdapter.AnimationSpec; 257 import com.android.server.wm.RefreshRatePolicy.FrameRateVote; 258 import com.android.server.wm.SurfaceAnimator.AnimationType; 259 import com.android.window.flags.Flags; 260 261 import dalvik.annotation.optimization.NeverCompile; 262 263 import java.io.PrintWriter; 264 import java.io.StringWriter; 265 import java.lang.ref.WeakReference; 266 import java.util.ArrayList; 267 import java.util.Collection; 268 import java.util.Comparator; 269 import java.util.List; 270 import java.util.function.Consumer; 271 import java.util.function.Predicate; 272 273 /** A window in the window manager. */ 274 class WindowState extends WindowContainer<WindowState> implements WindowManagerPolicy.WindowState, 275 InsetsControlTarget, InputTarget { 276 static final String TAG = TAG_WITH_CLASS_NAME ? "WindowState" : TAG_WM; 277 278 // The minimal size of a window within the usable area of the freeform root task. 279 // TODO(multi-window): fix the min sizes when we have minimum width/height support, 280 // use hard-coded min sizes for now. 281 static final int MINIMUM_VISIBLE_WIDTH_IN_DP = 48; 282 static final int MINIMUM_VISIBLE_HEIGHT_IN_DP = 32; 283 284 // The thickness of a window resize handle outside the window bounds on the free form workspace 285 // to capture touch events in that area. 286 static final int RESIZE_HANDLE_WIDTH_IN_DP = 30; 287 288 static final int EXCLUSION_LEFT = 0; 289 static final int EXCLUSION_RIGHT = 1; 290 291 final WindowManagerPolicy mPolicy; 292 final Context mContext; 293 final Session mSession; 294 final IWindow mClient; 295 final int mAppOp; 296 // UserId and appId of the owner. Don't display windows of non-current user. 297 final int mOwnerUid; 298 /** 299 * Requested userId, if this is not equals with the userId from mOwnerUid, then this window is 300 * created for secondary user. 301 * Use this member instead of get userId from mOwnerUid while query for visibility. 302 */ 303 final int mShowUserId; 304 /** The owner has {@link android.Manifest.permission#INTERNAL_SYSTEM_WINDOW} */ 305 final boolean mOwnerCanAddInternalSystemWindow; 306 final WindowId mWindowId; 307 @NonNull WindowToken mToken; 308 // The same object as mToken if this is an app window and null for non-app windows. 309 ActivityRecord mActivityRecord; 310 /** Non-null if this is a starting window. */ 311 StartingData mStartingData; 312 313 // mAttrs.flags is tested in animation without being locked. If the bits tested are ever 314 // modified they will need to be locked. 315 final WindowManager.LayoutParams mAttrs = new WindowManager.LayoutParams(); 316 private boolean mIsChildWindow; 317 final int mBaseLayer; 318 final int mSubLayer; 319 final boolean mLayoutAttached; 320 final boolean mIsImWindow; 321 final boolean mIsWallpaper; 322 private final boolean mIsFloatingLayer; 323 int mViewVisibility; 324 325 /** 326 * Flags to disable system UI functions. This can only be set by the one which has the 327 * status bar permission. 328 * 329 * @see View.SystemUiVisibility 330 */ 331 int mDisableFlags; 332 333 /** 334 * The visibility flag of the window based on policy like {@link WindowManagerPolicy}. 335 * Normally set by calling {@link #show} and {@link #hide}. 336 * 337 * TODO: b/131253938 This will eventually be split into individual visibility policy flags. 338 */ 339 static final int LEGACY_POLICY_VISIBILITY = 1; 340 /** 341 * The visibility flag that determines whether this window is visible for the current user. 342 */ 343 private static final int VISIBLE_FOR_USER = 1 << 1; 344 private static final int POLICY_VISIBILITY_ALL = VISIBLE_FOR_USER | LEGACY_POLICY_VISIBILITY; 345 /** 346 * The Bitwise-or of flags that contribute to visibility of the WindowState 347 */ 348 private int mPolicyVisibility = POLICY_VISIBILITY_ALL; 349 350 /** 351 * Whether {@link #LEGACY_POLICY_VISIBILITY} flag should be set after a transition animation. 352 * For example, {@link #LEGACY_POLICY_VISIBILITY} might be set during an exit animation to hide 353 * it and then unset when the value of {@link #mLegacyPolicyVisibilityAfterAnim} is false 354 * after the exit animation is done. 355 * 356 * TODO: b/131253938 Determine whether this can be changed to use a visibility flag instead. 357 */ 358 boolean mLegacyPolicyVisibilityAfterAnim = true; 359 // overlay window is hidden because the owning app is suspended 360 private boolean mHiddenWhileSuspended; 361 private boolean mAppOpVisibility = true; 362 363 boolean mPermanentlyHidden; // the window should never be shown again 364 // This is a non-system overlay window that is currently force hidden. 365 private boolean mForceHideNonSystemOverlayWindow; 366 boolean mAppFreezing; 367 boolean mHidden = true; // Used to determine if to show child windows. 368 private boolean mDragResizing; 369 private boolean mDragResizingChangeReported = true; 370 private boolean mRedrawForSyncReported = true; 371 private long mCreateTime = System.currentTimeMillis(); 372 373 /** 374 * Used to assosciate a given set of state changes sent from MSG_RESIZED 375 * with a given call to finishDrawing (does this call contain or not contain 376 * those state changes). We need to use it to handle cases like this: 377 * 1. Server changes some state, calls applyWithNextDraw 378 * 2. Client observes state change, begins drawing frame. 379 * 3. Server makes another state change, and calls applyWithNextDraw again 380 * 4. We receive finishDrawing, and it only contains the first frame 381 * but there was no way for us to know, because we no longer rely 382 * on a synchronous call to relayout before draw. 383 * We track this by storing seqIds in each draw handler, and increment 384 * this seqId every time we send MSG_RESIZED. The client sends it back 385 * with finishDrawing, and this way we can know is the client replying to 386 * the latest MSG_RESIZED or an earlier one. For a detailed discussion, 387 * examine the git commit message introducing this comment and variable.2 388 */ 389 int mSyncSeqId = 0; 390 391 /** The last syncId associated with a BLAST prepareSync or 0 when no BLAST sync is active. */ 392 int mPrepareSyncSeqId = 0; 393 394 /** 395 * Special mode that is intended only for the rounded corner overlay: during rotation 396 * transition, we un-rotate the window token such that the window appears as it did before the 397 * rotation. 398 */ 399 final boolean mForceSeamlesslyRotate; 400 SeamlessRotator mPendingSeamlessRotate; 401 402 private RemoteCallbackList<IWindowFocusObserver> mFocusCallbacks; 403 404 /** 405 * The window size that was requested by the application. These are in 406 * the application's coordinate space (without compatibility scale applied). 407 */ 408 int mRequestedWidth; 409 int mRequestedHeight; 410 private int mLastRequestedWidth; 411 private int mLastRequestedHeight; 412 413 int mLayer; 414 boolean mHaveFrame; 415 boolean mObscured; 416 417 int mRelayoutSeq = -1; 418 int mLayoutSeq = -1; 419 420 /** 421 * Used to store last reported to client configuration and check if we have newer available. 422 * We'll send configuration to client only if it is different from the last applied one and 423 * client won't perform unnecessary updates. 424 */ 425 private final MergedConfiguration mLastReportedConfiguration = new MergedConfiguration(); 426 427 /** 428 * Similar to {@link #mLastReportedConfiguration}, used to store last reported to client 429 * ActivityWindowInfo. {@code null} if this is not an Activity window. 430 */ 431 @Nullable 432 final ActivityWindowInfo mLastReportedActivityWindowInfo; 433 434 /** @see #isLastConfigReportedToClient() */ 435 private boolean mLastConfigReportedToClient; 436 437 private final ClientWindowFrames mLastReportedFrames = new ClientWindowFrames(); 438 439 private final InsetsState mLastReportedInsetsState = new InsetsState(); 440 441 private final InsetsSourceControl.Array mLastReportedActiveControls = 442 new InsetsSourceControl.Array(); 443 444 private final Configuration mTempConfiguration = new Configuration(); 445 446 /** 447 * Set to true if we are waiting for this window to receive its 448 * given internal insets before laying out other windows based on it. 449 */ 450 boolean mGivenInsetsPending; 451 452 /** 453 * These are the content insets that were given during layout for this window, to be applied to 454 * windows behind it. 455 * This is only applied to IME windows when corresponding process in DisplayPolicy executed. 456 */ 457 final Rect mGivenContentInsets = new Rect(); 458 459 /** 460 * These are the visible insets that were given during layout for 461 * this window, to be applied to windows behind it. 462 */ 463 final Rect mGivenVisibleInsets = new Rect(); 464 465 /** 466 * This is the given touchable area relative to the window frame, or null if none. 467 */ 468 final Region mGivenTouchableRegion = new Region(); 469 470 /** 471 * Flag indicating whether the touchable region should be adjusted by 472 * the visible insets; if false the area outside the visible insets is 473 * NOT touchable, so we must use those to adjust the frame during hit 474 * tests. 475 */ 476 int mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME; 477 478 // Current transformation being applied. 479 float mGlobalScale = 1f; 480 float mInvGlobalScale = 1f; 481 float mCompatScale = 1f; 482 final float mOverrideScale; 483 float mHScale = 1f, mVScale = 1f; 484 float mLastHScale = 1f, mLastVScale = 1f; 485 486 // An offset in pixel of the surface contents from the window position. Used for Wallpaper 487 // to provide the effect of scrolling within a large surface. We just use these values as 488 // a cache. 489 int mXOffset = 0; 490 int mYOffset = 0; 491 492 // A scale factor for the surface contents, that will be applied from the center of the visible 493 // region. 494 float mWallpaperScale = 1f; 495 496 final Matrix mTmpMatrix = new Matrix(); 497 final float[] mTmpMatrixArray = new float[9]; 498 499 private final WindowFrames mWindowFrames = new WindowFrames(); 500 501 /** 502 * List of rects where system gestures should be ignored. 503 * 504 * Coordinates are relative to the window's position. 505 */ 506 private final List<Rect> mExclusionRects = new ArrayList<>(); 507 /** 508 * List of rects which should ideally not be covered by floating windows like Pip. 509 * 510 * Coordinates are relative to the window's position. 511 */ 512 private final List<Rect> mKeepClearAreas = new ArrayList<>(); 513 514 /** 515 * Like mKeepClearAreas, but the unrestricted ones can be trusted to behave nicely. 516 * Floating windows (like Pip) will be moved away from them without applying restrictions. 517 */ 518 private final List<Rect> mUnrestrictedKeepClearAreas = new ArrayList<>(); 519 520 // 0 = left, 1 = right 521 private final int[] mLastRequestedExclusionHeight = {0, 0}; 522 private final int[] mLastGrantedExclusionHeight = {0, 0}; 523 private final long[] mLastExclusionLogUptimeMillis = {0, 0}; 524 525 private boolean mLastShownChangedReported; 526 527 // If a window showing a wallpaper: the requested offset for the 528 // wallpaper; if a wallpaper window: the currently applied offset. 529 float mWallpaperX = -1; 530 float mWallpaperY = -1; 531 532 // If a window showing a wallpaper: the requested zoom out for the 533 // wallpaper; if a wallpaper window: the currently applied zoom. 534 float mWallpaperZoomOut = -1; 535 536 // If a wallpaper window: whether the wallpaper should be scaled when zoomed, if set 537 // to false, mWallpaperZoom will be ignored here and just passed to the WallpaperService. 538 boolean mShouldScaleWallpaper; 539 540 // If a window showing a wallpaper: what fraction of the offset 541 // range corresponds to a full virtual screen. 542 float mWallpaperXStep = -1; 543 float mWallpaperYStep = -1; 544 545 // If a window showing a wallpaper: a raw pixel offset to forcibly apply 546 // to its window; if a wallpaper window: not used. 547 int mWallpaperDisplayOffsetX = Integer.MIN_VALUE; 548 int mWallpaperDisplayOffsetY = Integer.MIN_VALUE; 549 550 /** 551 * This is set after IWindowSession.relayout() has been called at 552 * least once for the window. It allows us to detect the situation 553 * where we don't yet have a surface, but should have one soon, so 554 * we can give the window focus before waiting for the relayout. 555 */ 556 boolean mRelayoutCalled; 557 558 boolean mInRelayout; 559 560 /** 561 * If the application has called relayout() with changes that can 562 * impact its window's size, we need to perform a layout pass on it 563 * even if it is not currently visible for layout. This is set 564 * when in that case until the layout is done. 565 */ 566 boolean mLayoutNeeded; 567 568 /** 569 * If the application is not currently visible but requires a layout, 570 * then make sure we call performSurfacePlacement as well. This is set 571 * in layout if mLayoutNeeded is set until surface placement is done. 572 */ 573 boolean mSurfacePlacementNeeded; 574 575 /** 576 * The animation types that will call {@link #onExitAnimationDone} so {@link #mAnimatingExit} 577 * is guaranteed to be cleared. 578 */ 579 static final int EXIT_ANIMATING_TYPES = ANIMATION_TYPE_APP_TRANSITION 580 | ANIMATION_TYPE_WINDOW_ANIMATION | ANIMATION_TYPE_RECENTS; 581 582 /** Currently running an exit animation? */ 583 boolean mAnimatingExit; 584 585 /** Currently on the mDestroySurface list? */ 586 boolean mDestroying; 587 588 /** Completely remove from window manager after exit animation? */ 589 boolean mRemoveOnExit; 590 591 /** 592 * Set when the orientation is changing and this window has not yet 593 * been updated for the new orientation. 594 */ 595 private boolean mOrientationChanging; 596 597 /** The time when the window was last requested to redraw for orientation change. */ 598 private long mOrientationChangeRedrawRequestTime; 599 600 /** 601 * Sometimes in addition to the mOrientationChanging 602 * flag we report that the orientation is changing 603 * due to a mismatch in current and reported configuration. 604 * 605 * In the case of timeout we still need to make sure we 606 * leave the orientation changing state though, so we 607 * use this as a special time out escape hatch. 608 */ 609 private boolean mOrientationChangeTimedOut; 610 611 /** 612 * The orientation during the last visible call to relayout. If our 613 * current orientation is different, the window can't be ready 614 * to be shown. 615 */ 616 int mLastVisibleLayoutRotation = -1; 617 618 /** 619 * How long we last kept the screen frozen. 620 */ 621 int mLastFreezeDuration; 622 623 /** Is this window now (or just being) removed? */ 624 boolean mRemoved; 625 626 /** 627 * It is save to remove the window and destroy the surface because the client requested removal 628 * or some other higher level component said so (e.g. activity manager). 629 * TODO: We should either have different booleans for the removal reason or use a bit-field. 630 */ 631 boolean mWindowRemovalAllowed; 632 633 // Input channel and input window handle used by the input dispatcher. 634 final InputWindowHandleWrapper mInputWindowHandle; 635 InputChannel mInputChannel; 636 637 /** 638 * The token will be assigned to {@link InputWindowHandle#token} if this window can receive 639 * input event. Note that the token of associated input window handle can be cleared if this 640 * window becomes unable to receive input, but this field will remain until the input channel 641 * is actually disposed. 642 */ 643 IBinder mInputChannelToken; 644 645 // Used to improve performance of toString() 646 private String mStringNameCache; 647 private CharSequence mLastTitle; 648 private boolean mWasExiting; 649 650 final WindowStateAnimator mWinAnimator; 651 652 boolean mHasSurface = false; 653 654 // Whether this window is being moved via the resize API 655 private boolean mMovedByResize; 656 657 /** 658 * Wake lock for drawing. 659 * Even though it's slightly more expensive to do so, we will use a separate wake lock 660 * for each app that is requesting to draw while dozing so that we can accurately track 661 * who is preventing the system from suspending. 662 * This lock is only acquired on first use. 663 */ 664 private PowerManager.WakeLock mDrawLock; 665 666 private final Rect mTmpRect = new Rect(); 667 private final Point mTmpPoint = new Point(); 668 private final Region mTmpRegion = new Region(); 669 670 private final Transaction mTmpTransaction; 671 672 /** 673 * Whether the surface position of window is paused to update. Currently it is only used for 674 * {@link Task#setMainWindowSizeChangeTransaction(Transaction)} to synchronize position. 675 */ 676 boolean mIsSurfacePositionPaused; 677 678 /** 679 * During seamless rotation we have two phases, first the old window contents 680 * are rotated to look as if they didn't move in the new coordinate system. Then we 681 * have to freeze updates to this layer (to preserve the transformation) until 682 * the resize actually occurs. This is true from when the transformation is set 683 * and false until the transaction to resize is sent. 684 */ 685 boolean mSeamlesslyRotated = false; 686 687 /** 688 * Whether the IME insets have been consumed. If {@code true}, this window won't be able to 689 * receive visible IME insets; {@code false}, otherwise. 690 */ 691 boolean mImeInsetsConsumed = false; 692 693 /** 694 * The insets state of sources provided by windows above the current window. 695 */ 696 final InsetsState mAboveInsetsState = new InsetsState(); 697 698 /** 699 * The insets state of sources provided by the overrides set on any parent up the hierarchy. 700 */ 701 SparseArray<InsetsSource> mMergedLocalInsetsSources = null; 702 703 /** 704 * Surface insets from the previous call to relayout(), used to track 705 * if we are changing the Surface insets. 706 */ 707 final Rect mLastSurfaceInsets = new Rect(); 708 709 /** 710 * A flag set by the {@link WindowState} parent to indicate that the parent has examined this 711 * {@link WindowState} in its overall drawing context. This book-keeping allows the parent to 712 * make sure all children have been considered. 713 */ 714 private boolean mDrawnStateEvaluated; 715 716 /** The surface position relative to the parent container. */ 717 final Point mSurfacePosition = new Point(); 718 719 /** 720 * A region inside of this window to be excluded from touch. 721 */ 722 private final Region mTapExcludeRegion = new Region(); 723 724 private static final StringBuilder sTmpSB = new StringBuilder(); 725 726 /** 727 * Compares two window sub-layers and returns -1 if the first is lesser than the second in terms 728 * of z-order and 1 otherwise. 729 */ 730 private static final Comparator<WindowState> sWindowSubLayerComparator = 731 new Comparator<WindowState>() { 732 @Override 733 public int compare(WindowState w1, WindowState w2) { 734 final int layer1 = w1.mSubLayer; 735 final int layer2 = w2.mSubLayer; 736 if (layer1 < layer2 || (layer1 == layer2 && layer2 < 0 )) { 737 // We insert the child window into the list ordered by 738 // the sub-layer. For same sub-layers, the negative one 739 // should go below others; the positive one should go 740 // above others. 741 return -1; 742 } 743 return 1; 744 }; 745 }; 746 747 /** 748 * Indicates whether we have requested a Dim (in the sense of {@link Dimmer}) from our host 749 * container. 750 */ 751 private boolean mIsDimming = false; 752 753 private @InsetsType int mRequestedVisibleTypes = WindowInsets.Type.defaultVisible(); 754 755 /** 756 * Freeze the insets state in some cases that not necessarily keeps up-to-date to the client. 757 * (e.g app exiting transition) 758 */ 759 private InsetsState mFrozenInsetsState; 760 761 private KeyInterceptionInfo mKeyInterceptionInfo; 762 763 /** 764 * This information is passed to SurfaceFlinger to decide which window should have a priority 765 * when deciding about the refresh rate of the display. All windows have the lowest priority by 766 * default. The variable is cached, so we do not send too many updates to SF. 767 */ 768 int mFrameRateSelectionPriority = RefreshRatePolicy.LAYER_PRIORITY_UNSET; 769 770 /** 771 * This is the frame rate which is passed to SurfaceFlinger if the window set a 772 * preferredDisplayModeId or is part of the high refresh rate deny list. 773 * The variable is cached, so we do not send too many updates to SF. 774 */ 775 FrameRateVote mFrameRateVote = new FrameRateVote(); 776 777 static final int BLAST_TIMEOUT_DURATION = 5000; /* milliseconds */ 778 779 class DrawHandler { 780 Consumer<SurfaceControl.Transaction> mConsumer; 781 int mSeqId; 782 DrawHandler(int seqId, Consumer<SurfaceControl.Transaction> consumer)783 DrawHandler(int seqId, Consumer<SurfaceControl.Transaction> consumer) { 784 mSeqId = seqId; 785 mConsumer = consumer; 786 } 787 } 788 private final List<DrawHandler> mDrawHandlers = new ArrayList<>(); 789 790 private final Consumer<SurfaceControl.Transaction> mSeamlessRotationFinishedConsumer = t -> { 791 finishSeamlessRotation(t); 792 updateSurfacePosition(t); 793 }; 794 795 private final Consumer<SurfaceControl.Transaction> mSetSurfacePositionConsumer = t -> { 796 // Only apply the position to the surface when there's no leash created. 797 if (mSurfaceControl != null && mSurfaceControl.isValid() && !mSurfaceAnimator.hasLeash()) { 798 t.setPosition(mSurfaceControl, mSurfacePosition.x, mSurfacePosition.y); 799 } 800 }; 801 802 /** 803 * @see #setOnBackInvokedCallbackInfo(OnBackInvokedCallbackInfo) 804 */ 805 private OnBackInvokedCallbackInfo mOnBackInvokedCallbackInfo; 806 @Override asWindowState()807 WindowState asWindowState() { 808 return this; 809 } 810 811 /** 812 * @see #setSurfaceTranslationY(int) 813 */ 814 private int mSurfaceTranslationY; 815 816 @Override isRequestedVisible(@nsetsType int types)817 public boolean isRequestedVisible(@InsetsType int types) { 818 return (mRequestedVisibleTypes & types) != 0; 819 } 820 821 /** 822 * Returns requested visible types of insets. 823 * 824 * @return an integer as the requested visible insets types. 825 */ 826 @Override getRequestedVisibleTypes()827 public @InsetsType int getRequestedVisibleTypes() { 828 return mRequestedVisibleTypes; 829 } 830 831 /** 832 * @see #getRequestedVisibleTypes() 833 */ setRequestedVisibleTypes(@nsetsType int requestedVisibleTypes)834 void setRequestedVisibleTypes(@InsetsType int requestedVisibleTypes) { 835 if (mRequestedVisibleTypes != requestedVisibleTypes) { 836 mRequestedVisibleTypes = requestedVisibleTypes; 837 } 838 } 839 840 @VisibleForTesting setRequestedVisibleTypes(@nsetsType int requestedVisibleTypes, @InsetsType int mask)841 void setRequestedVisibleTypes(@InsetsType int requestedVisibleTypes, @InsetsType int mask) { 842 setRequestedVisibleTypes(mRequestedVisibleTypes & ~mask | requestedVisibleTypes & mask); 843 } 844 845 /** 846 * Set a freeze state for the window to ignore dispatching its insets state to the client. 847 * 848 * Used to keep the insets state for some use cases. (e.g. app exiting transition) 849 */ freezeInsetsState()850 void freezeInsetsState() { 851 if (mFrozenInsetsState == null) { 852 mFrozenInsetsState = new InsetsState(getInsetsState(), true /* copySources */); 853 } 854 } 855 clearFrozenInsetsState()856 void clearFrozenInsetsState() { 857 mFrozenInsetsState = null; 858 } 859 getFrozenInsetsState()860 InsetsState getFrozenInsetsState() { 861 return mFrozenInsetsState; 862 } 863 864 /** 865 * Check if the insets state of the window is ready to dispatch to the client when invoking 866 * {@link InsetsStateController#notifyInsetsChanged}. 867 */ isReadyToDispatchInsetsState()868 boolean isReadyToDispatchInsetsState() { 869 if (mStartingData != null) { 870 // Starting window doesn't consider insets. 871 return false; 872 } 873 final boolean visible = shouldCheckTokenVisibleRequested() 874 ? isVisibleRequested() : isVisible(); 875 return visible && mFrozenInsetsState == null; 876 } 877 seamlesslyRotateIfAllowed(Transaction transaction, @Rotation int oldRotation, @Rotation int rotation, boolean requested)878 void seamlesslyRotateIfAllowed(Transaction transaction, @Rotation int oldRotation, 879 @Rotation int rotation, boolean requested) { 880 // Invisible windows and the wallpaper do not participate in the seamless rotation animation 881 if (!isVisibleNow() || mIsWallpaper) { 882 return; 883 } 884 885 if (mToken.hasFixedRotationTransform()) { 886 // The transform of its surface is handled by fixed rotation. 887 return; 888 } 889 final Task task = getTask(); 890 if (task != null && task.inPinnedWindowingMode()) { 891 // It is handled by PinnedTaskController. Note that the windowing mode of activity 892 // and windows may still be fullscreen. 893 return; 894 } 895 896 if (mPendingSeamlessRotate != null) { 897 oldRotation = mPendingSeamlessRotate.getOldRotation(); 898 } 899 900 // Skip performing seamless rotation when the controlled insets is IME with visible state. 901 if (mControllableInsetProvider != null 902 && mControllableInsetProvider.getSource().getType() == WindowInsets.Type.ime()) { 903 return; 904 } 905 906 if (mForceSeamlesslyRotate || requested) { 907 if (mControllableInsetProvider != null) { 908 mControllableInsetProvider.startSeamlessRotation(); 909 } 910 mPendingSeamlessRotate = new SeamlessRotator(oldRotation, rotation, getDisplayInfo(), 911 false /* applyFixedTransformationHint */); 912 // The surface position is going to be unrotated according to the last position. 913 // Make sure the source position is up-to-date. 914 mLastSurfacePosition.set(mSurfacePosition.x, mSurfacePosition.y); 915 mPendingSeamlessRotate.unrotate(transaction, this); 916 getDisplayContent().getDisplayRotation().markForSeamlessRotation(this, 917 true /* seamlesslyRotated */); 918 applyWithNextDraw(mSeamlessRotationFinishedConsumer); 919 } 920 } 921 cancelSeamlessRotation()922 void cancelSeamlessRotation() { 923 finishSeamlessRotation(getPendingTransaction()); 924 } 925 finishSeamlessRotation(SurfaceControl.Transaction t)926 void finishSeamlessRotation(SurfaceControl.Transaction t) { 927 if (mPendingSeamlessRotate == null) { 928 return; 929 } 930 931 mPendingSeamlessRotate.finish(t, this); 932 mPendingSeamlessRotate = null; 933 934 getDisplayContent().getDisplayRotation().markForSeamlessRotation(this, 935 false /* seamlesslyRotated */); 936 if (mControllableInsetProvider != null) { 937 mControllableInsetProvider.finishSeamlessRotation(); 938 } 939 } 940 getSystemGestureExclusion()941 List<Rect> getSystemGestureExclusion() { 942 return mExclusionRects; 943 } 944 945 /** 946 * Sets the system gesture exclusion rects. 947 * 948 * @return {@code true} if anything changed 949 */ setSystemGestureExclusion(List<Rect> exclusionRects)950 boolean setSystemGestureExclusion(List<Rect> exclusionRects) { 951 if (mExclusionRects.equals(exclusionRects)) { 952 return false; 953 } 954 mExclusionRects.clear(); 955 mExclusionRects.addAll(exclusionRects); 956 return true; 957 } 958 isImplicitlyExcludingAllSystemGestures()959 boolean isImplicitlyExcludingAllSystemGestures() { 960 final boolean stickyHideNav = 961 mAttrs.insetsFlags.behavior == BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE 962 && !isRequestedVisible(navigationBars()); 963 return stickyHideNav && mWmService.mConstants.mSystemGestureExcludedByPreQStickyImmersive 964 && mActivityRecord != null && mActivityRecord.mTargetSdk < Build.VERSION_CODES.Q; 965 } 966 setLastExclusionHeights(int side, int requested, int granted)967 void setLastExclusionHeights(int side, int requested, int granted) { 968 boolean changed = mLastGrantedExclusionHeight[side] != granted 969 || mLastRequestedExclusionHeight[side] != requested; 970 971 if (changed) { 972 if (mLastShownChangedReported) { 973 logExclusionRestrictions(side); 974 } 975 976 mLastGrantedExclusionHeight[side] = granted; 977 mLastRequestedExclusionHeight[side] = requested; 978 } 979 } 980 981 /** 982 * Collects all restricted and unrestricted keep-clear areas for this window. 983 * Keep-clear areas are rects that should ideally not be covered by floating windows like Pip. 984 * The system is more careful about restricted ones and may apply restrictions to them, while 985 * the unrestricted ones are considered safe. 986 * 987 * @param outRestricted collection to add restricted keep-clear areas to 988 * @param outUnrestricted collection to add unrestricted keep-clear areas to 989 */ getKeepClearAreas(Collection<Rect> outRestricted, Collection<Rect> outUnrestricted)990 void getKeepClearAreas(Collection<Rect> outRestricted, Collection<Rect> outUnrestricted) { 991 final Matrix tmpMatrix = new Matrix(); 992 final float[] tmpFloat9 = new float[9]; 993 getKeepClearAreas(outRestricted, outUnrestricted, tmpMatrix, tmpFloat9); 994 } 995 996 /** 997 * Collects all restricted and unrestricted keep-clear areas for this window. 998 * Keep-clear areas are rects that should ideally not be covered by floating windows like Pip. 999 * The system is more careful about restricted ones and may apply restrictions to them, while 1000 * the unrestricted ones are considered safe. 1001 * 1002 * @param outRestricted collection to add restricted keep-clear areas to 1003 * @param outUnrestricted collection to add unrestricted keep-clear areas to 1004 * @param tmpMatrix a temporary matrix to be used for transformations 1005 * @param float9 a temporary array of 9 floats 1006 */ getKeepClearAreas(Collection<Rect> outRestricted, Collection<Rect> outUnrestricted, Matrix tmpMatrix, float[] float9)1007 void getKeepClearAreas(Collection<Rect> outRestricted, Collection<Rect> outUnrestricted, 1008 Matrix tmpMatrix, float[] float9) { 1009 outRestricted.addAll(getRectsInScreenSpace(mKeepClearAreas, tmpMatrix, float9)); 1010 outUnrestricted.addAll( 1011 getRectsInScreenSpace(mUnrestrictedKeepClearAreas, tmpMatrix, float9)); 1012 } 1013 1014 /** 1015 * Transforms the given rects from window coordinate space to screen space. 1016 */ getRectsInScreenSpace(List<Rect> rects, Matrix tmpMatrix, float[] float9)1017 List<Rect> getRectsInScreenSpace(List<Rect> rects, Matrix tmpMatrix, float[] float9) { 1018 getTransformationMatrix(float9, tmpMatrix); 1019 1020 final List<Rect> transformedRects = new ArrayList<Rect>(); 1021 final RectF tmpRect = new RectF(); 1022 Rect curr; 1023 for (Rect r : rects) { 1024 tmpRect.set(r); 1025 tmpMatrix.mapRect(tmpRect); 1026 curr = new Rect(); 1027 tmpRect.roundOut(curr); 1028 transformedRects.add(curr); 1029 } 1030 return transformedRects; 1031 } 1032 1033 /** 1034 * Sets the new keep-clear areas for this window. The rects should be defined in window 1035 * coordinate space. 1036 * Keep-clear areas can be restricted or unrestricted, depending on whether the app holds the 1037 * {@link android.Manifest.permission.SET_UNRESTRICTED_KEEP_CLEAR_AREAS} system permission. 1038 * Restricted ones will be handled more carefully by the system. Restrictions may be applied. 1039 * Unrestricted ones are considered safe. The system should move floating windows away from them 1040 * without applying restrictions. 1041 * 1042 * @param restricted the new restricted keep-clear areas for this window 1043 * @param unrestricted the new unrestricted keep-clear areas for this window 1044 * 1045 * @return true if there is a change in the list of keep-clear areas; false otherwise 1046 */ setKeepClearAreas(List<Rect> restricted, List<Rect> unrestricted)1047 boolean setKeepClearAreas(List<Rect> restricted, List<Rect> unrestricted) { 1048 final boolean newRestrictedAreas = !mKeepClearAreas.equals(restricted); 1049 final boolean newUnrestrictedAreas = !mUnrestrictedKeepClearAreas.equals(unrestricted); 1050 if (!newRestrictedAreas && !newUnrestrictedAreas) { 1051 return false; 1052 } 1053 if (newRestrictedAreas) { 1054 mKeepClearAreas.clear(); 1055 mKeepClearAreas.addAll(restricted); 1056 } 1057 1058 if (newUnrestrictedAreas) { 1059 mUnrestrictedKeepClearAreas.clear(); 1060 mUnrestrictedKeepClearAreas.addAll(unrestricted); 1061 } 1062 return true; 1063 } 1064 1065 /** 1066 * Used by {@link android.window.WindowOnBackInvokedDispatcher} to set the callback to be 1067 * called when a back navigation action is initiated. 1068 * @see BackNavigationController 1069 */ setOnBackInvokedCallbackInfo( @ullable OnBackInvokedCallbackInfo callbackInfo)1070 void setOnBackInvokedCallbackInfo( 1071 @Nullable OnBackInvokedCallbackInfo callbackInfo) { 1072 ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "%s: Setting back callback %s", 1073 this, callbackInfo); 1074 mOnBackInvokedCallbackInfo = callbackInfo; 1075 } 1076 1077 @Nullable getOnBackInvokedCallbackInfo()1078 OnBackInvokedCallbackInfo getOnBackInvokedCallbackInfo() { 1079 return mOnBackInvokedCallbackInfo; 1080 } 1081 WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token, WindowState parentWindow, int appOp, WindowManager.LayoutParams a, int viewVisibility, int ownerId, int showUserId, boolean ownerCanAddInternalSystemWindow)1082 WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token, 1083 WindowState parentWindow, int appOp, WindowManager.LayoutParams a, int viewVisibility, 1084 int ownerId, int showUserId, boolean ownerCanAddInternalSystemWindow) { 1085 super(service); 1086 mTmpTransaction = service.mTransactionFactory.get(); 1087 mSession = s; 1088 mClient = c; 1089 mAppOp = appOp; 1090 mToken = token; 1091 mDisplayContent = token.mDisplayContent; 1092 mActivityRecord = mToken.asActivityRecord(); 1093 mOwnerUid = ownerId; 1094 mShowUserId = showUserId; 1095 mOwnerCanAddInternalSystemWindow = ownerCanAddInternalSystemWindow; 1096 mWindowId = new WindowId(this); 1097 mAttrs.copyFrom(a); 1098 mLastSurfaceInsets.set(mAttrs.surfaceInsets); 1099 mViewVisibility = viewVisibility; 1100 mPolicy = mWmService.mPolicy; 1101 mContext = mWmService.mContext; 1102 mForceSeamlesslyRotate = token.mRoundedCornerOverlay; 1103 mLastReportedActivityWindowInfo = Flags.activityWindowInfoFlag() && mActivityRecord != null 1104 ? new ActivityWindowInfo() 1105 : null; 1106 mInputWindowHandle = new InputWindowHandleWrapper(new InputWindowHandle( 1107 mActivityRecord != null 1108 ? mActivityRecord.getInputApplicationHandle(false /* update */) : null, 1109 getDisplayId())); 1110 mInputWindowHandle.setFocusable(false); 1111 mInputWindowHandle.setOwnerPid(s.mPid); 1112 mInputWindowHandle.setOwnerUid(s.mUid); 1113 mInputWindowHandle.setName(getName()); 1114 mInputWindowHandle.setPackageName(mAttrs.packageName); 1115 mInputWindowHandle.setLayoutParamsType(mAttrs.type); 1116 if (!surfaceTrustedOverlay()) { 1117 mInputWindowHandle.setTrustedOverlay(isWindowTrustedOverlay()); 1118 } 1119 if (DEBUG) { 1120 Slog.v(TAG, "Window " + this + " client=" + c.asBinder() 1121 + " token=" + token + " (" + mAttrs.token + ")" + " params=" + a); 1122 } 1123 1124 if (mAttrs.type >= FIRST_SUB_WINDOW && mAttrs.type <= LAST_SUB_WINDOW) { 1125 // The multiplier here is to reserve space for multiple 1126 // windows in the same type layer. 1127 mBaseLayer = mPolicy.getWindowLayerLw(parentWindow) 1128 * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET; 1129 mSubLayer = mPolicy.getSubWindowLayerFromTypeLw(a.type); 1130 mIsChildWindow = true; 1131 1132 mLayoutAttached = mAttrs.type != 1133 WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; 1134 mIsImWindow = parentWindow.mAttrs.type == TYPE_INPUT_METHOD 1135 || parentWindow.mAttrs.type == TYPE_INPUT_METHOD_DIALOG; 1136 mIsWallpaper = parentWindow.mAttrs.type == TYPE_WALLPAPER; 1137 } else { 1138 // The multiplier here is to reserve space for multiple 1139 // windows in the same type layer. 1140 mBaseLayer = mPolicy.getWindowLayerLw(this) 1141 * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET; 1142 mSubLayer = 0; 1143 mIsChildWindow = false; 1144 mLayoutAttached = false; 1145 mIsImWindow = mAttrs.type == TYPE_INPUT_METHOD 1146 || mAttrs.type == TYPE_INPUT_METHOD_DIALOG; 1147 mIsWallpaper = mAttrs.type == TYPE_WALLPAPER; 1148 } 1149 mIsFloatingLayer = mIsImWindow || mIsWallpaper; 1150 1151 if (mActivityRecord != null && mActivityRecord.mShowForAllUsers) { 1152 // Windows for apps that can show for all users should also show when the device is 1153 // locked. 1154 mAttrs.flags |= FLAG_SHOW_WHEN_LOCKED; 1155 } 1156 1157 mWinAnimator = new WindowStateAnimator(this); 1158 mWinAnimator.mAlpha = a.alpha; 1159 1160 mRequestedWidth = UNSPECIFIED_LENGTH; 1161 mRequestedHeight = UNSPECIFIED_LENGTH; 1162 mLastRequestedWidth = UNSPECIFIED_LENGTH; 1163 mLastRequestedHeight = UNSPECIFIED_LENGTH; 1164 mLayer = 0; 1165 mOverrideScale = mWmService.mAtmService.mCompatModePackages.getCompatScale( 1166 mAttrs.packageName, s.mUid); 1167 updateGlobalScale(); 1168 1169 // Make sure we initial all fields before adding to parentWindow, to prevent exception 1170 // during onDisplayChanged. 1171 if (mIsChildWindow) { 1172 ProtoLog.v(WM_DEBUG_ADD_REMOVE, "Adding %s to %s", this, parentWindow); 1173 parentWindow.addChild(this, sWindowSubLayerComparator); 1174 } 1175 1176 } 1177 1178 @Override setInitialSurfaceControlProperties(SurfaceControl.Builder b)1179 void setInitialSurfaceControlProperties(SurfaceControl.Builder b) { 1180 super.setInitialSurfaceControlProperties(b); 1181 if (surfaceTrustedOverlay() && isWindowTrustedOverlay()) { 1182 getPendingTransaction().setTrustedOverlay(mSurfaceControl, true); 1183 } 1184 if (secureWindowState()) { 1185 getPendingTransaction().setSecure(mSurfaceControl, isSecureLocked()); 1186 } 1187 // All apps should be considered as occluding when computing TrustedPresentation Thresholds. 1188 final boolean canOccludePresentation = !mSession.mCanAddInternalSystemWindow; 1189 getPendingTransaction().setCanOccludePresentation(mSurfaceControl, canOccludePresentation); 1190 } 1191 updateTrustedOverlay()1192 void updateTrustedOverlay() { 1193 mInputWindowHandle.setTrustedOverlay(getPendingTransaction(), mSurfaceControl, 1194 isWindowTrustedOverlay()); 1195 mInputWindowHandle.forceChange(); 1196 } 1197 isWindowTrustedOverlay()1198 boolean isWindowTrustedOverlay() { 1199 return InputMonitor.isTrustedOverlay(mAttrs.type) 1200 || ((mAttrs.privateFlags & PRIVATE_FLAG_TRUSTED_OVERLAY) != 0 1201 && mSession.mCanAddInternalSystemWindow) 1202 || ((mAttrs.privateFlags & PRIVATE_FLAG_SYSTEM_APPLICATION_OVERLAY) != 0 1203 && mSession.mCanCreateSystemApplicationOverlay); 1204 } 1205 getTouchOcclusionMode()1206 int getTouchOcclusionMode() { 1207 if (WindowManager.LayoutParams.isSystemAlertWindowType(mAttrs.type)) { 1208 return TouchOcclusionMode.USE_OPACITY; 1209 } 1210 if (isAnimating(PARENTS | TRANSITION, ANIMATION_TYPE_ALL) || inTransition()) { 1211 return TouchOcclusionMode.USE_OPACITY; 1212 } 1213 return TouchOcclusionMode.BLOCK_UNTRUSTED; 1214 } 1215 updateGlobalScale()1216 void updateGlobalScale() { 1217 if (hasCompatScale()) { 1218 mCompatScale = (mOverrideScale == 1f || mToken.hasSizeCompatBounds()) 1219 ? mToken.getCompatScale() 1220 : 1f; 1221 mGlobalScale = mCompatScale * mOverrideScale; 1222 mInvGlobalScale = 1f / mGlobalScale; 1223 return; 1224 } 1225 1226 mGlobalScale = mInvGlobalScale = mCompatScale = 1f; 1227 } 1228 getCompatScaleForClient()1229 float getCompatScaleForClient() { 1230 // If this window in the size compat mode. The scaling is fully controlled at the server 1231 // side. The client doesn't need to take it into account. 1232 return mToken.hasSizeCompatBounds() ? 1f : mCompatScale; 1233 } 1234 1235 /** 1236 * @return {@code true} if the application runs in size compatibility mode or has an app level 1237 * scaling override set. 1238 * @see CompatModePackages#getCompatScale 1239 * @see android.content.res.CompatibilityInfo#supportsScreen 1240 * @see ActivityRecord#hasSizeCompatBounds() 1241 */ hasCompatScale()1242 boolean hasCompatScale() { 1243 if (mAttrs.type == TYPE_APPLICATION_STARTING) { 1244 // Exclude starting window because it is not displayed by the application. 1245 return false; 1246 } 1247 if (mWmService.mAtmService.mCompatModePackages.useLegacyScreenCompatMode( 1248 mSession.mProcess.mInfo.packageName)) { 1249 return true; 1250 } 1251 return mActivityRecord != null && mActivityRecord.hasSizeCompatBounds() 1252 || mOverrideScale != 1f; 1253 } 1254 1255 /** 1256 * Returns whether this {@link WindowState} has been considered for drawing by its parent. 1257 */ getDrawnStateEvaluated()1258 boolean getDrawnStateEvaluated() { 1259 return mDrawnStateEvaluated; 1260 } 1261 1262 /** 1263 * Sets whether this {@link WindowState} has been considered for drawing by its parent. Should 1264 * be cleared when detached from parent. 1265 */ setDrawnStateEvaluated(boolean evaluated)1266 void setDrawnStateEvaluated(boolean evaluated) { 1267 mDrawnStateEvaluated = evaluated; 1268 } 1269 1270 @Override onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent)1271 void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) { 1272 super.onParentChanged(newParent, oldParent); 1273 setDrawnStateEvaluated(false /*evaluated*/); 1274 1275 getDisplayContent().reapplyMagnificationSpec(); 1276 } 1277 1278 /** Returns the uid of the app that owns this window. */ getOwningUid()1279 int getOwningUid() { 1280 return mOwnerUid; 1281 } 1282 1283 @Override getOwningPackage()1284 public String getOwningPackage() { 1285 return mAttrs.packageName; 1286 } 1287 1288 @Override canAddInternalSystemWindow()1289 public boolean canAddInternalSystemWindow() { 1290 return mOwnerCanAddInternalSystemWindow; 1291 } 1292 skipLayout()1293 boolean skipLayout() { 1294 // Skip layout of the window when in transition to pip mode. 1295 return mActivityRecord != null && mActivityRecord.mWaitForEnteringPinnedMode; 1296 } 1297 setFrames(ClientWindowFrames clientWindowFrames, int requestedWidth, int requestedHeight)1298 void setFrames(ClientWindowFrames clientWindowFrames, int requestedWidth, int requestedHeight) { 1299 final WindowFrames windowFrames = mWindowFrames; 1300 mTmpRect.set(windowFrames.mParentFrame); 1301 1302 windowFrames.mDisplayFrame.set(clientWindowFrames.displayFrame); 1303 windowFrames.mParentFrame.set(clientWindowFrames.parentFrame); 1304 windowFrames.mFrame.set(clientWindowFrames.frame); 1305 1306 windowFrames.mCompatFrame.set(windowFrames.mFrame); 1307 if (mInvGlobalScale != 1f) { 1308 // Also, the scaled frame that we report to the app needs to be adjusted to be in 1309 // its coordinate space. 1310 windowFrames.mCompatFrame.scale(mInvGlobalScale); 1311 } 1312 windowFrames.setParentFrameWasClippedByDisplayCutout( 1313 clientWindowFrames.isParentFrameClippedByDisplayCutout); 1314 1315 // Calculate relative frame 1316 windowFrames.mRelFrame.set(windowFrames.mFrame); 1317 WindowContainer<?> parent = getParent(); 1318 int parentLeft = 0; 1319 int parentTop = 0; 1320 if (mIsChildWindow) { 1321 parentLeft = ((WindowState) parent).mWindowFrames.mFrame.left; 1322 parentTop = ((WindowState) parent).mWindowFrames.mFrame.top; 1323 } else if (parent != null) { 1324 final Rect parentBounds = parent.getBounds(); 1325 parentLeft = parentBounds.left; 1326 parentTop = parentBounds.top; 1327 } 1328 windowFrames.mRelFrame.offsetTo(windowFrames.mFrame.left - parentLeft, 1329 windowFrames.mFrame.top - parentTop); 1330 1331 if (requestedWidth != mLastRequestedWidth || requestedHeight != mLastRequestedHeight 1332 || !mTmpRect.equals(windowFrames.mParentFrame)) { 1333 mLastRequestedWidth = requestedWidth; 1334 mLastRequestedHeight = requestedHeight; 1335 windowFrames.setContentChanged(true); 1336 } 1337 1338 if (!windowFrames.mFrame.equals(windowFrames.mLastFrame) 1339 || !windowFrames.mRelFrame.equals(windowFrames.mLastRelFrame)) { 1340 mWmService.mFrameChangingWindows.add(this); 1341 } 1342 1343 if (mAttrs.type == TYPE_DOCK_DIVIDER) { 1344 if (!windowFrames.mFrame.equals(windowFrames.mLastFrame)) { 1345 mMovedByResize = true; 1346 } 1347 } 1348 1349 if (mIsWallpaper) { 1350 final Rect lastFrame = windowFrames.mLastFrame; 1351 final Rect frame = windowFrames.mFrame; 1352 if (lastFrame.width() != frame.width() || lastFrame.height() != frame.height()) { 1353 mDisplayContent.mWallpaperController.updateWallpaperOffset(this, false /* sync */); 1354 } 1355 } 1356 1357 updateSourceFrame(windowFrames.mFrame); 1358 1359 if (mActivityRecord != null && !mIsChildWindow) { 1360 mActivityRecord.layoutLetterboxIfNeeded(this); 1361 } 1362 mSurfacePlacementNeeded = true; 1363 mHaveFrame = true; 1364 } 1365 updateSourceFrame(Rect winFrame)1366 void updateSourceFrame(Rect winFrame) { 1367 if (!hasInsetsSourceProvider()) { 1368 // This window doesn't provide any insets. 1369 return; 1370 } 1371 if (mGivenInsetsPending) { 1372 // The given insets are pending, and they are not reliable for now. The source frame 1373 // should be updated after the new given insets are sent to window manager. 1374 return; 1375 } 1376 final SparseArray<InsetsSourceProvider> providers = getInsetsSourceProviders(); 1377 for (int i = providers.size() - 1; i >= 0; i--) { 1378 providers.valueAt(i).updateSourceFrame(winFrame); 1379 } 1380 } 1381 1382 @Override getBounds()1383 public Rect getBounds() { 1384 // The window bounds are used for layout in screen coordinates. If the token has bounds for 1385 // size compatibility mode, its configuration bounds are app based coordinates which should 1386 // not be used for layout. 1387 return mToken.hasSizeCompatBounds() ? mToken.getBounds() : super.getBounds(); 1388 } 1389 1390 /** Retrieves the current frame of the window that the application sees. */ getFrame()1391 Rect getFrame() { 1392 return mWindowFrames.mFrame; 1393 } 1394 1395 /** Accessor for testing */ getRelativeFrame()1396 Rect getRelativeFrame() { 1397 return mWindowFrames.mRelFrame; 1398 } 1399 1400 /** 1401 * Gets the frame that excludes the area of side insets according to the layout parameter from 1402 * {@link WindowManager.LayoutParams#setFitInsetsSides}. 1403 */ getDisplayFrame()1404 Rect getDisplayFrame() { 1405 return mWindowFrames.mDisplayFrame; 1406 } 1407 getParentFrame()1408 Rect getParentFrame() { 1409 return mWindowFrames.mParentFrame; 1410 } 1411 getAttrs()1412 WindowManager.LayoutParams getAttrs() { 1413 return mAttrs; 1414 } 1415 1416 /** Retrieves the flags used to disable system UI functions. */ getDisableFlags()1417 int getDisableFlags() { 1418 return mDisableFlags; 1419 } 1420 1421 @Override getBaseType()1422 public int getBaseType() { 1423 return getTopParentWindow().mAttrs.type; 1424 } 1425 setReportResizeHints()1426 boolean setReportResizeHints() { 1427 return mWindowFrames.setReportResizeHints(); 1428 } 1429 1430 /** 1431 * Adds the window to the resizing list if any of the parameters we use to track the window 1432 * dimensions or insets have changed. 1433 */ updateResizingWindowIfNeeded()1434 void updateResizingWindowIfNeeded() { 1435 final boolean insetsChanged = mWindowFrames.hasInsetsChanged(); 1436 if ((!mHasSurface || getDisplayContent().mLayoutSeq != mLayoutSeq || isGoneForLayout()) 1437 && !insetsChanged) { 1438 return; 1439 } 1440 1441 final WindowStateAnimator winAnimator = mWinAnimator; 1442 final boolean didFrameInsetsChange = setReportResizeHints(); 1443 // The latest configuration will be returned by the out parameter of relayout, so it is 1444 // unnecessary to report resize if this window is running relayout. 1445 final boolean configChanged = !mInRelayout && !isLastConfigReportedToClient(); 1446 if (DEBUG_CONFIGURATION && configChanged) { 1447 Slog.v(TAG_WM, "Win " + this + " config changed: " + getConfiguration()); 1448 } 1449 1450 final boolean dragResizingChanged = !mDragResizingChangeReported && isDragResizeChanged(); 1451 final boolean attachedFrameChanged = mLayoutAttached && getParentWindow().frameChanged(); 1452 1453 if (DEBUG) { 1454 Slog.v(TAG_WM, "Resizing " + this + ": configChanged=" + configChanged 1455 + " last=" + mWindowFrames.mLastFrame + " frame=" + mWindowFrames.mFrame); 1456 } 1457 1458 final boolean contentChanged = didFrameInsetsChange || configChanged 1459 || dragResizingChanged || attachedFrameChanged; 1460 // Cancel unchanged non-sync-buffer redraw request to avoid unnecessary reportResized(). 1461 if (!contentChanged && !mRedrawForSyncReported && mPrepareSyncSeqId <= 0 1462 && mDrawHandlers.isEmpty()) { 1463 mRedrawForSyncReported = true; 1464 } 1465 1466 // Add a window that is using blastSync to the resizing list if it hasn't been reported 1467 // already. This because the window is waiting on a finishDrawing from the client. 1468 if (contentChanged || insetsChanged || shouldSendRedrawForSync()) { 1469 ProtoLog.v(WM_DEBUG_RESIZE, 1470 "Resize reasons for w=%s: %s configChanged=%b didFrameInsetsChange=%b", 1471 this, mWindowFrames.getInsetsChangedInfo(), 1472 configChanged, didFrameInsetsChange); 1473 1474 consumeInsetsChange(); 1475 onResizeHandled(); 1476 mWmService.makeWindowFreezingScreenIfNeededLocked(this); 1477 1478 // Reset the drawn state if the window need to redraw for the change, so the transition 1479 // can wait until it has finished drawing to start. 1480 if ((configChanged || getOrientationChanging() || dragResizingChanged) 1481 && isVisibleRequested()) { 1482 winAnimator.mDrawState = DRAW_PENDING; 1483 if (mActivityRecord != null) { 1484 mActivityRecord.clearAllDrawn(); 1485 if (mAttrs.type == TYPE_APPLICATION_STARTING 1486 && mActivityRecord.mStartingData != null) { 1487 mActivityRecord.mStartingData.mIsDisplayed = false; 1488 } 1489 } 1490 } 1491 if (!mWmService.mResizingWindows.contains(this)) { 1492 ProtoLog.v(WM_DEBUG_RESIZE, "Resizing window %s", this); 1493 mWmService.mResizingWindows.add(this); 1494 } 1495 } else if (getOrientationChanging()) { 1496 if (isDrawn()) { 1497 ProtoLog.v(WM_DEBUG_ORIENTATION, 1498 "Orientation not waiting for draw in %s, surfaceController %s", this, 1499 winAnimator.mSurfaceController); 1500 setOrientationChanging(false); 1501 mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 1502 - mWmService.mDisplayFreezeTime); 1503 } 1504 } 1505 } 1506 frameChanged()1507 private boolean frameChanged() { 1508 return !mWindowFrames.mFrame.equals(mWindowFrames.mLastFrame); 1509 } 1510 getOrientationChanging()1511 boolean getOrientationChanging() { 1512 if (mTransitionController.isShellTransitionsEnabled()) { 1513 // Shell transition doesn't use the methods for display frozen state. 1514 return false; 1515 } 1516 // In addition to the local state flag, we must also consider the difference in the last 1517 // reported configuration vs. the current state. If the client code has not been informed of 1518 // the change, logic dependent on having finished processing the orientation, such as 1519 // unfreezing, could be improperly triggered. 1520 // TODO(b/62846907): Checking against {@link mLastReportedConfiguration} could be flaky as 1521 // this is not necessarily what the client has processed yet. Find a 1522 // better indicator consistent with the client. 1523 return (mOrientationChanging || (isVisible() 1524 && getConfiguration().orientation != getLastReportedConfiguration().orientation)) 1525 && !mSeamlesslyRotated 1526 && !mOrientationChangeTimedOut; 1527 } 1528 setOrientationChanging(boolean changing)1529 void setOrientationChanging(boolean changing) { 1530 mOrientationChangeTimedOut = false; 1531 if (mOrientationChanging == changing) { 1532 return; 1533 } 1534 mOrientationChanging = changing; 1535 if (changing) { 1536 mLastFreezeDuration = 0; 1537 if (mWmService.mRoot.mOrientationChangeComplete 1538 && mDisplayContent.shouldSyncRotationChange(this)) { 1539 mWmService.mRoot.mOrientationChangeComplete = false; 1540 } 1541 } else { 1542 // The orientation change is completed. If it was hidden by the animation, reshow it. 1543 mDisplayContent.finishAsyncRotation(mToken); 1544 } 1545 } 1546 orientationChangeTimedOut()1547 void orientationChangeTimedOut() { 1548 mOrientationChangeTimedOut = true; 1549 } 1550 1551 @Override onDisplayChanged(DisplayContent dc)1552 void onDisplayChanged(DisplayContent dc) { 1553 if (dc != null && mDisplayContent != null && dc != mDisplayContent 1554 && mDisplayContent.getImeInputTarget() == this) { 1555 dc.updateImeInputAndControlTarget(getImeInputTarget()); 1556 mDisplayContent.setImeInputTarget(null); 1557 } 1558 super.onDisplayChanged(dc); 1559 // Window was not laid out for this display yet, so make sure mLayoutSeq does not match. 1560 if (dc != null && mInputWindowHandle.getDisplayId() != dc.getDisplayId()) { 1561 mLayoutSeq = dc.mLayoutSeq - 1; 1562 mInputWindowHandle.setDisplayId(dc.getDisplayId()); 1563 } 1564 } 1565 1566 /** @return The display frames in use by this window. */ getDisplayFrames(DisplayFrames originalFrames)1567 DisplayFrames getDisplayFrames(DisplayFrames originalFrames) { 1568 final DisplayFrames displayFrames = mToken.getFixedRotationTransformDisplayFrames(); 1569 if (displayFrames != null) { 1570 return displayFrames; 1571 } 1572 return originalFrames; 1573 } 1574 getDisplayInfo()1575 DisplayInfo getDisplayInfo() { 1576 final DisplayInfo displayInfo = mToken.getFixedRotationTransformDisplayInfo(); 1577 if (displayInfo != null) { 1578 return displayInfo; 1579 } 1580 return getDisplayContent().getDisplayInfo(); 1581 } 1582 1583 @Override getMaxBounds()1584 public Rect getMaxBounds() { 1585 final Rect maxBounds = mToken.getFixedRotationTransformMaxBounds(); 1586 if (maxBounds != null) { 1587 return maxBounds; 1588 } 1589 return super.getMaxBounds(); 1590 } 1591 1592 /** 1593 * See {@link WindowState#getInsetsState(boolean)} 1594 */ getInsetsState()1595 InsetsState getInsetsState() { 1596 return getInsetsState(false); 1597 } 1598 1599 /** 1600 * Returns the insets state for the window. Its sources may be the copies with visibility 1601 * modification according to the state of transient bars. 1602 * This is to get the insets for a window layout on the screen. If the window is not there, use 1603 * the {@link InsetsPolicy#getInsetsForWindowMetrics} to get insets instead. 1604 * @param includeTransient whether or not the transient types should be included in the 1605 * insets state. 1606 */ getInsetsState(boolean includeTransient)1607 InsetsState getInsetsState(boolean includeTransient) { 1608 final InsetsState rotatedState = mToken.getFixedRotationTransformInsetsState(); 1609 final InsetsPolicy insetsPolicy = getDisplayContent().getInsetsPolicy(); 1610 if (rotatedState != null) { 1611 return insetsPolicy.adjustInsetsForWindow(this, rotatedState); 1612 } 1613 final InsetsState rawInsetsState = 1614 mFrozenInsetsState != null ? mFrozenInsetsState : getMergedInsetsState(); 1615 final InsetsState insetsStateForWindow = insetsPolicy.enforceInsetsPolicyForTarget( 1616 mAttrs, getWindowingMode(), isAlwaysOnTop(), rawInsetsState); 1617 return insetsPolicy.adjustInsetsForWindow(this, insetsStateForWindow, 1618 includeTransient); 1619 } 1620 getMergedInsetsState()1621 private InsetsState getMergedInsetsState() { 1622 final InsetsState globalInsetsState = mAttrs.receiveInsetsIgnoringZOrder 1623 ? getDisplayContent().getInsetsStateController().getRawInsetsState() 1624 : mAboveInsetsState; 1625 if (mMergedLocalInsetsSources == null) { 1626 return globalInsetsState; 1627 } 1628 1629 final InsetsState mergedInsetsState = new InsetsState(globalInsetsState); 1630 for (int i = 0; i < mMergedLocalInsetsSources.size(); i++) { 1631 mergedInsetsState.addSource(mMergedLocalInsetsSources.valueAt(i)); 1632 } 1633 return mergedInsetsState; 1634 } 1635 1636 /** 1637 * Returns the insets state for the client and scales the frames if the client is in the size 1638 * compatible mode. 1639 */ getCompatInsetsState()1640 InsetsState getCompatInsetsState() { 1641 InsetsState state = getInsetsState(); 1642 if (mInvGlobalScale != 1f) { 1643 state = new InsetsState(state, true); 1644 state.scale(mInvGlobalScale); 1645 } 1646 return state; 1647 } 1648 1649 /** 1650 * Returns the insets state for the window and applies the requested visibility. 1651 */ getInsetsStateWithVisibilityOverride()1652 InsetsState getInsetsStateWithVisibilityOverride() { 1653 final InsetsState state = new InsetsState(getInsetsState(), true /* copySources */); 1654 for (int i = state.sourceSize() - 1; i >= 0; i--) { 1655 final InsetsSource source = state.sourceAt(i); 1656 final boolean requestedVisible = isRequestedVisible(source.getType()); 1657 if (source.isVisible() != requestedVisible) { 1658 source.setVisible(requestedVisible); 1659 } 1660 } 1661 return state; 1662 } 1663 1664 @Override getDisplayId()1665 public int getDisplayId() { 1666 final DisplayContent displayContent = getDisplayContent(); 1667 if (displayContent == null) { 1668 return Display.INVALID_DISPLAY; 1669 } 1670 return displayContent.getDisplayId(); 1671 } 1672 1673 @Override getWindowState()1674 public WindowState getWindowState() { 1675 return this; 1676 } 1677 1678 @Override getWindowToken()1679 public IBinder getWindowToken() { 1680 return mClient.asBinder(); 1681 } 1682 1683 @Override getPid()1684 public int getPid() { 1685 return mSession.mPid; 1686 } 1687 1688 @Override getUid()1689 public int getUid() { 1690 return mSession.mUid; 1691 } 1692 getTask()1693 Task getTask() { 1694 return mActivityRecord != null ? mActivityRecord.getTask() : null; 1695 } 1696 getTaskFragment()1697 @Nullable TaskFragment getTaskFragment() { 1698 return mActivityRecord != null ? mActivityRecord.getTaskFragment() : null; 1699 } 1700 getRootTask()1701 @Nullable Task getRootTask() { 1702 final Task task = getTask(); 1703 if (task != null) { 1704 return task.getRootTask(); 1705 } 1706 // Some system windows (e.g. "Power off" dialog) don't have a task, but we would still 1707 // associate them with some root task to enable dimming. 1708 final DisplayContent dc = getDisplayContent(); 1709 return mAttrs.type >= FIRST_SYSTEM_WINDOW 1710 && dc != null ? dc.getDefaultTaskDisplayArea().getRootHomeTask() : null; 1711 } 1712 1713 /** 1714 * Retrieves the visible bounds of the window. 1715 * @param bounds The rect which gets the bounds. 1716 */ getVisibleBounds(Rect bounds)1717 void getVisibleBounds(Rect bounds) { 1718 final Task task = getTask(); 1719 boolean intersectWithRootTaskBounds = task != null && task.cropWindowsToRootTaskBounds(); 1720 bounds.setEmpty(); 1721 mTmpRect.setEmpty(); 1722 if (intersectWithRootTaskBounds) { 1723 final Task rootTask = task.getRootTask(); 1724 if (rootTask != null) { 1725 rootTask.getDimBounds(mTmpRect); 1726 } else { 1727 intersectWithRootTaskBounds = false; 1728 } 1729 } 1730 1731 bounds.set(mWindowFrames.mFrame); 1732 bounds.inset(getInsetsStateWithVisibilityOverride().calculateVisibleInsets( 1733 bounds, mAttrs.type, getActivityType(), mAttrs.softInputMode, mAttrs.flags)); 1734 if (intersectWithRootTaskBounds) { 1735 bounds.intersect(mTmpRect); 1736 } 1737 } 1738 getInputDispatchingTimeoutMillis()1739 public long getInputDispatchingTimeoutMillis() { 1740 return mActivityRecord != null 1741 ? mActivityRecord.mInputDispatchingTimeoutMillis 1742 : DEFAULT_DISPATCHING_TIMEOUT_MILLIS; 1743 } 1744 getCreateTime()1745 long getCreateTime() { 1746 return mCreateTime; 1747 } 1748 1749 /** 1750 * Returns true if, at any point, the application token associated with this window has actually 1751 * displayed any windows. This is most useful with the "starting up" window to determine if any 1752 * windows were displayed when it is closed. 1753 * 1754 * @return {@code true} if one or more windows have been displayed, else false. 1755 */ hasAppShownWindows()1756 boolean hasAppShownWindows() { 1757 return mActivityRecord != null && (mActivityRecord.firstWindowDrawn 1758 || mActivityRecord.isStartingWindowDisplayed()); 1759 } 1760 1761 @Override hasContentToDisplay()1762 boolean hasContentToDisplay() { 1763 if (!mAppFreezing && isDrawn() && (mViewVisibility == View.VISIBLE 1764 || (isAnimating(TRANSITION | PARENTS) 1765 && !getDisplayContent().mAppTransition.isTransitionSet()))) { 1766 return true; 1767 } 1768 1769 return super.hasContentToDisplay(); 1770 } 1771 isVisibleByPolicyOrInsets()1772 private boolean isVisibleByPolicyOrInsets() { 1773 return isVisibleByPolicy() 1774 // If we don't have a provider, this window isn't used as a window generating 1775 // insets, so nobody can hide it over the inset APIs. 1776 && (mControllableInsetProvider == null 1777 || mControllableInsetProvider.isClientVisible()); 1778 } 1779 1780 @Override isVisible()1781 boolean isVisible() { 1782 return wouldBeVisibleIfPolicyIgnored() && isVisibleByPolicyOrInsets(); 1783 } 1784 1785 @Override isVisibleRequested()1786 boolean isVisibleRequested() { 1787 final boolean localVisibleRequested = 1788 wouldBeVisibleRequestedIfPolicyIgnored() && isVisibleByPolicyOrInsets(); 1789 if (localVisibleRequested && shouldCheckTokenVisibleRequested()) { 1790 return mToken.isVisibleRequested(); 1791 } 1792 return localVisibleRequested; 1793 } 1794 1795 /** 1796 * Returns {@code true} if {@link WindowToken#isVisibleRequested()} should be considered 1797 * before dispatching the latest configuration. Currently only {@link 1798 * ActivityRecord#isVisibleRequested()} and {@link WallpaperWindowToken#isVisibleRequested()} 1799 * implement explicit visible-requested. 1800 */ shouldCheckTokenVisibleRequested()1801 boolean shouldCheckTokenVisibleRequested() { 1802 return mActivityRecord != null || mToken.asWallpaperToken() != null; 1803 } 1804 1805 /** 1806 * Ensures that all the policy visibility bits are set. 1807 * @return {@code true} if all flags about visiblity are set 1808 */ isVisibleByPolicy()1809 boolean isVisibleByPolicy() { 1810 return (mPolicyVisibility & POLICY_VISIBILITY_ALL) == POLICY_VISIBILITY_ALL; 1811 } 1812 providesDisplayDecorInsets()1813 boolean providesDisplayDecorInsets() { 1814 if (mInsetsSourceProviders == null) { 1815 return false; 1816 } 1817 final @InsetsType int decorInsetsTypes = 1818 mWmService.mConfigTypes | mWmService.mOverrideConfigTypes; 1819 for (int i = mInsetsSourceProviders.size() - 1; i >= 0; i--) { 1820 final InsetsSource source = mInsetsSourceProviders.valueAt(i).getSource(); 1821 if ((source.getType() & decorInsetsTypes) != 0) { 1822 return true; 1823 } 1824 } 1825 return false; 1826 } 1827 clearPolicyVisibilityFlag(int policyVisibilityFlag)1828 void clearPolicyVisibilityFlag(int policyVisibilityFlag) { 1829 mPolicyVisibility &= ~policyVisibilityFlag; 1830 mWmService.scheduleAnimationLocked(); 1831 } 1832 setPolicyVisibilityFlag(int policyVisibilityFlag)1833 void setPolicyVisibilityFlag(int policyVisibilityFlag) { 1834 mPolicyVisibility |= policyVisibilityFlag; 1835 mWmService.scheduleAnimationLocked(); 1836 } 1837 isLegacyPolicyVisibility()1838 private boolean isLegacyPolicyVisibility() { 1839 return (mPolicyVisibility & LEGACY_POLICY_VISIBILITY) != 0; 1840 } 1841 1842 /** 1843 * @return {@code true} if the window would be visible if we'd ignore policy visibility, 1844 * {@code false} otherwise. 1845 */ wouldBeVisibleIfPolicyIgnored()1846 boolean wouldBeVisibleIfPolicyIgnored() { 1847 if (!mHasSurface || isParentWindowHidden() || mAnimatingExit || mDestroying) { 1848 return false; 1849 } 1850 final boolean isWallpaper = mToken.asWallpaperToken() != null; 1851 return !isWallpaper || mToken.isVisible(); 1852 } 1853 wouldBeVisibleRequestedIfPolicyIgnored()1854 private boolean wouldBeVisibleRequestedIfPolicyIgnored() { 1855 final WindowState parent = getParentWindow(); 1856 final boolean isParentHiddenRequested = parent != null && !parent.isVisibleRequested(); 1857 if (isParentHiddenRequested || mAnimatingExit || mDestroying) { 1858 return false; 1859 } 1860 final boolean isWallpaper = mToken.asWallpaperToken() != null; 1861 return !isWallpaper || mToken.isVisibleRequested(); 1862 } 1863 1864 /** 1865 * The same as isVisible(), but follows the current hidden state of the associated app token, 1866 * not the pending requested hidden state. 1867 */ isVisibleNow()1868 boolean isVisibleNow() { 1869 return (mToken.isVisible() || mAttrs.type == TYPE_APPLICATION_STARTING) 1870 && isVisible(); 1871 } 1872 1873 /** 1874 * Can this window possibly be a drag/drop target? The test here is 1875 * a combination of the above "visible now" with the check that the 1876 * Input Manager uses when discarding windows from input consideration. 1877 */ isPotentialDragTarget(boolean targetInterceptsGlobalDrag)1878 boolean isPotentialDragTarget(boolean targetInterceptsGlobalDrag) { 1879 return (targetInterceptsGlobalDrag || isVisibleNow()) && !mRemoved 1880 && mInputChannel != null && mInputWindowHandle != null; 1881 } 1882 1883 /** 1884 * Is this window capable of being visible (policy and content), in a visible part of the 1885 * hierarchy, and, if an activity window, the activity is visible-requested. Note, this means 1886 * if the activity is going-away, this will be {@code false} even when the window is visible. 1887 * 1888 * The 'adding' part refers to the period of time between IWindowSession.add() and the first 1889 * relayout() -- which, for activities, is the same as visibleRequested. 1890 * 1891 * TODO(b/206005136): This is very similar to isVisibleRequested(). Investigate merging them. 1892 */ isVisibleRequestedOrAdding()1893 boolean isVisibleRequestedOrAdding() { 1894 final ActivityRecord atoken = mActivityRecord; 1895 return (mHasSurface || (!mRelayoutCalled && mViewVisibility == View.VISIBLE)) 1896 && isVisibleByPolicy() && !isParentWindowHidden() 1897 && (atoken == null || atoken.isVisibleRequested()) 1898 && !mAnimatingExit && !mDestroying; 1899 } 1900 1901 /** 1902 * Is this window currently on-screen? It is on-screen either if it 1903 * is visible or it is currently running an animation before no longer 1904 * being visible. 1905 */ isOnScreen()1906 boolean isOnScreen() { 1907 if (!mHasSurface || mDestroying || !isVisibleByPolicy()) { 1908 return false; 1909 } 1910 final ActivityRecord atoken = mActivityRecord; 1911 if (atoken != null) { 1912 final boolean isVisible = isStartingWindowAssociatedToTask() 1913 ? mStartingData.mAssociatedTask.isVisible() : atoken.isVisible(); 1914 return ((!isParentWindowHidden() && isVisible) 1915 || isAnimationRunningSelfOrParent()); 1916 } 1917 final WallpaperWindowToken wtoken = mToken.asWallpaperToken(); 1918 if (wtoken != null) { 1919 return !isParentWindowHidden() && wtoken.isVisible(); 1920 } 1921 return !isParentWindowHidden() || isAnimating(TRANSITION | PARENTS); 1922 } 1923 isDreamWindow()1924 boolean isDreamWindow() { 1925 return mActivityRecord != null 1926 && mActivityRecord.getActivityType() == ACTIVITY_TYPE_DREAM; 1927 } 1928 isSecureLocked()1929 boolean isSecureLocked() { 1930 if (mWmService.getDisableSecureWindows()) { 1931 return false; 1932 } 1933 1934 if ((mAttrs.flags & WindowManager.LayoutParams.FLAG_SECURE) != 0) { 1935 return true; 1936 } 1937 1938 // block screen capture to protect sensitive notifications or content on the screen. 1939 if (mWmService.mSensitiveContentPackages.shouldBlockScreenCaptureForApp( 1940 getOwningPackage(), getOwningUid(), getWindowToken())) { 1941 return true; 1942 } 1943 1944 return !DevicePolicyCache.getInstance().isScreenCaptureAllowed(mShowUserId); 1945 } 1946 1947 /** 1948 * Whether this window's drawn state might affect the drawn states of the app token. 1949 * 1950 * @return true if the window should be considered while evaluating allDrawn flags. 1951 */ mightAffectAllDrawn()1952 boolean mightAffectAllDrawn() { 1953 final boolean isAppType = mWinAnimator.mAttrType == TYPE_BASE_APPLICATION 1954 || mWinAnimator.mAttrType == TYPE_DRAWN_APPLICATION; 1955 return (isOnScreen() || isAppType) && !mAnimatingExit && !mDestroying; 1956 } 1957 1958 /** 1959 * Whether this window is "interesting" when evaluating allDrawn. If it's interesting, 1960 * it must be drawn before allDrawn can become true. 1961 */ isInteresting()1962 boolean isInteresting() { 1963 final RecentsAnimationController recentsAnimationController = 1964 mWmService.getRecentsAnimationController(); 1965 return mActivityRecord != null 1966 && (!mActivityRecord.isFreezingScreen() || !mAppFreezing) 1967 && mViewVisibility == View.VISIBLE 1968 && (recentsAnimationController == null 1969 || recentsAnimationController.isInterestingForAllDrawn(this)); 1970 } 1971 1972 /** 1973 * Like isOnScreen(), but we don't return true if the window is part 1974 * of a transition that has not yet been started. 1975 */ isReadyForDisplay()1976 boolean isReadyForDisplay() { 1977 final boolean parentAndClientVisible = !isParentWindowHidden() 1978 && mViewVisibility == View.VISIBLE && mToken.isVisible(); 1979 return mHasSurface && isVisibleByPolicy() && !mDestroying 1980 && (parentAndClientVisible || isAnimating(TRANSITION | PARENTS)); 1981 } 1982 isFullyTransparent()1983 boolean isFullyTransparent() { 1984 return mAttrs.alpha == 0f; 1985 } 1986 1987 /** 1988 * @return Whether the window can affect SystemUI flags, meaning that SystemUI (system bars, 1989 * for example) will be affected by the flags specified in this window. This is the 1990 * case when the surface is on screen but not exiting. 1991 */ canAffectSystemUiFlags()1992 boolean canAffectSystemUiFlags() { 1993 if (isFullyTransparent()) { 1994 return false; 1995 } 1996 if (mActivityRecord == null) { 1997 final boolean shown = mWinAnimator.getShown(); 1998 final boolean exiting = mAnimatingExit || mDestroying; 1999 return shown && !exiting; 2000 } else { 2001 return mActivityRecord.canAffectSystemUiFlags() 2002 // Do not let snapshot window control the bar 2003 && (mAttrs.type != TYPE_APPLICATION_STARTING 2004 || !(mStartingData instanceof SnapshotStartingData)); 2005 } 2006 } 2007 2008 /** 2009 * Like isOnScreen, but returns false if the surface hasn't yet 2010 * been drawn. 2011 */ isDisplayed()2012 boolean isDisplayed() { 2013 final ActivityRecord atoken = mActivityRecord; 2014 return isDrawn() && isVisibleByPolicy() 2015 && ((!isParentWindowHidden() && (atoken == null || atoken.isVisibleRequested())) 2016 || isAnimationRunningSelfOrParent()); 2017 } 2018 2019 /** 2020 * Return true if this window or its app token is currently animating. 2021 */ 2022 @Override isAnimatingLw()2023 public boolean isAnimatingLw() { 2024 return isAnimating(TRANSITION | PARENTS); 2025 } 2026 2027 /** Returns {@code true} if this window considered to be gone for purposes of layout. */ isGoneForLayout()2028 boolean isGoneForLayout() { 2029 final ActivityRecord atoken = mActivityRecord; 2030 return mViewVisibility == View.GONE 2031 || !mRelayoutCalled 2032 // We can't check isVisible here because it will also check the client visibility 2033 // for WindowTokens. Even if the client is not visible, we still need to perform 2034 // a layout since they can request relayout when client visibility is false. 2035 // TODO (b/157682066) investigate if we can clean up isVisible 2036 || (atoken == null && !(wouldBeVisibleIfPolicyIgnored() && isVisibleByPolicy())) 2037 || (atoken != null && !atoken.isVisibleRequested()) 2038 || isParentWindowGoneForLayout() 2039 || (mAnimatingExit && !isAnimatingLw()) 2040 || mDestroying; 2041 } 2042 2043 /** 2044 * Returns true if the window has a surface that it has drawn a 2045 * complete UI in to. 2046 */ isDrawFinishedLw()2047 public boolean isDrawFinishedLw() { 2048 return mHasSurface && !mDestroying && 2049 (mWinAnimator.mDrawState == COMMIT_DRAW_PENDING 2050 || mWinAnimator.mDrawState == READY_TO_SHOW 2051 || mWinAnimator.mDrawState == HAS_DRAWN); 2052 } 2053 2054 /** 2055 * Returns true if the window has a surface that it has drawn a complete UI in to. Note that 2056 * this is different from {@link #hasDrawn()} in that it also returns true if the window is 2057 * READY_TO_SHOW, but was not yet promoted to HAS_DRAWN. 2058 */ isDrawn()2059 boolean isDrawn() { 2060 return mHasSurface && !mDestroying && 2061 (mWinAnimator.mDrawState == READY_TO_SHOW || mWinAnimator.mDrawState == HAS_DRAWN); 2062 } 2063 2064 /** 2065 * Return true if the window is opaque and fully drawn. This indicates 2066 * it may obscure windows behind it. 2067 */ isOpaqueDrawn()2068 private boolean isOpaqueDrawn() { 2069 // When there is keyguard, wallpaper could be placed over the secure app 2070 // window but invisible. We need to check wallpaper visibility explicitly 2071 // to determine if it's occluding apps. 2072 final boolean isWallpaper = mToken.asWallpaperToken() != null; 2073 return ((!isWallpaper && mAttrs.format == PixelFormat.OPAQUE) 2074 || (isWallpaper && mToken.isVisible())) 2075 && isDrawn() && !isAnimating(TRANSITION | PARENTS); 2076 } 2077 2078 /** @see WindowManagerInternal#waitForAllWindowsDrawn */ requestDrawIfNeeded(List<WindowState> outWaitingForDrawn)2079 void requestDrawIfNeeded(List<WindowState> outWaitingForDrawn) { 2080 if (!isVisible()) { 2081 return; 2082 } 2083 final WallpaperWindowToken wallpaperToken = mToken.asWallpaperToken(); 2084 if (wallpaperToken != null) { 2085 if (wallpaperToken.hasVisibleNotDrawnWallpaper()) { 2086 outWaitingForDrawn.add(this); 2087 } 2088 return; 2089 } 2090 if (mActivityRecord != null) { 2091 if (!mActivityRecord.isVisibleRequested()) return; 2092 if (mActivityRecord.allDrawn) { 2093 // The allDrawn of activity is reset when the visibility is changed to visible, so 2094 // the content should be ready if allDrawn is set. 2095 return; 2096 } 2097 if (mAttrs.type == TYPE_APPLICATION_STARTING) { 2098 if (isDrawn()) { 2099 // Unnecessary to redraw a drawn starting window. 2100 return; 2101 } 2102 } else if (mActivityRecord.mStartingWindow != null) { 2103 // If the activity has an active starting window, there is no need to wait for the 2104 // main window. 2105 return; 2106 } 2107 } else if (!mPolicy.isKeyguardHostWindow(mAttrs)) { 2108 return; 2109 // Always invalidate keyguard host window to make sure it shows the latest content 2110 // because its visibility may not be changed. 2111 } 2112 2113 mWinAnimator.mDrawState = DRAW_PENDING; 2114 // Force add to {@link WindowManagerService#mResizingWindows}. 2115 forceReportingResized(); 2116 outWaitingForDrawn.add(this); 2117 } 2118 2119 @Override onMovedByResize()2120 void onMovedByResize() { 2121 ProtoLog.d(WM_DEBUG_RESIZE, "onMovedByResize: Moving %s", this); 2122 mMovedByResize = true; 2123 super.onMovedByResize(); 2124 } 2125 onAppVisibilityChanged(boolean visible, boolean runningAppAnimation)2126 void onAppVisibilityChanged(boolean visible, boolean runningAppAnimation) { 2127 for (int i = mChildren.size() - 1; i >= 0; --i) { 2128 mChildren.get(i).onAppVisibilityChanged(visible, runningAppAnimation); 2129 } 2130 2131 final boolean isVisibleNow = isVisibleNow(); 2132 if (mAttrs.type == TYPE_APPLICATION_STARTING) { 2133 // Starting window that's exiting will be removed when the animation finishes. 2134 // Mark all relevant flags for that onExitAnimationDone will proceed all the way 2135 // to actually remove it. 2136 if (!visible && isVisibleNow && mActivityRecord.isAnimating(PARENTS | TRANSITION)) { 2137 ProtoLog.d(WM_DEBUG_ANIM, 2138 "Set animatingExit: reason=onAppVisibilityChanged win=%s", this); 2139 mAnimatingExit = true; 2140 mRemoveOnExit = true; 2141 mWindowRemovalAllowed = true; 2142 } 2143 } else if (visible != isVisibleNow) { 2144 // Run exit animation if: 2145 // 1. App visibility and WS visibility are different 2146 // 2. App is not running an animation 2147 // 3. WS is currently visible 2148 if (!runningAppAnimation && isVisibleNow) { 2149 final AccessibilityController accessibilityController = 2150 mWmService.mAccessibilityController; 2151 final int winTransit = TRANSIT_EXIT; 2152 mWinAnimator.applyAnimationLocked(winTransit, false /* isEntrance */); 2153 if (accessibilityController.hasCallbacks()) { 2154 accessibilityController.onWindowTransition(this, winTransit); 2155 } 2156 } 2157 setDisplayLayoutNeeded(); 2158 } 2159 } 2160 onSetAppExiting(boolean animateExit)2161 boolean onSetAppExiting(boolean animateExit) { 2162 final DisplayContent displayContent = getDisplayContent(); 2163 boolean changed = false; 2164 2165 if (!animateExit) { 2166 // Hide the window permanently if no window exist animation is performed, so we can 2167 // avoid the window surface becoming visible again unexpectedly during the next 2168 // relayout. 2169 mPermanentlyHidden = true; 2170 hide(false /* doAnimation */, false /* requestAnim */); 2171 } 2172 if (isVisibleNow() && animateExit) { 2173 mWinAnimator.applyAnimationLocked(TRANSIT_EXIT, false); 2174 if (mWmService.mAccessibilityController.hasCallbacks()) { 2175 mWmService.mAccessibilityController.onWindowTransition(this, TRANSIT_EXIT); 2176 } 2177 changed = true; 2178 if (displayContent != null) { 2179 displayContent.setLayoutNeeded(); 2180 } 2181 } 2182 2183 for (int i = mChildren.size() - 1; i >= 0; --i) { 2184 final WindowState c = mChildren.get(i); 2185 changed |= c.onSetAppExiting(animateExit); 2186 } 2187 2188 return changed; 2189 } 2190 2191 @Override onResize()2192 void onResize() { 2193 final ArrayList<WindowState> resizingWindows = mWmService.mResizingWindows; 2194 if (mHasSurface && !isGoneForLayout() && !resizingWindows.contains(this)) { 2195 ProtoLog.d(WM_DEBUG_RESIZE, "onResize: Resizing %s", this); 2196 resizingWindows.add(this); 2197 } 2198 2199 super.onResize(); 2200 } 2201 2202 /** 2203 * If the window has moved due to its containing content frame changing, then notify the 2204 * listeners and optionally animate it. Simply checking a change of position is not enough, 2205 * because being move due to dock divider is not a trigger for animation. 2206 */ handleWindowMovedIfNeeded()2207 void handleWindowMovedIfNeeded() { 2208 if (!hasMoved()) { 2209 return; 2210 } 2211 2212 // Frame has moved, containing content frame has also moved, and we're not currently 2213 // animating... let's do something. 2214 final int left = mWindowFrames.mFrame.left; 2215 final int top = mWindowFrames.mFrame.top; 2216 2217 if (canPlayMoveAnimation()) { 2218 startMoveAnimation(left, top); 2219 } 2220 2221 if (mWmService.mAccessibilityController.hasCallbacks()) { 2222 mWmService.mAccessibilityController.onSomeWindowResizedOrMoved(getDisplayId()); 2223 } 2224 2225 try { 2226 mClient.moved(left, top); 2227 } catch (RemoteException e) { 2228 } 2229 mMovedByResize = false; 2230 } 2231 canPlayMoveAnimation()2232 private boolean canPlayMoveAnimation() { 2233 2234 // During the transition from pip to fullscreen, the activity windowing mode is set to 2235 // fullscreen at the beginning while the task is kept in pinned mode. Skip the move 2236 // animation in such case since the transition is handled in SysUI. 2237 final boolean hasMovementAnimation = getTask() == null 2238 ? getWindowConfiguration().hasMovementAnimations() 2239 : getTask().getWindowConfiguration().hasMovementAnimations(); 2240 return mToken.okToAnimate() 2241 && (mAttrs.privateFlags & PRIVATE_FLAG_NO_MOVE_ANIMATION) == 0 2242 && !isDragResizing() 2243 && hasMovementAnimation 2244 && !mWinAnimator.mLastHidden 2245 && !mSeamlesslyRotated; 2246 } 2247 2248 /** 2249 * Return whether this window has moved. (Only makes 2250 * sense to call from performLayoutAndPlaceSurfacesLockedInner().) 2251 */ hasMoved()2252 private boolean hasMoved() { 2253 return mHasSurface && (mWindowFrames.hasContentChanged() || mMovedByResize) 2254 && !mAnimatingExit 2255 && (mWindowFrames.mRelFrame.top != mWindowFrames.mLastRelFrame.top 2256 || mWindowFrames.mRelFrame.left != mWindowFrames.mLastRelFrame.left) 2257 && (!mIsChildWindow || !getParentWindow().hasMoved()) 2258 && !mTransitionController.isCollecting(); 2259 } 2260 isObscuringDisplay()2261 boolean isObscuringDisplay() { 2262 Task task = getTask(); 2263 if (task != null && !task.fillsParent()) { 2264 return false; 2265 } 2266 return isOpaqueDrawn() && fillsDisplay(); 2267 } 2268 fillsDisplay()2269 boolean fillsDisplay() { 2270 final DisplayInfo displayInfo = getDisplayInfo(); 2271 return mWindowFrames.mFrame.left <= 0 && mWindowFrames.mFrame.top <= 0 2272 && mWindowFrames.mFrame.right >= displayInfo.appWidth 2273 && mWindowFrames.mFrame.bottom >= displayInfo.appHeight; 2274 } 2275 matchesDisplayAreaBounds()2276 boolean matchesDisplayAreaBounds() { 2277 final Rect rotatedDisplayBounds = mToken.getFixedRotationTransformDisplayBounds(); 2278 if (rotatedDisplayBounds != null) { 2279 // If the rotated display bounds are available, the window bounds are also rotated. 2280 return rotatedDisplayBounds.equals(getBounds()); 2281 } 2282 final DisplayArea displayArea = getDisplayArea(); 2283 if (displayArea == null) { 2284 return getDisplayContent().getBounds().equals(getBounds()); 2285 } 2286 return displayArea.getBounds().equals(getBounds()); 2287 } 2288 2289 /** 2290 * @return {@code true} if last applied config was reported to the client already, {@code false} 2291 * otherwise. 2292 */ isLastConfigReportedToClient()2293 boolean isLastConfigReportedToClient() { 2294 return mLastConfigReportedToClient; 2295 } 2296 2297 @Override onConfigurationChanged(Configuration newParentConfig)2298 public void onConfigurationChanged(Configuration newParentConfig) { 2299 // Get from super to avoid using the updated global config from the override method. 2300 final Configuration selfConfiguration = super.getConfiguration(); 2301 mTempConfiguration.setTo(selfConfiguration); 2302 super.onConfigurationChanged(newParentConfig); 2303 final int diff = selfConfiguration.diff(mTempConfiguration); 2304 if (diff != 0) { 2305 mLastConfigReportedToClient = false; 2306 } 2307 2308 if (getDisplayContent().getImeInputTarget() != this && !isImeLayeringTarget()) { 2309 return; 2310 } 2311 // When the window configuration changed, we need to update the IME control target in 2312 // case the app may lose the IME inets control when exiting from split-screen mode, or the 2313 // IME parent may failed to attach to the app during rotating the screen. 2314 // See DisplayContent#shouldImeAttachedToApp, DisplayContent#isImeControlledByApp 2315 if ((diff & CONFIG_WINDOW_CONFIGURATION) != 0) { 2316 // If the window was the IME layering target, updates the IME surface parent in case 2317 // the IME surface may be wrongly positioned when the window configuration affects the 2318 // IME surface association. (e.g. Attach IME surface on the display instead of the 2319 // app when the app bounds being letterboxed.) 2320 mDisplayContent.updateImeControlTarget(isImeLayeringTarget() /* updateImeParent */); 2321 // Fix the starting window to task when Activity has changed. 2322 if (mStartingData != null && mStartingData.mAssociatedTask == null 2323 && mTempConfiguration.windowConfiguration.getRotation() 2324 == selfConfiguration.windowConfiguration.getRotation() 2325 && !mTempConfiguration.windowConfiguration.getBounds().equals(getBounds())) { 2326 mStartingData.mResizedFromTransfer = true; 2327 // Lock the starting window to task, so it won't resize from transfer anymore. 2328 mActivityRecord.associateStartingWindowWithTaskIfNeeded(); 2329 } 2330 } 2331 } 2332 2333 @Override removeImmediately()2334 void removeImmediately() { 2335 if (mRemoved) { 2336 // Nothing to do. 2337 ProtoLog.v(WM_DEBUG_ADD_REMOVE, 2338 "WS.removeImmediately: %s Already removed...", this); 2339 return; 2340 } 2341 2342 mRemoved = true; 2343 // Destroy surface before super call. The general pattern is that the children need 2344 // to be removed before the parent (so that the sync-engine tracking works). Since 2345 // WindowStateAnimator is a "virtual" child, we have to do it manually here. 2346 mWinAnimator.destroySurfaceLocked(getSyncTransaction()); 2347 if (!mDrawHandlers.isEmpty()) { 2348 mWmService.mH.removeMessages(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this); 2349 } 2350 super.removeImmediately(); 2351 2352 if (isImeOverlayLayeringTarget()) { 2353 mWmService.dispatchImeTargetOverlayVisibilityChanged(mClient.asBinder(), mAttrs.type, 2354 false /* visible */, true /* removed */); 2355 } 2356 final DisplayContent dc = getDisplayContent(); 2357 if (isImeLayeringTarget()) { 2358 // Remove the attached IME screenshot surface. 2359 dc.removeImeSurfaceByTarget(this); 2360 // Make sure to set mImeLayeringTarget as null when the removed window is the 2361 // IME target, in case computeImeTarget may use the outdated target. 2362 dc.setImeLayeringTarget(null); 2363 dc.computeImeTarget(true /* updateImeTarget */); 2364 } 2365 if (dc.getImeInputTarget() == this && !inRelaunchingActivity()) { 2366 mWmService.dispatchImeInputTargetVisibilityChanged(mClient.asBinder(), 2367 false /* visible */, true /* removed */); 2368 dc.updateImeInputAndControlTarget(null); 2369 } 2370 2371 final int type = mAttrs.type; 2372 2373 if (type == TYPE_PRESENTATION || type == TYPE_PRIVATE_PRESENTATION) { 2374 mWmService.mDisplayManagerInternal.onPresentation(dc.getDisplay().getDisplayId(), 2375 /*isShown=*/ false); 2376 } 2377 2378 dc.getDisplayPolicy().removeWindowLw(this); 2379 2380 disposeInputChannel(); 2381 mOnBackInvokedCallbackInfo = null; 2382 2383 mSession.onWindowRemoved(this); 2384 mWmService.postWindowRemoveCleanupLocked(this); 2385 2386 consumeInsetsChange(); 2387 } 2388 2389 @Override removeIfPossible()2390 void removeIfPossible() { 2391 mWindowRemovalAllowed = true; 2392 ProtoLog.v(WM_DEBUG_ADD_REMOVE, 2393 "removeIfPossible: %s callers=%s", this, Debug.getCallers(5)); 2394 2395 final boolean startingWindow = mStartingData != null; 2396 if (startingWindow) { 2397 ProtoLog.d(WM_DEBUG_STARTING_WINDOW, "Starting window removed %s", this); 2398 // Cancel the remove starting window animation on shell. The main window might changed 2399 // during animating, checking for all windows would be safer. 2400 if (mActivityRecord != null) { 2401 mActivityRecord.forAllWindows(w -> { 2402 if (w.isSelfAnimating(0, ANIMATION_TYPE_STARTING_REVEAL)) { 2403 w.cancelAnimation(); 2404 return true; 2405 } 2406 return false; 2407 }, true); 2408 } 2409 mTransitionController.mTransitionTracer.logRemovingStartingWindow(mStartingData); 2410 } else if (mAttrs.type == TYPE_BASE_APPLICATION 2411 && isSelfAnimating(0, ANIMATION_TYPE_STARTING_REVEAL)) { 2412 // Cancel the remove starting window animation in case the binder dead before remove 2413 // splash window. 2414 cancelAnimation(); 2415 } 2416 2417 ProtoLog.v(WM_DEBUG_FOCUS, "Remove client=%x, surfaceController=%s Callers=%s", 2418 System.identityHashCode(mClient.asBinder()), 2419 mWinAnimator.mSurfaceController, 2420 Debug.getCallers(5)); 2421 2422 final DisplayContent displayContent = getDisplayContent(); 2423 final long origId = Binder.clearCallingIdentity(); 2424 2425 try { 2426 disposeInputChannel(); 2427 mOnBackInvokedCallbackInfo = null; 2428 2429 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, 2430 "Remove %s: mSurfaceController=%s mAnimatingExit=%b mRemoveOnExit=%b " 2431 + "mHasSurface=%b surfaceShowing=%b animating=%b app-animation=%b " 2432 + "mDisplayFrozen=%b callers=%s", 2433 this, mWinAnimator.mSurfaceController, mAnimatingExit, mRemoveOnExit, 2434 mHasSurface, mWinAnimator.getShown(), 2435 isAnimating(TRANSITION | PARENTS), 2436 mActivityRecord != null && mActivityRecord.isAnimating(PARENTS | TRANSITION), 2437 mWmService.mDisplayFrozen, Debug.getCallers(6)); 2438 2439 // Visibility of the removed window. Will be used later to update orientation later on. 2440 boolean wasVisible = false; 2441 2442 // First, see if we need to run an animation. If we do, we have to hold off on removing the 2443 // window until the animation is done. If the display is frozen, just remove immediately, 2444 // since the animation wouldn't be seen. 2445 if (mHasSurface && mToken.okToAnimate()) { 2446 // If we are not currently running the exit animation, we need to see about starting one 2447 wasVisible = isVisible(); 2448 2449 // Remove immediately if there is display transition because the animation is 2450 // usually unnoticeable (e.g. covered by rotation animation) and the animation 2451 // bounds could be inconsistent, such as depending on when the window applies 2452 // its draw transaction with new rotation. 2453 final boolean allowExitAnimation = !displayContent.inTransition() 2454 // There will be a new window so the exit animation may not be visible or 2455 // look weird if its orientation is changed. 2456 && !inRelaunchingActivity(); 2457 2458 if (wasVisible && isDisplayed()) { 2459 final int transit = (!startingWindow) ? TRANSIT_EXIT : TRANSIT_PREVIEW_DONE; 2460 2461 // Try starting an animation. 2462 if (allowExitAnimation && mWinAnimator.applyAnimationLocked(transit, false)) { 2463 ProtoLog.v(WM_DEBUG_ANIM, 2464 "Set animatingExit: reason=remove/applyAnimation win=%s", this); 2465 if (startingWindow && mSurfaceAnimator.hasLeash()) { 2466 // Keep starting window on top during fade-out animation. 2467 getPendingTransaction().setLayer(mSurfaceAnimator.mLeash, 2468 Integer.MAX_VALUE); 2469 } 2470 mAnimatingExit = true; 2471 2472 // mAnimatingExit affects canAffectSystemUiFlags(). Run layout such that 2473 // any change from that is performed immediately. 2474 setDisplayLayoutNeeded(); 2475 mWmService.requestTraversal(); 2476 } 2477 if (mWmService.mAccessibilityController.hasCallbacks()) { 2478 mWmService.mAccessibilityController.onWindowTransition(this, transit); 2479 } 2480 } 2481 final boolean isAnimating = allowExitAnimation 2482 && (mAnimatingExit || isAnimationRunningSelfOrParent()); 2483 final boolean lastWindowIsStartingWindow = startingWindow && mActivityRecord != null 2484 && mActivityRecord.isLastWindow(this); 2485 // We delay the removal of a window if it has a showing surface that can be used to run 2486 // exit animation and it is marked as exiting. 2487 // Also, If isn't the an animating starting window that is the last window in the app. 2488 // We allow the removal of the non-animating starting window now as there is no 2489 // additional window or animation that will trigger its removal. 2490 if (mWinAnimator.getShown() && !lastWindowIsStartingWindow && isAnimating) { 2491 // Make isSelfOrAncestorWindowAnimatingExit return true so onExitAnimationDone 2492 // can proceed to remove this window. 2493 mAnimatingExit = true; 2494 // The exit animation is running or should run... wait for it! 2495 ProtoLog.v(WM_DEBUG_ADD_REMOVE, 2496 "Not removing %s due to exit animation", this); 2497 ProtoLog.v(WM_DEBUG_ANIM, "Set animatingExit: reason=remove/isAnimating win=%s", 2498 this); 2499 setupWindowForRemoveOnExit(); 2500 if (mActivityRecord != null) { 2501 mActivityRecord.updateReportedVisibilityLocked(); 2502 } 2503 return; 2504 } 2505 } 2506 2507 // Check if window provides non decor insets before clearing its provided insets. 2508 final boolean windowProvidesDisplayDecorInsets = providesDisplayDecorInsets(); 2509 2510 removeImmediately(); 2511 // Removing a visible window may affect the display orientation so just update it if 2512 // needed. Also recompute configuration if it provides screen decor insets. 2513 boolean needToSendNewConfiguration = wasVisible && displayContent.updateOrientation(); 2514 if (windowProvidesDisplayDecorInsets) { 2515 needToSendNewConfiguration |= 2516 displayContent.getDisplayPolicy().updateDecorInsetsInfo(); 2517 } 2518 2519 if (needToSendNewConfiguration) { 2520 displayContent.sendNewConfiguration(); 2521 } 2522 mWmService.updateFocusedWindowLocked(isFocused() 2523 ? UPDATE_FOCUS_REMOVING_FOCUS 2524 : UPDATE_FOCUS_NORMAL, 2525 true /*updateInputWindows*/); 2526 } finally { 2527 Binder.restoreCallingIdentity(origId); 2528 } 2529 } 2530 setupWindowForRemoveOnExit()2531 private void setupWindowForRemoveOnExit() { 2532 mRemoveOnExit = true; 2533 setDisplayLayoutNeeded(); 2534 getDisplayContent().getDisplayPolicy().removeWindowLw(this); 2535 // Request a focus update as this window's input channel is already gone. Otherwise 2536 // we could have no focused window in input manager. 2537 final boolean focusChanged = mWmService.updateFocusedWindowLocked( 2538 UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/); 2539 mWmService.mWindowPlacerLocked.performSurfacePlacement(); 2540 if (focusChanged) { 2541 getDisplayContent().getInputMonitor().updateInputWindowsLw(false /*force*/); 2542 } 2543 } 2544 setHasSurface(boolean hasSurface)2545 void setHasSurface(boolean hasSurface) { 2546 mHasSurface = hasSurface; 2547 } 2548 canBeImeTarget()2549 boolean canBeImeTarget() { 2550 if (mIsImWindow) { 2551 // IME windows can't be IME targets. IME targets are required to be below the IME 2552 // windows and that wouldn't be possible if the IME window is its own target...silly. 2553 return false; 2554 } 2555 2556 if (inPinnedWindowingMode()) { 2557 return false; 2558 } 2559 2560 if (mAttrs.type == TYPE_SCREENSHOT) { 2561 // Disallow screenshot windows from being IME targets 2562 return false; 2563 } 2564 2565 final boolean windowsAreFocusable = mActivityRecord == null || mActivityRecord.windowsAreFocusable(); 2566 if (!windowsAreFocusable) { 2567 // This window can't be an IME target if the app's windows should not be focusable. 2568 return false; 2569 } 2570 2571 final Task rootTask = getRootTask(); 2572 if (rootTask != null && !rootTask.isFocusable()) { 2573 // Ignore when the root task shouldn't receive input event. 2574 // (i.e. the minimized root task in split screen mode.) 2575 return false; 2576 } 2577 2578 if (mAttrs.type == TYPE_APPLICATION_STARTING) { 2579 // Ignore mayUseInputMethod for starting window for now. 2580 // TODO(b/159911356): Remove this special casing (originally added in commit e75d872). 2581 } else { 2582 // TODO(b/145812508): Clean this up in S, may depend on b/141738570 2583 // The current logic lets windows become the "ime target" even though they are 2584 // not-focusable and can thus never actually start input. 2585 // Ideally, this would reject windows where mayUseInputMethod() == false, but this 2586 // also impacts Z-ordering of and delivery of IME insets to child windows, which means 2587 // that simply disallowing non-focusable windows would break apps. 2588 // See b/159438771, b/144619551. 2589 2590 final int fl = mAttrs.flags & (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM); 2591 2592 // Can only be an IME target if both FLAG_NOT_FOCUSABLE and FLAG_ALT_FOCUSABLE_IM are 2593 // set or both are cleared...and not a starting window. 2594 if (fl != 0 && fl != (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM)) { 2595 return false; 2596 } 2597 } 2598 2599 // Don't allow transient-launch activities to take IME. 2600 if (rootTask != null && mActivityRecord != null 2601 && mTransitionController.isTransientLaunch(mActivityRecord)) { 2602 return false; 2603 } 2604 2605 if (DEBUG_INPUT_METHOD) { 2606 Slog.i(TAG_WM, "isVisibleRequestedOrAdding " + this + ": " 2607 + isVisibleRequestedOrAdding() + " isVisible: " + (isVisible() 2608 && mActivityRecord != null && mActivityRecord.isVisible())); 2609 if (!isVisibleRequestedOrAdding()) { 2610 Slog.i(TAG_WM, " mSurfaceController=" + mWinAnimator.mSurfaceController 2611 + " relayoutCalled=" + mRelayoutCalled 2612 + " viewVis=" + mViewVisibility 2613 + " policyVis=" + isVisibleByPolicy() 2614 + " policyVisAfterAnim=" + mLegacyPolicyVisibilityAfterAnim 2615 + " parentHidden=" + isParentWindowHidden() 2616 + " exiting=" + mAnimatingExit + " destroying=" + mDestroying); 2617 if (mActivityRecord != null) { 2618 Slog.i(TAG_WM, " mActivityRecord.visibleRequested=" 2619 + mActivityRecord.isVisibleRequested()); 2620 } 2621 } 2622 } 2623 return isVisibleRequestedOrAdding() 2624 || (isVisible() && mActivityRecord != null && mActivityRecord.isVisible()); 2625 } 2626 openInputChannel(@onNull InputChannel outInputChannel)2627 void openInputChannel(@NonNull InputChannel outInputChannel) { 2628 if (mInputChannel != null) { 2629 throw new IllegalStateException("Window already has an input channel."); 2630 } 2631 String name = getName(); 2632 mInputChannel = mWmService.mInputManager.createInputChannel(name); 2633 mInputChannelToken = mInputChannel.getToken(); 2634 mInputWindowHandle.setToken(mInputChannelToken); 2635 mWmService.mInputToWindowMap.put(mInputChannelToken, this); 2636 mInputChannel.copyTo(outInputChannel); 2637 } 2638 2639 /** 2640 * Move the touch gesture from the currently touched window on this display to this window. 2641 * 2642 * @deprecated Use {@link 2643 * com.android.server.input.InputManagerInternal#transferTouchGesture(IBinder, IBinder)}. 2644 */ 2645 @Deprecated transferTouch()2646 public boolean transferTouch() { 2647 return mWmService.mInputManager.transferTouch(mInputChannelToken, getDisplayId()); 2648 } 2649 disposeInputChannel()2650 void disposeInputChannel() { 2651 if (mInputChannelToken != null) { 2652 // Unregister server channel first otherwise it complains about broken channel. 2653 mWmService.mInputManager.removeInputChannel(mInputChannelToken); 2654 mWmService.mKeyInterceptionInfoForToken.remove(mInputChannelToken); 2655 mWmService.mInputToWindowMap.remove(mInputChannelToken); 2656 mInputChannelToken = null; 2657 } 2658 2659 if (mInputChannel != null) { 2660 mInputChannel.dispose(); 2661 mInputChannel = null; 2662 } 2663 mInputWindowHandle.setToken(null); 2664 } 2665 setDisplayLayoutNeeded()2666 void setDisplayLayoutNeeded() { 2667 final DisplayContent dc = getDisplayContent(); 2668 if (dc != null) { 2669 dc.setLayoutNeeded(); 2670 } 2671 } 2672 2673 @Override switchUser(int userId)2674 void switchUser(int userId) { 2675 super.switchUser(userId); 2676 2677 if (showToCurrentUser()) { 2678 setPolicyVisibilityFlag(VISIBLE_FOR_USER); 2679 } else { 2680 if (DEBUG_VISIBILITY) Slog.w(TAG_WM, "user changing, hiding " + this 2681 + ", attrs=" + mAttrs.type + ", belonging to " + mOwnerUid); 2682 clearPolicyVisibilityFlag(VISIBLE_FOR_USER); 2683 } 2684 } 2685 getSurfaceTouchableRegion(Region region, WindowManager.LayoutParams attrs)2686 void getSurfaceTouchableRegion(Region region, WindowManager.LayoutParams attrs) { 2687 final boolean modal = attrs.isModal(); 2688 if (modal) { 2689 if (mActivityRecord != null) { 2690 // Limit the outer touch to the activity root task region. 2691 updateRegionForModalActivityWindow(region); 2692 } else { 2693 // Give it a large touchable region at first because it was touch modal. The window 2694 // might be moved on the display, so the touchable region should be large enough to 2695 // ensure it covers the whole display, no matter where it is moved. 2696 getDisplayContent().getBounds(mTmpRect); 2697 final int dw = mTmpRect.width(); 2698 final int dh = mTmpRect.height(); 2699 region.set(-dw, -dh, dw + dw, dh + dh); 2700 } 2701 subtractTouchExcludeRegionIfNeeded(region); 2702 2703 } else { 2704 // Not modal 2705 getTouchableRegion(region); 2706 } 2707 2708 // Translate to surface based coordinates. 2709 final Rect frame = mWindowFrames.mFrame; 2710 if (frame.left != 0 || frame.top != 0) { 2711 region.translate(-frame.left, -frame.top); 2712 } 2713 if (modal && mTouchableInsets == TOUCHABLE_INSETS_REGION) { 2714 // The client gave us a touchable region and so first 2715 // we calculate the untouchable region, then punch that out of our 2716 // expanded modal region. 2717 mTmpRegion.set(0, 0, frame.right, frame.bottom); 2718 mTmpRegion.op(mGivenTouchableRegion, Region.Op.DIFFERENCE); 2719 region.op(mTmpRegion, Region.Op.DIFFERENCE); 2720 } 2721 2722 // TODO(b/139804591): sizecompat layout needs to be reworked. Currently mFrame is post- 2723 // scaling but the existing logic doesn't expect that. The result is that the already- 2724 // scaled region ends up getting sent to surfaceflinger which then applies the scale 2725 // (again). Until this is resolved, apply an inverse-scale here. 2726 if (mInvGlobalScale != 1.f) { 2727 region.scale(mInvGlobalScale); 2728 } 2729 } 2730 2731 /** 2732 * Expands the given rectangle by the region of window resize handle for freeform window. 2733 * @param inOutRect The rectangle to update. 2734 */ adjustRegionInFreefromWindowMode(Rect inOutRect)2735 private void adjustRegionInFreefromWindowMode(Rect inOutRect) { 2736 if (!inFreeformWindowingMode()) { 2737 return; 2738 } 2739 2740 // For freeform windows, we need the touch region to include the whole 2741 // surface for the shadows. 2742 final DisplayMetrics displayMetrics = getDisplayContent().getDisplayMetrics(); 2743 final int delta = WindowManagerService.dipToPixel( 2744 RESIZE_HANDLE_WIDTH_IN_DP, displayMetrics); 2745 inOutRect.inset(-delta, -delta); 2746 } 2747 2748 /** 2749 * Updates the region for a window in an Activity that was a touch modal. This will limit 2750 * the outer touch to the activity root task region. 2751 * @param outRegion The region to update. 2752 */ updateRegionForModalActivityWindow(Region outRegion)2753 private void updateRegionForModalActivityWindow(Region outRegion) { 2754 // If the inner bounds of letterbox is available, then it will be used as the 2755 // touchable region so it won't cover the touchable letterbox and the touch 2756 // events can slip to activity from letterbox. 2757 mActivityRecord.getLetterboxInnerBounds(mTmpRect); 2758 if (mTmpRect.isEmpty()) { 2759 final Rect transformedBounds = mActivityRecord.getFixedRotationTransformDisplayBounds(); 2760 if (transformedBounds != null) { 2761 // Task is in the same orientation as display, so the rotated bounds should be 2762 // chosen as the touchable region. Then when the surface layer transforms the 2763 // region to display space, the orientation will be consistent. 2764 mTmpRect.set(transformedBounds); 2765 } else { 2766 // If this is a modal window we need to dismiss it if it's not full screen 2767 // and the touch happens outside of the frame that displays the content. This 2768 // means we need to intercept touches outside of that window. The dim layer 2769 // user associated with the window (task or root task) will give us the good 2770 // bounds, as they would be used to display the dim layer. 2771 final TaskFragment taskFragment = getTaskFragment(); 2772 if (taskFragment != null) { 2773 taskFragment.getDimBounds(mTmpRect); 2774 } else if (getRootTask() != null) { 2775 getRootTask().getDimBounds(mTmpRect); 2776 } 2777 } 2778 } 2779 adjustRegionInFreefromWindowMode(mTmpRect); 2780 outRegion.set(mTmpRect); 2781 cropRegionToRootTaskBoundsIfNeeded(outRegion); 2782 } 2783 checkPolicyVisibilityChange()2784 void checkPolicyVisibilityChange() { 2785 if (isLegacyPolicyVisibility() != mLegacyPolicyVisibilityAfterAnim) { 2786 if (DEBUG_VISIBILITY) { 2787 Slog.v(TAG, "Policy visibility changing after anim in " + 2788 mWinAnimator + ": " + mLegacyPolicyVisibilityAfterAnim); 2789 } 2790 if (mLegacyPolicyVisibilityAfterAnim) { 2791 setPolicyVisibilityFlag(LEGACY_POLICY_VISIBILITY); 2792 } else { 2793 clearPolicyVisibilityFlag(LEGACY_POLICY_VISIBILITY); 2794 } 2795 if (!isVisibleByPolicy()) { 2796 mWinAnimator.hide(getPendingTransaction(), "checkPolicyVisibilityChange"); 2797 if (isFocused()) { 2798 ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, 2799 "setAnimationLocked: setting mFocusMayChange true"); 2800 mWmService.mFocusMayChange = true; 2801 } 2802 setDisplayLayoutNeeded(); 2803 // Window is no longer visible -- make sure if we were waiting 2804 // for it to be displayed before enabling the display, that 2805 // we allow the display to be enabled now. 2806 mWmService.enableScreenIfNeededLocked(); 2807 } 2808 } 2809 } 2810 setRequestedSize(int requestedWidth, int requestedHeight)2811 void setRequestedSize(int requestedWidth, int requestedHeight) { 2812 if ((mRequestedWidth != requestedWidth || mRequestedHeight != requestedHeight)) { 2813 mLayoutNeeded = true; 2814 mRequestedWidth = requestedWidth; 2815 mRequestedHeight = requestedHeight; 2816 } 2817 } 2818 prepareWindowToDisplayDuringRelayout(boolean wasVisible)2819 void prepareWindowToDisplayDuringRelayout(boolean wasVisible) { 2820 // We need to turn on screen regardless of visibility. 2821 final boolean hasTurnScreenOnFlag = (mAttrs.flags & FLAG_TURN_SCREEN_ON) != 0 2822 || (mActivityRecord != null && mActivityRecord.canTurnScreenOn()); 2823 2824 // The screen will turn on if the following conditions are met 2825 // 1. The window has the flag FLAG_TURN_SCREEN_ON or ActivityRecord#canTurnScreenOn. 2826 // 2. The WMS allows theater mode. 2827 // 3. No AWT or the AWT allows the screen to be turned on. This should only be true once 2828 // per resume to prevent the screen getting getting turned on for each relayout. Set 2829 // currentLaunchCanTurnScreenOn will be set to false so the window doesn't turn the screen 2830 // on again during this resume. 2831 // 4. When the screen is not interactive. This is because when the screen is already 2832 // interactive, the value may persist until the next animation, which could potentially 2833 // be occurring while turning off the screen. This would lead to the screen incorrectly 2834 // turning back on. 2835 if (hasTurnScreenOnFlag) { 2836 boolean allowTheaterMode = mWmService.mAllowTheaterModeWakeFromLayout 2837 || Settings.Global.getInt(mWmService.mContext.getContentResolver(), 2838 Settings.Global.THEATER_MODE_ON, 0) == 0; 2839 boolean canTurnScreenOn = mActivityRecord == null || mActivityRecord.currentLaunchCanTurnScreenOn(); 2840 2841 if (allowTheaterMode && canTurnScreenOn 2842 && (mWmService.mAtmService.isDreaming() 2843 || !mWmService.mPowerManager.isInteractive())) { 2844 if (DEBUG_VISIBILITY || DEBUG_POWER) { 2845 Slog.v(TAG, "Relayout window turning screen on: " + this); 2846 } 2847 mWmService.mPowerManager.wakeUp(SystemClock.uptimeMillis(), 2848 PowerManager.WAKE_REASON_APPLICATION, "android.server.wm:SCREEN_ON_FLAG"); 2849 } 2850 2851 if (mActivityRecord != null) { 2852 mActivityRecord.setCurrentLaunchCanTurnScreenOn(false); 2853 } 2854 } 2855 2856 // If we were already visible, skip rest of preparation. 2857 if (wasVisible) { 2858 if (DEBUG_VISIBILITY) Slog.v(TAG, 2859 "Already visible and does not turn on screen, skip preparing: " + this); 2860 return; 2861 } 2862 2863 if ((mAttrs.softInputMode & SOFT_INPUT_MASK_ADJUST) 2864 == SOFT_INPUT_ADJUST_RESIZE) { 2865 mLayoutNeeded = true; 2866 } 2867 2868 if (isDrawn() && mToken.okToAnimate()) { 2869 mWinAnimator.applyEnterAnimationLocked(); 2870 } 2871 } 2872 getProcessGlobalConfiguration()2873 private Configuration getProcessGlobalConfiguration() { 2874 // For child windows we want to use the pid for the parent window in case the the child 2875 // window was added from another process. 2876 final WindowState parentWindow = getParentWindow(); 2877 final Session session = parentWindow != null ? parentWindow.mSession : mSession; 2878 return session.mPid == MY_PID ? mWmService.mRoot.getConfiguration() 2879 : session.mProcess.getConfiguration(); 2880 } 2881 getLastReportedConfiguration()2882 private Configuration getLastReportedConfiguration() { 2883 return mLastReportedConfiguration.getMergedConfiguration(); 2884 } 2885 adjustStartingWindowFlags()2886 void adjustStartingWindowFlags() { 2887 if (mAttrs.type == TYPE_BASE_APPLICATION && mActivityRecord != null 2888 && mActivityRecord.mStartingWindow != null) { 2889 // Special handling of starting window over the base 2890 // window of the app: propagate lock screen flags to it, 2891 // to provide the correct semantics while starting. 2892 final int mask = FLAG_SHOW_WHEN_LOCKED | FLAG_DISMISS_KEYGUARD 2893 | FLAG_ALLOW_LOCK_WHILE_SCREEN_ON; 2894 WindowManager.LayoutParams sa = mActivityRecord.mStartingWindow.mAttrs; 2895 sa.flags = (sa.flags & ~mask) | (mAttrs.flags & mask); 2896 } 2897 } 2898 setWindowScale(int requestedWidth, int requestedHeight)2899 void setWindowScale(int requestedWidth, int requestedHeight) { 2900 final boolean scaledWindow = (mAttrs.flags & FLAG_SCALED) != 0; 2901 2902 if (scaledWindow) { 2903 // requested{Width|Height} Surface's physical size 2904 // attrs.{width|height} Size on screen 2905 // TODO: We don't check if attrs != null here. Is it implicitly checked? 2906 mHScale = (mAttrs.width != requestedWidth) ? 2907 (mAttrs.width / (float)requestedWidth) : 1.0f; 2908 mVScale = (mAttrs.height != requestedHeight) ? 2909 (mAttrs.height / (float)requestedHeight) : 1.0f; 2910 } else { 2911 mHScale = mVScale = 1; 2912 } 2913 } 2914 2915 /** Returns {@code true} if this window desires key events. */ canReceiveKeys()2916 boolean canReceiveKeys() { 2917 return canReceiveKeys(false /* fromUserTouch */); 2918 } 2919 canReceiveKeysReason(boolean fromUserTouch)2920 public String canReceiveKeysReason(boolean fromUserTouch) { 2921 return "fromTouch= " + fromUserTouch 2922 + " isVisibleRequestedOrAdding=" + isVisibleRequestedOrAdding() 2923 + " mViewVisibility=" + mViewVisibility 2924 + " mRemoveOnExit=" + mRemoveOnExit 2925 + " flags=" + mAttrs.flags 2926 + " appWindowsAreFocusable=" 2927 + (mActivityRecord == null || mActivityRecord.windowsAreFocusable(fromUserTouch)) 2928 + " canReceiveTouchInput=" + canReceiveTouchInput() 2929 + " displayIsOnTop=" + getDisplayContent().isOnTop() 2930 + " displayIsTrusted=" + getDisplayContent().isTrusted() 2931 + " transitShouldKeepFocus=" + (mActivityRecord != null 2932 && mTransitionController.shouldKeepFocus(mActivityRecord)); 2933 } 2934 canReceiveKeys(boolean fromUserTouch)2935 public boolean canReceiveKeys(boolean fromUserTouch) { 2936 if (mActivityRecord != null && mTransitionController.shouldKeepFocus(mActivityRecord)) { 2937 // During transient launch, the transient-hide windows are not visibleRequested 2938 // or on-top but are kept focusable and thus can receive keys. 2939 return true; 2940 } 2941 final boolean canReceiveKeys = isVisibleRequestedOrAdding() 2942 && (mViewVisibility == View.VISIBLE) && !mRemoveOnExit 2943 && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0) 2944 && (mActivityRecord == null || mActivityRecord.windowsAreFocusable(fromUserTouch)) 2945 // can it receive touches 2946 && (mActivityRecord == null || mActivityRecord.getTask() == null 2947 || !mActivityRecord.getTask().getRootTask().shouldIgnoreInput()); 2948 2949 if (!canReceiveKeys) { 2950 return false; 2951 } 2952 // Do not allow untrusted virtual display to receive keys unless user intentionally 2953 // touches the display. 2954 return fromUserTouch || getDisplayContent().isOnTop() 2955 || getDisplayContent().isTrusted(); 2956 } 2957 2958 @Override canShowWhenLocked()2959 public boolean canShowWhenLocked() { 2960 if (mActivityRecord != null) { 2961 // It will also check if its windows contain FLAG_SHOW_WHEN_LOCKED. 2962 return mActivityRecord.canShowWhenLocked(); 2963 } 2964 return (mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0; 2965 } 2966 2967 /** 2968 * @return {@code true} if this window can receive touches based on among other things, 2969 * windowing state and recents animation state. 2970 **/ canReceiveTouchInput()2971 boolean canReceiveTouchInput() { 2972 if (mActivityRecord == null || mActivityRecord.getTask() == null) { 2973 return true; 2974 } 2975 // During transient launch, the transient-hide windows are not visibleRequested 2976 // or on-top but are kept focusable and thus can receive touch input. 2977 if (mTransitionController.shouldKeepFocus(mActivityRecord)) { 2978 return true; 2979 } 2980 2981 // Do not allow back predictive animation target to receive touch, app can trigger an 2982 // unexpected transition so basically unable to polish it. 2983 if (mWmService.mAtmService.mBackNavigationController.shouldPauseTouch(mActivityRecord)) { 2984 return false; 2985 } 2986 return !mActivityRecord.getTask().getRootTask().shouldIgnoreInput() 2987 && mActivityRecord.isVisibleRequested(); 2988 } 2989 2990 /** 2991 * Returns {@code true} if this window has been shown on screen at some time in the past. 2992 * 2993 * @deprecated Use {@link #isDrawn} or any of the other drawn/visibility methods. 2994 */ 2995 @Deprecated hasDrawn()2996 boolean hasDrawn() { 2997 return mWinAnimator.mDrawState == WindowStateAnimator.HAS_DRAWN; 2998 } 2999 3000 /** 3001 * Can be called to undo the effect of {@link #hide}, allowing a window to be shown as long 3002 * as the client would also like it to be shown. 3003 */ show(boolean doAnimation, boolean requestAnim)3004 boolean show(boolean doAnimation, boolean requestAnim) { 3005 if (isLegacyPolicyVisibility() && mLegacyPolicyVisibilityAfterAnim) { 3006 // Already showing. 3007 return false; 3008 } 3009 if (!showToCurrentUser()) { 3010 return false; 3011 } 3012 if (!mAppOpVisibility) { 3013 // Being hidden due to app op request. 3014 return false; 3015 } 3016 if (mPermanentlyHidden) { 3017 // Permanently hidden until the app exists as apps aren't prepared 3018 // to handle their windows being removed from under them. 3019 return false; 3020 } 3021 if (mHiddenWhileSuspended) { 3022 // Being hidden due to owner package being suspended. 3023 return false; 3024 } 3025 if (mForceHideNonSystemOverlayWindow) { 3026 // This is an alert window that is currently force hidden. 3027 return false; 3028 } 3029 if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility true: " + this); 3030 if (doAnimation) { 3031 if (DEBUG_VISIBILITY) Slog.v(TAG, "doAnimation: mPolicyVisibility=" 3032 + isLegacyPolicyVisibility() 3033 + " animating=" + isAnimating(TRANSITION | PARENTS)); 3034 if (!mToken.okToAnimate()) { 3035 doAnimation = false; 3036 } else if (isLegacyPolicyVisibility() && !isAnimating(TRANSITION | PARENTS)) { 3037 // Check for the case where we are currently visible and 3038 // not animating; we do not want to do animation at such a 3039 // point to become visible when we already are. 3040 doAnimation = false; 3041 } 3042 } 3043 setPolicyVisibilityFlag(LEGACY_POLICY_VISIBILITY); 3044 mLegacyPolicyVisibilityAfterAnim = true; 3045 if (doAnimation) { 3046 mWinAnimator.applyAnimationLocked(TRANSIT_ENTER, true); 3047 } 3048 if (requestAnim) { 3049 mWmService.scheduleAnimationLocked(); 3050 } 3051 if ((mAttrs.flags & FLAG_NOT_FOCUSABLE) == 0) { 3052 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false /* updateImWindows */); 3053 } 3054 return true; 3055 } 3056 3057 /** Forces the window to be hidden, regardless of whether the client like it shown. */ hide(boolean doAnimation, boolean requestAnim)3058 boolean hide(boolean doAnimation, boolean requestAnim) { 3059 if (doAnimation) { 3060 if (!mToken.okToAnimate()) { 3061 doAnimation = false; 3062 } 3063 } 3064 boolean current = 3065 doAnimation ? mLegacyPolicyVisibilityAfterAnim : isLegacyPolicyVisibility(); 3066 if (!current) { 3067 // Already hiding. 3068 return false; 3069 } 3070 if (doAnimation) { 3071 // If a hide animation is applied, then let onAnimationFinished 3072 // -> checkPolicyVisibilityChange hide the window. Otherwise make doAnimation false 3073 // to commit invisible immediately. 3074 if (!mWinAnimator.applyAnimationLocked(TRANSIT_EXIT, false /* isEntrance */)) { 3075 doAnimation = false; 3076 } 3077 } 3078 mLegacyPolicyVisibilityAfterAnim = false; 3079 final boolean isFocused = isFocused(); 3080 if (!doAnimation) { 3081 if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility false: " + this); 3082 clearPolicyVisibilityFlag(LEGACY_POLICY_VISIBILITY); 3083 // Window is no longer visible -- make sure if we were waiting 3084 // for it to be displayed before enabling the display, that 3085 // we allow the display to be enabled now. 3086 mWmService.enableScreenIfNeededLocked(); 3087 if (isFocused) { 3088 ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, 3089 "WindowState.hideLw: setting mFocusMayChange true"); 3090 mWmService.mFocusMayChange = true; 3091 } 3092 } 3093 if (requestAnim) { 3094 mWmService.scheduleAnimationLocked(); 3095 } 3096 if (isFocused) { 3097 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false /* updateImWindows */); 3098 } 3099 return true; 3100 } 3101 setForceHideNonSystemOverlayWindowIfNeeded(boolean forceHide)3102 void setForceHideNonSystemOverlayWindowIfNeeded(boolean forceHide) { 3103 final int baseType = getBaseType(); 3104 if (mSession.mCanAddInternalSystemWindow 3105 || (!isSystemAlertWindowType(baseType) && baseType != TYPE_TOAST)) { 3106 return; 3107 } 3108 3109 if (baseType == TYPE_APPLICATION_OVERLAY && mAttrs.isSystemApplicationOverlay() 3110 && mSession.mCanCreateSystemApplicationOverlay) { 3111 return; 3112 } 3113 3114 if (mForceHideNonSystemOverlayWindow == forceHide) { 3115 return; 3116 } 3117 mForceHideNonSystemOverlayWindow = forceHide; 3118 if (forceHide) { 3119 hide(true /* doAnimation */, true /* requestAnim */); 3120 } else { 3121 show(true /* doAnimation */, true /* requestAnim */); 3122 } 3123 } 3124 setHiddenWhileSuspended(boolean hide)3125 void setHiddenWhileSuspended(boolean hide) { 3126 if (mOwnerCanAddInternalSystemWindow 3127 || (!isSystemAlertWindowType(mAttrs.type) && mAttrs.type != TYPE_TOAST)) { 3128 return; 3129 } 3130 if (mHiddenWhileSuspended == hide) { 3131 return; 3132 } 3133 mHiddenWhileSuspended = hide; 3134 if (hide) { 3135 hide(true /* doAnimation */, true /* requestAnim */); 3136 } else { 3137 show(true /* doAnimation */, true /* requestAnim */); 3138 } 3139 } 3140 setAppOpVisibilityLw(boolean state)3141 private void setAppOpVisibilityLw(boolean state) { 3142 if (mAppOpVisibility != state) { 3143 mAppOpVisibility = state; 3144 if (state) { 3145 // If the policy visibility had last been to hide, then this 3146 // will incorrectly show at this point since we lost that 3147 // information. Not a big deal -- for the windows that have app 3148 // ops modifies they should only be hidden by policy due to the 3149 // lock screen, and the user won't be changing this if locked. 3150 // Plus it will quickly be fixed the next time we do a layout. 3151 show(true /* doAnimation */, true /* requestAnim */); 3152 } else { 3153 hide(true /* doAnimation */, true /* requestAnim */); 3154 } 3155 } 3156 } 3157 initAppOpsState()3158 void initAppOpsState() { 3159 if (mAppOp == OP_NONE || !mAppOpVisibility) { 3160 return; 3161 } 3162 // If the app op was MODE_DEFAULT we would have checked the permission 3163 // and add the window only if the permission was granted. Therefore, if 3164 // the mode is MODE_DEFAULT we want the op to succeed as the window is 3165 // shown. 3166 final int mode = mWmService.mAppOps.startOpNoThrow(mAppOp, getOwningUid(), 3167 getOwningPackage(), true /* startIfModeDefault */, null /* featureId */, 3168 "init-default-visibility"); 3169 if (mode != MODE_ALLOWED && mode != MODE_DEFAULT) { 3170 setAppOpVisibilityLw(false); 3171 } 3172 } 3173 resetAppOpsState()3174 void resetAppOpsState() { 3175 if (mAppOp != OP_NONE && mAppOpVisibility) { 3176 mWmService.mAppOps.finishOp(mAppOp, getOwningUid(), getOwningPackage(), 3177 null /* featureId */); 3178 } 3179 } 3180 updateAppOpsState()3181 void updateAppOpsState() { 3182 if (mAppOp == OP_NONE) { 3183 return; 3184 } 3185 final int uid = getOwningUid(); 3186 final String packageName = getOwningPackage(); 3187 if (mAppOpVisibility) { 3188 // There is a race between the check and the finish calls but this is fine 3189 // as this would mean we will get another change callback and will reconcile. 3190 int mode = mWmService.mAppOps.checkOpNoThrow(mAppOp, uid, packageName); 3191 if (mode != MODE_ALLOWED && mode != MODE_DEFAULT) { 3192 mWmService.mAppOps.finishOp(mAppOp, uid, packageName, null /* featureId */); 3193 setAppOpVisibilityLw(false); 3194 } 3195 } else { 3196 final int mode = mWmService.mAppOps.startOpNoThrow(mAppOp, uid, packageName, 3197 true /* startIfModeDefault */, null /* featureId */, "attempt-to-be-visible"); 3198 if (mode == MODE_ALLOWED || mode == MODE_DEFAULT) { 3199 setAppOpVisibilityLw(true); 3200 } 3201 } 3202 } 3203 hidePermanentlyLw()3204 public void hidePermanentlyLw() { 3205 if (!mPermanentlyHidden) { 3206 mPermanentlyHidden = true; 3207 hide(true /* doAnimation */, true /* requestAnim */); 3208 } 3209 } 3210 pokeDrawLockLw(long timeout)3211 public void pokeDrawLockLw(long timeout) { 3212 if (isVisibleRequestedOrAdding()) { 3213 if (mDrawLock == null) { 3214 // We want the tag name to be somewhat stable so that it is easier to correlate 3215 // in wake lock statistics. So in particular, we don't want to include the 3216 // window's hash code as in toString(). 3217 final CharSequence tag = getWindowTag(); 3218 mDrawLock = mWmService.mPowerManager.newWakeLock(DRAW_WAKE_LOCK, "Window:" + tag); 3219 mDrawLock.setReferenceCounted(false); 3220 mDrawLock.setWorkSource(new WorkSource(mOwnerUid, mAttrs.packageName)); 3221 } 3222 // Each call to acquire resets the timeout. 3223 if (DEBUG_POWER) { 3224 Slog.d(TAG, "pokeDrawLock: poking draw lock on behalf of visible window owned by " 3225 + mAttrs.packageName); 3226 } 3227 mDrawLock.acquire(timeout); 3228 } else if (DEBUG_POWER) { 3229 Slog.d(TAG, "pokeDrawLock: suppressed draw lock request for invisible window " 3230 + "owned by " + mAttrs.packageName); 3231 } 3232 } 3233 3234 /** Checks whether the process hosting this window is currently alive. */ isAlive()3235 boolean isAlive() { 3236 return mClient.asBinder().isBinderAlive(); 3237 } 3238 sendAppVisibilityToClients()3239 void sendAppVisibilityToClients() { 3240 super.sendAppVisibilityToClients(); 3241 3242 final boolean clientVisible = mToken.isClientVisible(); 3243 // TODO(shell-transitions): This is currently only applicable to app windows, BUT we 3244 // want to extend the "starting" concept to other windows. 3245 if (mAttrs.type == TYPE_APPLICATION_STARTING && !clientVisible) { 3246 // Don't hide the starting window. 3247 return; 3248 } 3249 3250 try { 3251 if (DEBUG_VISIBILITY) Slog.v(TAG, 3252 "Setting visibility of " + this + ": " + clientVisible); 3253 mClient.dispatchAppVisibility(clientVisible); 3254 } catch (RemoteException e) { 3255 // The remote client fails to process the visibility message. That means it is in a 3256 // wrong state. E.g. the binder buffer is running out or the binder threads are dead. 3257 // The window visibility is out-of-sync that may cause blank content or left over, so 3258 // just kill it. And if it is a window of foreground activity, the activity can be 3259 // restarted automatically if needed. 3260 Slog.w(TAG, "Exception thrown during dispatchAppVisibility " + this, e); 3261 if (android.os.Process.getUidForPid(mSession.mPid) == mSession.mUid) { 3262 android.os.Process.killProcess(mSession.mPid); 3263 } 3264 } 3265 } 3266 onStartFreezingScreen()3267 void onStartFreezingScreen() { 3268 mAppFreezing = true; 3269 for (int i = mChildren.size() - 1; i >= 0; --i) { 3270 final WindowState c = mChildren.get(i); 3271 c.onStartFreezingScreen(); 3272 } 3273 } 3274 onStopFreezingScreen()3275 boolean onStopFreezingScreen() { 3276 boolean unfrozeWindows = false; 3277 for (int i = mChildren.size() - 1; i >= 0; --i) { 3278 final WindowState c = mChildren.get(i); 3279 unfrozeWindows |= c.onStopFreezingScreen(); 3280 } 3281 3282 if (!mAppFreezing) { 3283 return unfrozeWindows; 3284 } 3285 3286 mAppFreezing = false; 3287 3288 if (mHasSurface && !getOrientationChanging() 3289 && mWmService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_TIMEOUT) { 3290 ProtoLog.v(WM_DEBUG_ORIENTATION, 3291 "set mOrientationChanging of %s", this); 3292 setOrientationChanging(true); 3293 } 3294 mLastFreezeDuration = 0; 3295 setDisplayLayoutNeeded(); 3296 return true; 3297 } 3298 destroySurface(boolean cleanupOnResume, boolean appStopped)3299 boolean destroySurface(boolean cleanupOnResume, boolean appStopped) { 3300 boolean destroyedSomething = false; 3301 3302 // Copying to a different list as multiple children can be removed. 3303 final ArrayList<WindowState> childWindows = new ArrayList<>(mChildren); 3304 for (int i = childWindows.size() - 1; i >= 0; --i) { 3305 final WindowState c = childWindows.get(i); 3306 destroyedSomething |= c.destroySurface(cleanupOnResume, appStopped); 3307 } 3308 3309 if (!(appStopped || mWindowRemovalAllowed || cleanupOnResume)) { 3310 return destroyedSomething; 3311 } 3312 3313 if (mDestroying) { 3314 ProtoLog.e(WM_DEBUG_ADD_REMOVE, "win=%s" 3315 + " destroySurfaces: appStopped=%b" 3316 + " win.mWindowRemovalAllowed=%b" 3317 + " win.mRemoveOnExit=%b", this, appStopped, 3318 mWindowRemovalAllowed, mRemoveOnExit); 3319 if (!cleanupOnResume || mRemoveOnExit) { 3320 destroySurfaceUnchecked(); 3321 } 3322 if (mRemoveOnExit) { 3323 removeImmediately(); 3324 } 3325 if (cleanupOnResume) { 3326 requestUpdateWallpaperIfNeeded(); 3327 } 3328 mDestroying = false; 3329 destroyedSomething = true; 3330 3331 // Since mDestroying will affect ActivityRecord#allDrawn, we need to perform another 3332 // traversal in case we are waiting on this window to start the transition. 3333 if (getDisplayContent().mAppTransition.isTransitionSet() 3334 && getDisplayContent().mOpeningApps.contains(mActivityRecord)) { 3335 mWmService.mWindowPlacerLocked.requestTraversal(); 3336 } 3337 } 3338 3339 return destroyedSomething; 3340 } 3341 3342 // Destroy or save the application surface without checking 3343 // various indicators of whether the client has released the surface. 3344 // This is in general unsafe, and most callers should use {@link #destroySurface} destroySurfaceUnchecked()3345 void destroySurfaceUnchecked() { 3346 mWinAnimator.destroySurfaceLocked(mTmpTransaction); 3347 mTmpTransaction.apply(); 3348 3349 // Clear animating flags now, since the surface is now gone. (Note this is true even 3350 // if the surface is saved, to outside world the surface is still NO_SURFACE.) 3351 mAnimatingExit = false; 3352 ProtoLog.d(WM_DEBUG_ANIM, "Clear animatingExit: reason=destroySurface win=%s", this); 3353 3354 if (syncNextBuffer()) { 3355 immediatelyNotifyBlastSync(); 3356 } 3357 } 3358 onSurfaceShownChanged(boolean shown)3359 void onSurfaceShownChanged(boolean shown) { 3360 if (mLastShownChangedReported == shown) { 3361 return; 3362 } 3363 mLastShownChangedReported = shown; 3364 3365 if (shown) { 3366 initExclusionRestrictions(); 3367 } else { 3368 logExclusionRestrictions(EXCLUSION_LEFT); 3369 logExclusionRestrictions(EXCLUSION_RIGHT); 3370 getDisplayContent().removeImeSurfaceByTarget(this); 3371 } 3372 // Exclude toast because legacy apps may show toast window by themselves, so the misused 3373 // apps won't always be considered as foreground state. 3374 // Exclude private presentations as they can only be shown on private virtual displays and 3375 // shouldn't be the cause of an app be considered foreground. 3376 // Exclude presentations on virtual displays as they are not actually visible. 3377 if (mAttrs.type >= FIRST_SYSTEM_WINDOW 3378 && mAttrs.type != TYPE_TOAST 3379 && mAttrs.type != TYPE_PRIVATE_PRESENTATION 3380 && !(mAttrs.type == TYPE_PRESENTATION && isOnVirtualDisplay()) 3381 ) { 3382 mWmService.mAtmService.mActiveUids.onNonAppSurfaceVisibilityChanged(mOwnerUid, shown); 3383 } 3384 } 3385 isOnVirtualDisplay()3386 private boolean isOnVirtualDisplay() { 3387 return getDisplayContent().mDisplay.getType() == Display.TYPE_VIRTUAL; 3388 } 3389 logExclusionRestrictions(int side)3390 private void logExclusionRestrictions(int side) { 3391 if (!logsGestureExclusionRestrictions(this) 3392 || SystemClock.uptimeMillis() < mLastExclusionLogUptimeMillis[side] 3393 + mWmService.mConstants.mSystemGestureExclusionLogDebounceTimeoutMillis) { 3394 // Drop the log if we have just logged; this is okay, because what we would have logged 3395 // was true only for a short duration. 3396 return; 3397 } 3398 3399 final long now = SystemClock.uptimeMillis(); 3400 final long duration = now - mLastExclusionLogUptimeMillis[side]; 3401 mLastExclusionLogUptimeMillis[side] = now; 3402 3403 final int requested = mLastRequestedExclusionHeight[side]; 3404 final int granted = mLastGrantedExclusionHeight[side]; 3405 3406 FrameworkStatsLog.write(FrameworkStatsLog.EXCLUSION_RECT_STATE_CHANGED, 3407 mAttrs.packageName, requested, requested - granted /* rejected */, 3408 side + 1 /* Sides are 1-indexed in atoms.proto */, 3409 (getConfiguration().orientation == ORIENTATION_LANDSCAPE), 3410 false /* (deprecated param) inSplitscreen */, (int) duration); 3411 } 3412 initExclusionRestrictions()3413 private void initExclusionRestrictions() { 3414 final long now = SystemClock.uptimeMillis(); 3415 mLastExclusionLogUptimeMillis[EXCLUSION_LEFT] = now; 3416 mLastExclusionLogUptimeMillis[EXCLUSION_RIGHT] = now; 3417 } 3418 3419 /** @return {@code true} if this window can be shown to all users. */ showForAllUsers()3420 boolean showForAllUsers() { 3421 3422 // If this switch statement is modified, modify the comment in the declarations of 3423 // the type in {@link WindowManager.LayoutParams} as well. 3424 switch (mAttrs.type) { 3425 default: 3426 // These are the windows that by default are shown only to the user that created 3427 // them. If this needs to be overridden, set 3428 // {@link WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS} in 3429 // {@link WindowManager.LayoutParams}. Note that permission 3430 // {@link android.Manifest.permission.INTERNAL_SYSTEM_WINDOW} is required as well. 3431 if ((mAttrs.privateFlags & SYSTEM_FLAG_SHOW_FOR_ALL_USERS) == 0) { 3432 return false; 3433 } 3434 break; 3435 3436 // These are the windows that by default are shown to all users. However, to 3437 // protect against spoofing, check permissions below. 3438 case TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY: 3439 case TYPE_APPLICATION_STARTING: 3440 case TYPE_BOOT_PROGRESS: 3441 case TYPE_DISPLAY_OVERLAY: 3442 case TYPE_INPUT_CONSUMER: 3443 case TYPE_KEYGUARD_DIALOG: 3444 case TYPE_MAGNIFICATION_OVERLAY: 3445 case TYPE_NAVIGATION_BAR: 3446 case TYPE_NAVIGATION_BAR_PANEL: 3447 case TYPE_PHONE: 3448 case TYPE_POINTER: 3449 case TYPE_PRIORITY_PHONE: 3450 case TYPE_SEARCH_BAR: 3451 case TYPE_STATUS_BAR: 3452 case TYPE_NOTIFICATION_SHADE: 3453 case TYPE_STATUS_BAR_ADDITIONAL: 3454 case TYPE_STATUS_BAR_SUB_PANEL: 3455 case TYPE_SYSTEM_DIALOG: 3456 case TYPE_VOLUME_OVERLAY: 3457 case TYPE_PRESENTATION: 3458 case TYPE_PRIVATE_PRESENTATION: 3459 case TYPE_DOCK_DIVIDER: 3460 break; 3461 } 3462 3463 // Only the system can show free windows to all users. 3464 return mOwnerCanAddInternalSystemWindow; 3465 3466 } 3467 3468 @Override showToCurrentUser()3469 boolean showToCurrentUser() { 3470 // Child windows are evaluated based on their parent window. 3471 final WindowState win = getTopParentWindow(); 3472 if (win.mAttrs.type < FIRST_SYSTEM_WINDOW 3473 && win.mActivityRecord != null && win.mActivityRecord.mShowForAllUsers) { 3474 3475 // All window frames that are fullscreen extend above status bar, but some don't extend 3476 // below navigation bar. Thus, check for display frame for top/left and stable frame for 3477 // bottom right. 3478 if (win.getFrame().left <= win.getDisplayFrame().left 3479 && win.getFrame().top <= win.getDisplayFrame().top 3480 && win.getFrame().right >= win.getDisplayFrame().right 3481 && win.getFrame().bottom >= win.getDisplayFrame().bottom) { 3482 // Is a fullscreen window, like the clock alarm. Show to everyone. 3483 return true; 3484 } 3485 } 3486 3487 return win.showForAllUsers() 3488 || mWmService.isUserVisible(win.mShowUserId); 3489 } 3490 applyInsets(Region outRegion, Rect frame, Rect inset)3491 private static void applyInsets(Region outRegion, Rect frame, Rect inset) { 3492 outRegion.set( 3493 frame.left + inset.left, frame.top + inset.top, 3494 frame.right - inset.right, frame.bottom - inset.bottom); 3495 } 3496 3497 /** Get the touchable region in global coordinates. */ getTouchableRegion(Region outRegion)3498 void getTouchableRegion(Region outRegion) { 3499 final Rect frame = mWindowFrames.mFrame; 3500 switch (mTouchableInsets) { 3501 default: 3502 case TOUCHABLE_INSETS_FRAME: 3503 outRegion.set(frame); 3504 break; 3505 case TOUCHABLE_INSETS_CONTENT: 3506 applyInsets(outRegion, frame, mGivenContentInsets); 3507 break; 3508 case TOUCHABLE_INSETS_VISIBLE: 3509 applyInsets(outRegion, frame, mGivenVisibleInsets); 3510 break; 3511 case TOUCHABLE_INSETS_REGION: { 3512 outRegion.set(mGivenTouchableRegion); 3513 if (frame.left != 0 || frame.top != 0) { 3514 outRegion.translate(frame.left, frame.top); 3515 } 3516 break; 3517 } 3518 } 3519 cropRegionToRootTaskBoundsIfNeeded(outRegion); 3520 subtractTouchExcludeRegionIfNeeded(outRegion); 3521 } 3522 3523 /** 3524 * Get the effective touchable region in global coordinates. 3525 * 3526 * In contrast to {@link #getTouchableRegion}, this takes into account 3527 * {@link WindowManager.LayoutParams#FLAG_NOT_TOUCH_MODAL touch modality.} 3528 */ getEffectiveTouchableRegion(Region outRegion)3529 void getEffectiveTouchableRegion(Region outRegion) { 3530 final DisplayContent dc = getDisplayContent(); 3531 3532 if (mAttrs.isModal() && dc != null) { 3533 outRegion.set(dc.getBounds()); 3534 cropRegionToRootTaskBoundsIfNeeded(outRegion); 3535 subtractTouchExcludeRegionIfNeeded(outRegion); 3536 } else { 3537 getTouchableRegion(outRegion); 3538 } 3539 } 3540 cropRegionToRootTaskBoundsIfNeeded(Region region)3541 private void cropRegionToRootTaskBoundsIfNeeded(Region region) { 3542 final Task task = getTask(); 3543 if (task == null || !task.cropWindowsToRootTaskBounds()) { 3544 return; 3545 } 3546 3547 final Task rootTask = task.getRootTask(); 3548 if (rootTask == null || rootTask.mCreatedByOrganizer) { 3549 return; 3550 } 3551 3552 rootTask.getDimBounds(mTmpRect); 3553 adjustRegionInFreefromWindowMode(mTmpRect); 3554 region.op(mTmpRect, Region.Op.INTERSECT); 3555 } 3556 3557 /** 3558 * If this window has areas that cannot be touched, we subtract those areas from its touchable 3559 * region. 3560 */ subtractTouchExcludeRegionIfNeeded(Region touchableRegion)3561 private void subtractTouchExcludeRegionIfNeeded(Region touchableRegion) { 3562 if (mTapExcludeRegion.isEmpty()) { 3563 return; 3564 } 3565 final Region touchExcludeRegion = Region.obtain(); 3566 getTapExcludeRegion(touchExcludeRegion); 3567 if (!touchExcludeRegion.isEmpty()) { 3568 touchableRegion.op(touchExcludeRegion, Region.Op.DIFFERENCE); 3569 } 3570 touchExcludeRegion.recycle(); 3571 } 3572 3573 /** 3574 * Report a focus change. Must be called with no locks held, and consistently 3575 * from the same serialized thread (such as dispatched from a handler). 3576 */ reportFocusChangedSerialized(boolean focused)3577 void reportFocusChangedSerialized(boolean focused) { 3578 if (mFocusCallbacks != null) { 3579 final int N = mFocusCallbacks.beginBroadcast(); 3580 for (int i=0; i<N; i++) { 3581 IWindowFocusObserver obs = mFocusCallbacks.getBroadcastItem(i); 3582 try { 3583 if (focused) { 3584 obs.focusGained(mWindowId.asBinder()); 3585 } else { 3586 obs.focusLost(mWindowId.asBinder()); 3587 } 3588 } catch (RemoteException e) { 3589 } 3590 } 3591 mFocusCallbacks.finishBroadcast(); 3592 } 3593 } 3594 3595 @Override getConfiguration()3596 public Configuration getConfiguration() { 3597 // If the process has not registered to any display area to listen to the configuration 3598 // change, we can simply return the mFullConfiguration as default. 3599 if (!registeredForDisplayAreaConfigChanges()) { 3600 return super.getConfiguration(); 3601 } 3602 3603 // We use the process config this window is associated with as the based global config since 3604 // the process can override its config, but isn't part of the window hierarchy. 3605 mTempConfiguration.setTo(getProcessGlobalConfiguration()); 3606 mTempConfiguration.updateFrom(getMergedOverrideConfiguration()); 3607 return mTempConfiguration; 3608 } 3609 3610 /** @return {@code true} if the process registered to a display area as a config listener. */ registeredForDisplayAreaConfigChanges()3611 private boolean registeredForDisplayAreaConfigChanges() { 3612 final WindowState parentWindow = getParentWindow(); 3613 final Session session = parentWindow != null ? parentWindow.mSession : mSession; 3614 if (session.mPid == MY_PID) { 3615 // System process cannot register to display area config change. 3616 return false; 3617 } 3618 return session.mProcess.registeredForDisplayAreaConfigChanges(); 3619 } 3620 3621 @NonNull getProcess()3622 WindowProcessController getProcess() { 3623 return mSession.mProcess; 3624 } 3625 3626 /** 3627 * Fills the given window frames and merged configuration for the client. 3628 * 3629 * @param outFrames The frames that will be sent to the client. 3630 * @param outMergedConfiguration The configuration that will be sent to the client. 3631 * @param outActivityWindowInfo The ActivityWindowInfo that will be sent to the client if set. 3632 * {@code null} if this is not activity window. 3633 * @param useLatestConfig Whether to use the latest configuration. 3634 * @param relayoutVisible Whether to consider visibility to use the latest configuration. 3635 */ fillClientWindowFramesAndConfiguration(@onNull ClientWindowFrames outFrames, @NonNull MergedConfiguration outMergedConfiguration, @Nullable ActivityWindowInfo outActivityWindowInfo, boolean useLatestConfig, boolean relayoutVisible)3636 void fillClientWindowFramesAndConfiguration(@NonNull ClientWindowFrames outFrames, 3637 @NonNull MergedConfiguration outMergedConfiguration, 3638 @Nullable ActivityWindowInfo outActivityWindowInfo, 3639 boolean useLatestConfig, boolean relayoutVisible) { 3640 outFrames.frame.set(mWindowFrames.mCompatFrame); 3641 outFrames.displayFrame.set(mWindowFrames.mDisplayFrame); 3642 if (mInvGlobalScale != 1f) { 3643 outFrames.displayFrame.scale(mInvGlobalScale); 3644 } 3645 if (mLayoutAttached) { 3646 if (outFrames.attachedFrame == null) { 3647 outFrames.attachedFrame = new Rect(); 3648 } 3649 outFrames.attachedFrame.set(getParentWindow().getFrame()); 3650 if (mInvGlobalScale != 1f) { 3651 outFrames.attachedFrame.scale(mInvGlobalScale); 3652 } 3653 } 3654 outFrames.compatScale = getCompatScaleForClient(); 3655 if (mLastReportedFrames != outFrames) { 3656 mLastReportedFrames.setTo(outFrames); 3657 } 3658 3659 // Note: in the cases where the window is tied to an activity, we should not send a 3660 // configuration update when the window has requested to be hidden. Doing so can lead to 3661 // the client erroneously accepting a configuration that would have otherwise caused an 3662 // activity restart. We instead hand back the last reported {@link MergedConfiguration}. 3663 if (useLatestConfig || (relayoutVisible && (mActivityRecord == null 3664 || mActivityRecord.isVisibleRequested()))) { 3665 final Configuration globalConfig = getProcessGlobalConfiguration(); 3666 final Configuration overrideConfig = getMergedOverrideConfiguration(); 3667 outMergedConfiguration.setConfiguration(globalConfig, overrideConfig); 3668 if (outMergedConfiguration != mLastReportedConfiguration) { 3669 mLastReportedConfiguration.setTo(outMergedConfiguration); 3670 } 3671 if (outActivityWindowInfo != null && mLastReportedActivityWindowInfo != null) { 3672 outActivityWindowInfo.set(mActivityRecord.getActivityWindowInfo()); 3673 mLastReportedActivityWindowInfo.set(outActivityWindowInfo); 3674 } 3675 } else { 3676 outMergedConfiguration.setTo(mLastReportedConfiguration); 3677 if (outActivityWindowInfo != null && mLastReportedActivityWindowInfo != null) { 3678 outActivityWindowInfo.set(mLastReportedActivityWindowInfo); 3679 } 3680 } 3681 mLastConfigReportedToClient = true; 3682 } 3683 fillInsetsState(@onNull InsetsState outInsetsState, boolean copySources)3684 void fillInsetsState(@NonNull InsetsState outInsetsState, boolean copySources) { 3685 outInsetsState.set(getCompatInsetsState(), copySources); 3686 if (outInsetsState != mLastReportedInsetsState) { 3687 // No need to copy for the recorded. 3688 mLastReportedInsetsState.set(outInsetsState, false /* copySources */); 3689 } 3690 } 3691 fillInsetsSourceControls(@onNull InsetsSourceControl.Array outArray, boolean copyControls)3692 void fillInsetsSourceControls(@NonNull InsetsSourceControl.Array outArray, 3693 boolean copyControls) { 3694 final InsetsSourceControl[] controls = 3695 getDisplayContent().getInsetsStateController().getControlsForDispatch(this); 3696 outArray.set(controls, copyControls); 3697 if (outArray != mLastReportedActiveControls) { 3698 // No need to copy for the recorded. 3699 mLastReportedActiveControls.setTo(outArray, false /* copyControls */); 3700 } 3701 } 3702 reportResized()3703 void reportResized() { 3704 // If the activity is scheduled to relaunch, skip sending the resized to ViewRootImpl now 3705 // since it will be destroyed anyway. This also prevents the client from receiving 3706 // windowing mode change before it is destroyed. 3707 if (inRelaunchingActivity()) { 3708 return; 3709 } 3710 // If this is an activity or wallpaper and is invisible or going invisible, don't report 3711 // either since it is going away. This is likely during a transition so we want to preserve 3712 // the original state. 3713 if (shouldCheckTokenVisibleRequested() && !mToken.isVisibleRequested()) { 3714 return; 3715 } 3716 3717 if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) { 3718 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "wm.reportResized_" + getWindowTag()); 3719 } 3720 3721 ProtoLog.v(WM_DEBUG_RESIZE, "Reporting new frame to %s: %s", this, 3722 mWindowFrames.mCompatFrame); 3723 final boolean drawPending = mWinAnimator.mDrawState == DRAW_PENDING; 3724 if (drawPending) { 3725 ProtoLog.i(WM_DEBUG_ORIENTATION, "Resizing %s WITH DRAW PENDING", this); 3726 } 3727 3728 // Always reset these states first, so if {@link IWindow#resized} fails, this 3729 // window won't be added to {@link WindowManagerService#mResizingWindows} and set 3730 // {@link #mOrientationChanging} to true again by {@link #updateResizingWindowIfNeeded} 3731 // that may cause WINDOW_FREEZE_TIMEOUT because resizing the client keeps failing. 3732 mDragResizingChangeReported = true; 3733 mWindowFrames.clearReportResizeHints(); 3734 3735 final int prevRotation = mLastReportedConfiguration 3736 .getMergedConfiguration().windowConfiguration.getRotation(); 3737 fillClientWindowFramesAndConfiguration(mLastReportedFrames, mLastReportedConfiguration, 3738 mLastReportedActivityWindowInfo, true /* useLatestConfig */, 3739 false /* relayoutVisible */); 3740 fillInsetsState(mLastReportedInsetsState, false /* copySources */); 3741 final boolean syncRedraw = shouldSendRedrawForSync(); 3742 final boolean syncWithBuffers = syncRedraw && shouldSyncWithBuffers(); 3743 final boolean reportDraw = syncRedraw || drawPending; 3744 final boolean isDragResizeChanged = isDragResizeChanged(); 3745 final boolean forceRelayout = syncWithBuffers || isDragResizeChanged; 3746 final DisplayContent displayContent = getDisplayContent(); 3747 final boolean alwaysConsumeSystemBars = 3748 displayContent.getDisplayPolicy().areSystemBarsForcedConsumedLw(); 3749 final int displayId = displayContent.getDisplayId(); 3750 3751 if (isDragResizeChanged) { 3752 setDragResizing(); 3753 } 3754 final boolean isDragResizing = isDragResizing(); 3755 3756 markRedrawForSyncReported(); 3757 3758 if (Flags.bundleClientTransactionFlag()) { 3759 getProcess().scheduleClientTransactionItem( 3760 WindowStateResizeItem.obtain(mClient, mLastReportedFrames, reportDraw, 3761 mLastReportedConfiguration, mLastReportedInsetsState, forceRelayout, 3762 alwaysConsumeSystemBars, displayId, 3763 syncWithBuffers ? mSyncSeqId : -1, isDragResizing, 3764 mLastReportedActivityWindowInfo)); 3765 onResizePostDispatched(drawPending, prevRotation, displayId); 3766 } else { 3767 // TODO(b/301870955): cleanup after launch 3768 try { 3769 mClient.resized(mLastReportedFrames, reportDraw, mLastReportedConfiguration, 3770 mLastReportedInsetsState, forceRelayout, alwaysConsumeSystemBars, displayId, 3771 syncWithBuffers ? mSyncSeqId : -1, isDragResizing, 3772 mLastReportedActivityWindowInfo); 3773 onResizePostDispatched(drawPending, prevRotation, displayId); 3774 } catch (RemoteException e) { 3775 // Cancel orientation change of this window to avoid blocking unfreeze display. 3776 setOrientationChanging(false); 3777 mLastFreezeDuration = (int) (SystemClock.elapsedRealtime() 3778 - mWmService.mDisplayFreezeTime); 3779 Slog.w(TAG, "Failed to report 'resized' to " + this + " due to " + e); 3780 } 3781 } 3782 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 3783 } 3784 onResizePostDispatched(boolean drawPending, int prevRotation, int displayId)3785 private void onResizePostDispatched(boolean drawPending, int prevRotation, int displayId) { 3786 if (drawPending && prevRotation >= 0 && prevRotation != mLastReportedConfiguration 3787 .getMergedConfiguration().windowConfiguration.getRotation()) { 3788 mOrientationChangeRedrawRequestTime = SystemClock.elapsedRealtime(); 3789 ProtoLog.v(WM_DEBUG_ORIENTATION, 3790 "Requested redraw for orientation change: %s", this); 3791 } 3792 3793 if (mWmService.mAccessibilityController.hasCallbacks()) { 3794 mWmService.mAccessibilityController.onSomeWindowResizedOrMoved(displayId); 3795 } 3796 } 3797 inRelaunchingActivity()3798 boolean inRelaunchingActivity() { 3799 return mActivityRecord != null && mActivityRecord.isRelaunching(); 3800 } 3801 isClientLocal()3802 boolean isClientLocal() { 3803 return mClient instanceof IWindow.Stub; 3804 } 3805 consumeInsetsChange()3806 private void consumeInsetsChange() { 3807 if (mWindowFrames.hasInsetsChanged()) { 3808 mWindowFrames.setInsetsChanged(false); 3809 mWmService.mWindowsInsetsChanged--; 3810 if (mWmService.mWindowsInsetsChanged == 0) { 3811 mWmService.mH.removeMessages(WindowManagerService.H.INSETS_CHANGED); 3812 } 3813 } 3814 } 3815 3816 /** 3817 * Called when the insets state changed. 3818 */ notifyInsetsChanged()3819 void notifyInsetsChanged() { 3820 ProtoLog.d(WM_DEBUG_WINDOW_INSETS, "notifyInsetsChanged for %s ", this); 3821 if (!mWindowFrames.hasInsetsChanged()) { 3822 mWindowFrames.setInsetsChanged(true); 3823 mWmService.mWindowsInsetsChanged++; 3824 3825 // If the new InsetsState won't be dispatched before releasing WM lock, the following 3826 // message will be executed. 3827 mWmService.mH.removeMessages(WindowManagerService.H.INSETS_CHANGED); 3828 mWmService.mH.sendEmptyMessage(WindowManagerService.H.INSETS_CHANGED); 3829 } 3830 3831 final WindowContainer p = getParent(); 3832 if (p != null) { 3833 p.updateOverlayInsetsState(this); 3834 } 3835 } 3836 3837 @Override notifyInsetsControlChanged(int displayId)3838 public void notifyInsetsControlChanged(int displayId) { 3839 ProtoLog.d(WM_DEBUG_WINDOW_INSETS, "notifyInsetsControlChanged for %s ", this); 3840 if (mRemoved) { 3841 return; 3842 } 3843 fillInsetsState(mLastReportedInsetsState, false /* copySources */); 3844 fillInsetsSourceControls(mLastReportedActiveControls, false /* copyControls */); 3845 if (Flags.insetsControlChangedItem()) { 3846 getProcess().scheduleClientTransactionItem(WindowStateInsetsControlChangeItem.obtain( 3847 mClient, mLastReportedInsetsState, mLastReportedActiveControls)); 3848 } else { 3849 try { 3850 mClient.insetsControlChanged(mLastReportedInsetsState, mLastReportedActiveControls); 3851 } catch (RemoteException e) { 3852 Slog.w(TAG, "Failed to deliver inset control state change to w=" + this, e); 3853 } 3854 } 3855 } 3856 3857 @Override getWindow()3858 public WindowState getWindow() { 3859 return this; 3860 } 3861 3862 @Override showInsets(@nsetsType int types, boolean fromIme, @Nullable ImeTracker.Token statsToken)3863 public void showInsets(@InsetsType int types, boolean fromIme, 3864 @Nullable ImeTracker.Token statsToken) { 3865 try { 3866 ImeTracker.forLogging().onProgress(statsToken, 3867 ImeTracker.PHASE_WM_WINDOW_INSETS_CONTROL_TARGET_SHOW_INSETS); 3868 mClient.showInsets(types, fromIme, statsToken); 3869 } catch (RemoteException e) { 3870 Slog.w(TAG, "Failed to deliver showInsets", e); 3871 ImeTracker.forLogging().onFailed(statsToken, 3872 ImeTracker.PHASE_WM_WINDOW_INSETS_CONTROL_TARGET_SHOW_INSETS); 3873 } 3874 } 3875 3876 @Override hideInsets(@nsetsType int types, boolean fromIme, @Nullable ImeTracker.Token statsToken)3877 public void hideInsets(@InsetsType int types, boolean fromIme, 3878 @Nullable ImeTracker.Token statsToken) { 3879 try { 3880 ImeTracker.forLogging().onProgress(statsToken, 3881 ImeTracker.PHASE_WM_WINDOW_INSETS_CONTROL_TARGET_HIDE_INSETS); 3882 mClient.hideInsets(types, fromIme, statsToken); 3883 } catch (RemoteException e) { 3884 Slog.w(TAG, "Failed to deliver hideInsets", e); 3885 ImeTracker.forLogging().onFailed(statsToken, 3886 ImeTracker.PHASE_WM_WINDOW_INSETS_CONTROL_TARGET_HIDE_INSETS); 3887 } 3888 } 3889 3890 @Override canShowTransient()3891 public boolean canShowTransient() { 3892 return (mAttrs.insetsFlags.behavior & BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE) != 0; 3893 } 3894 canBeHiddenByKeyguard()3895 boolean canBeHiddenByKeyguard() { 3896 // Keyguard visibility of window from activities are determined over activity visibility. 3897 if (mActivityRecord != null) { 3898 return false; 3899 } 3900 switch (mAttrs.type) { 3901 case TYPE_NOTIFICATION_SHADE: 3902 case TYPE_STATUS_BAR: 3903 case TYPE_NAVIGATION_BAR: 3904 case TYPE_WALLPAPER: 3905 return false; 3906 default: 3907 // Hide only windows below the keyguard host window. 3908 return mPolicy.getWindowLayerLw(this) 3909 < mPolicy.getWindowLayerFromTypeLw(TYPE_NOTIFICATION_SHADE); 3910 } 3911 } 3912 getRootTaskId()3913 private int getRootTaskId() { 3914 final Task rootTask = getRootTask(); 3915 if (rootTask == null) { 3916 return INVALID_TASK_ID; 3917 } 3918 return rootTask.mTaskId; 3919 } 3920 registerFocusObserver(IWindowFocusObserver observer)3921 public void registerFocusObserver(IWindowFocusObserver observer) { 3922 synchronized (mWmService.mGlobalLock) { 3923 if (mFocusCallbacks == null) { 3924 mFocusCallbacks = new RemoteCallbackList<IWindowFocusObserver>(); 3925 } 3926 mFocusCallbacks.register(observer); 3927 } 3928 } 3929 unregisterFocusObserver(IWindowFocusObserver observer)3930 public void unregisterFocusObserver(IWindowFocusObserver observer) { 3931 synchronized (mWmService.mGlobalLock) { 3932 if (mFocusCallbacks != null) { 3933 mFocusCallbacks.unregister(observer); 3934 } 3935 } 3936 } 3937 isFocused()3938 boolean isFocused() { 3939 return getDisplayContent().mCurrentFocus == this; 3940 } 3941 3942 /** 3943 * Returns {@code true} if activity bounds are letterboxed or letterboxed for display cutout. 3944 * 3945 * <p>Note that letterbox UI may not be shown even when this returns {@code true}. See {@link 3946 * LetterboxUiController#shouldShowLetterboxUi} for more context. 3947 */ areAppWindowBoundsLetterboxed()3948 boolean areAppWindowBoundsLetterboxed() { 3949 return mActivityRecord != null && !isStartingWindowAssociatedToTask() 3950 && (mActivityRecord.areBoundsLetterboxed() || isLetterboxedForDisplayCutout()); 3951 } 3952 3953 /** Returns {@code true} if the window is letterboxed for the display cutout. */ isLetterboxedForDisplayCutout()3954 boolean isLetterboxedForDisplayCutout() { 3955 if (mActivityRecord == null) { 3956 // Only windows with an ActivityRecord are letterboxed. 3957 return false; 3958 } 3959 if (!mWindowFrames.parentFrameWasClippedByDisplayCutout()) { 3960 // Cutout didn't make a difference, no letterbox 3961 return false; 3962 } 3963 if (mAttrs.layoutInDisplayCutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS) { 3964 // Layout in cutout, no letterbox. 3965 return false; 3966 } 3967 if (!mAttrs.isFullscreen()) { 3968 // Not filling the parent frame, no letterbox 3969 return false; 3970 } 3971 // Otherwise we need a letterbox if the layout was smaller than the app window token allowed 3972 // it to be. 3973 return !frameCoversEntireAppTokenBounds(); 3974 } 3975 3976 /** 3977 * @return true if this window covers the entire bounds of its app window token 3978 * @throws NullPointerException if there is no app window token for this window 3979 */ frameCoversEntireAppTokenBounds()3980 private boolean frameCoversEntireAppTokenBounds() { 3981 mTmpRect.set(mActivityRecord.getBounds()); 3982 mTmpRect.intersectUnchecked(mWindowFrames.mFrame); 3983 return mActivityRecord.getBounds().equals(mTmpRect); 3984 } 3985 3986 /** 3987 * @return {@code true} if bar shown within a given frame is allowed to be fully transparent 3988 * when the current window is displayed. 3989 */ isFullyTransparentBarAllowed(Rect frame)3990 boolean isFullyTransparentBarAllowed(Rect frame) { 3991 return mActivityRecord == null || mActivityRecord.isFullyTransparentBarAllowed(frame); 3992 } 3993 isDragResizeChanged()3994 boolean isDragResizeChanged() { 3995 return mDragResizing != computeDragResizing(); 3996 } 3997 3998 /** 3999 * Resets the state whether we reported a drag resize change to the app. 4000 */ 4001 @Override resetDragResizingChangeReported()4002 void resetDragResizingChangeReported() { 4003 mDragResizingChangeReported = false; 4004 super.resetDragResizingChangeReported(); 4005 } 4006 computeDragResizing()4007 private boolean computeDragResizing() { 4008 final Task task = getTask(); 4009 if (task == null) { 4010 return false; 4011 } 4012 if (!inFreeformWindowingMode() && !task.getRootTask().mCreatedByOrganizer) { 4013 return false; 4014 } 4015 // TODO(157912944): formalize drag-resizing so that exceptions aren't hardcoded like this 4016 if (task.getActivityType() == ACTIVITY_TYPE_HOME) { 4017 // The current sys-ui implementations never live-resize home, so to prevent WSA from 4018 // creating/destroying surfaces (which messes up sync-transactions), skip HOME tasks. 4019 return false; 4020 } 4021 if (mAttrs.width != MATCH_PARENT || mAttrs.height != MATCH_PARENT) { 4022 // Floating windows never enter drag resize mode. 4023 return false; 4024 } 4025 if (task.isDragResizing()) { 4026 return true; 4027 } 4028 4029 return false; 4030 } 4031 setDragResizing()4032 void setDragResizing() { 4033 final boolean resizing = computeDragResizing(); 4034 if (resizing == mDragResizing) { 4035 return; 4036 } 4037 mDragResizing = resizing; 4038 } 4039 isDragResizing()4040 boolean isDragResizing() { 4041 return mDragResizing; 4042 } 4043 4044 @CallSuper 4045 @Override dumpDebug(ProtoOutputStream proto, long fieldId, @WindowTraceLogLevel int logLevel)4046 public void dumpDebug(ProtoOutputStream proto, long fieldId, 4047 @WindowTraceLogLevel int logLevel) { 4048 boolean isVisible = isVisible(); 4049 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible) { 4050 return; 4051 } 4052 4053 final long token = proto.start(fieldId); 4054 super.dumpDebug(proto, WINDOW_CONTAINER, logLevel); 4055 proto.write(DISPLAY_ID, getDisplayId()); 4056 proto.write(STACK_ID, getRootTaskId()); 4057 mAttrs.dumpDebug(proto, ATTRIBUTES); 4058 mGivenContentInsets.dumpDebug(proto, GIVEN_CONTENT_INSETS); 4059 mWindowFrames.dumpDebug(proto, WINDOW_FRAMES); 4060 mAttrs.surfaceInsets.dumpDebug(proto, SURFACE_INSETS); 4061 dumpPointProto(mSurfacePosition, proto, SURFACE_POSITION); 4062 mWinAnimator.dumpDebug(proto, ANIMATOR); 4063 proto.write(ANIMATING_EXIT, mAnimatingExit); 4064 proto.write(REQUESTED_WIDTH, mRequestedWidth); 4065 proto.write(REQUESTED_HEIGHT, mRequestedHeight); 4066 proto.write(VIEW_VISIBILITY, mViewVisibility); 4067 proto.write(HAS_SURFACE, mHasSurface); 4068 proto.write(IS_READY_FOR_DISPLAY, isReadyForDisplay()); 4069 proto.write(REMOVE_ON_EXIT, mRemoveOnExit); 4070 proto.write(DESTROYING, mDestroying); 4071 proto.write(REMOVED, mRemoved); 4072 proto.write(IS_ON_SCREEN, isOnScreen()); 4073 proto.write(IS_VISIBLE, isVisible); 4074 proto.write(PENDING_SEAMLESS_ROTATION, mPendingSeamlessRotate != null); 4075 proto.write(FORCE_SEAMLESS_ROTATION, mForceSeamlesslyRotate); 4076 proto.write(HAS_COMPAT_SCALE, hasCompatScale()); 4077 proto.write(GLOBAL_SCALE, mGlobalScale); 4078 proto.write(REQUESTED_VISIBLE_TYPES, mRequestedVisibleTypes); 4079 for (Rect r : mKeepClearAreas) { 4080 r.dumpDebug(proto, KEEP_CLEAR_AREAS); 4081 } 4082 for (Rect r : mUnrestrictedKeepClearAreas) { 4083 r.dumpDebug(proto, UNRESTRICTED_KEEP_CLEAR_AREAS); 4084 } 4085 if (mMergedLocalInsetsSources != null) { 4086 for (int i = 0; i < mMergedLocalInsetsSources.size(); ++i) { 4087 mMergedLocalInsetsSources.valueAt(i).dumpDebug(proto, MERGED_LOCAL_INSETS_SOURCES); 4088 } 4089 } 4090 proto.end(token); 4091 } 4092 4093 @Override getProtoFieldId()4094 long getProtoFieldId() { 4095 return WINDOW; 4096 } 4097 4098 @Override writeIdentifierToProto(ProtoOutputStream proto, long fieldId)4099 public void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) { 4100 final long token = proto.start(fieldId); 4101 proto.write(HASH_CODE, System.identityHashCode(this)); 4102 proto.write(USER_ID, mShowUserId); 4103 final CharSequence title = getWindowTag(); 4104 if (title != null) { 4105 proto.write(TITLE, title.toString()); 4106 } 4107 proto.end(token); 4108 } 4109 4110 @NeverCompile // Avoid size overhead of debugging code. 4111 @Override dump(PrintWriter pw, String prefix, boolean dumpAll)4112 void dump(PrintWriter pw, String prefix, boolean dumpAll) { 4113 pw.print(prefix + "mDisplayId=" + getDisplayId()); 4114 if (getRootTask() != null) { 4115 pw.print(" rootTaskId=" + getRootTaskId()); 4116 } 4117 pw.println(" mSession=" + mSession 4118 + " mClient=" + mClient.asBinder()); 4119 pw.println(prefix + "mOwnerUid=" + mOwnerUid 4120 + " showForAllUsers=" + showForAllUsers() 4121 + " package=" + mAttrs.packageName 4122 + " appop=" + AppOpsManager.opToName(mAppOp)); 4123 pw.println(prefix + "mAttrs=" + mAttrs.toString(prefix)); 4124 pw.println(prefix + "Requested w=" + mRequestedWidth 4125 + " h=" + mRequestedHeight 4126 + " mLayoutSeq=" + mLayoutSeq); 4127 if (mRequestedWidth != mLastRequestedWidth || mRequestedHeight != mLastRequestedHeight) { 4128 pw.println(prefix + "LastRequested w=" + mLastRequestedWidth 4129 + " h=" + mLastRequestedHeight); 4130 } 4131 if (mIsChildWindow || mLayoutAttached) { 4132 pw.println(prefix + "mParentWindow=" + getParentWindow() 4133 + " mLayoutAttached=" + mLayoutAttached); 4134 } 4135 if (mIsImWindow || mIsWallpaper || mIsFloatingLayer) { 4136 pw.println(prefix + "mIsImWindow=" + mIsImWindow 4137 + " mIsWallpaper=" + mIsWallpaper 4138 + " mIsFloatingLayer=" + mIsFloatingLayer); 4139 } 4140 if (dumpAll) { 4141 pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer); 4142 pw.print(" mSubLayer="); pw.print(mSubLayer); 4143 } 4144 if (dumpAll) { 4145 pw.println(prefix + "mToken=" + mToken); 4146 if (mActivityRecord != null) { 4147 pw.println(prefix + "mActivityRecord=" + mActivityRecord); 4148 pw.print(prefix + "drawnStateEvaluated=" + getDrawnStateEvaluated()); 4149 pw.println(prefix + "mightAffectAllDrawn=" + mightAffectAllDrawn()); 4150 } 4151 pw.println(prefix + "mViewVisibility=0x" + Integer.toHexString(mViewVisibility) 4152 + " mHaveFrame=" + mHaveFrame 4153 + " mObscured=" + mObscured); 4154 if (mDisableFlags != 0) { 4155 pw.println(prefix + "mDisableFlags=" + ViewDebug.flagsToString( 4156 View.class, "mSystemUiVisibility", mDisableFlags)); 4157 } 4158 } 4159 if (!isVisibleByPolicy() || !mLegacyPolicyVisibilityAfterAnim || !mAppOpVisibility 4160 || isParentWindowHidden() || mPermanentlyHidden || mForceHideNonSystemOverlayWindow 4161 || mHiddenWhileSuspended) { 4162 pw.println(prefix + "mPolicyVisibility=" + isVisibleByPolicy() 4163 + " mLegacyPolicyVisibilityAfterAnim=" + mLegacyPolicyVisibilityAfterAnim 4164 + " mAppOpVisibility=" + mAppOpVisibility 4165 + " parentHidden=" + isParentWindowHidden() 4166 + " mPermanentlyHidden=" + mPermanentlyHidden 4167 + " mHiddenWhileSuspended=" + mHiddenWhileSuspended 4168 + " mForceHideNonSystemOverlayWindow=" + mForceHideNonSystemOverlayWindow); 4169 } 4170 if (!mRelayoutCalled || mLayoutNeeded) { 4171 pw.println(prefix + "mRelayoutCalled=" + mRelayoutCalled 4172 + " mLayoutNeeded=" + mLayoutNeeded); 4173 } 4174 if (dumpAll) { 4175 pw.println(prefix + "mGivenContentInsets=" + mGivenContentInsets.toShortString(sTmpSB) 4176 + " mGivenVisibleInsets=" + mGivenVisibleInsets.toShortString(sTmpSB)); 4177 if (mTouchableInsets != 0 || mGivenInsetsPending) { 4178 pw.println(prefix + "mTouchableInsets=" + mTouchableInsets 4179 + " mGivenInsetsPending=" + mGivenInsetsPending); 4180 Region region = new Region(); 4181 getTouchableRegion(region); 4182 pw.println(prefix + "touchable region=" + region); 4183 } 4184 pw.println(prefix + "mFullConfiguration=" + getConfiguration()); 4185 pw.println(prefix + "mLastReportedConfiguration=" + getLastReportedConfiguration()); 4186 if (mLastReportedActivityWindowInfo != null) { 4187 pw.println(prefix + "mLastReportedActivityWindowInfo=" 4188 + mLastReportedActivityWindowInfo); 4189 } 4190 } 4191 pw.println(prefix + "mHasSurface=" + mHasSurface 4192 + " isReadyForDisplay()=" + isReadyForDisplay() 4193 + " mWindowRemovalAllowed=" + mWindowRemovalAllowed); 4194 if (mIsSurfacePositionPaused) { 4195 pw.println(prefix + "mIsSurfacePositionPaused=true"); 4196 } 4197 if (mInvGlobalScale != 1f) { 4198 pw.println(prefix + "mCompatFrame=" + mWindowFrames.mCompatFrame.toShortString(sTmpSB)); 4199 } 4200 if (dumpAll) { 4201 mWindowFrames.dump(pw, prefix); 4202 pw.println(prefix + " surface=" + mAttrs.surfaceInsets.toShortString(sTmpSB)); 4203 } 4204 super.dump(pw, prefix, dumpAll); 4205 pw.println(prefix + mWinAnimator + ":"); 4206 mWinAnimator.dump(pw, prefix + " ", dumpAll); 4207 if (mAnimatingExit || mRemoveOnExit || mDestroying || mRemoved) { 4208 pw.println(prefix + "mAnimatingExit=" + mAnimatingExit 4209 + " mRemoveOnExit=" + mRemoveOnExit 4210 + " mDestroying=" + mDestroying 4211 + " mRemoved=" + mRemoved); 4212 } 4213 if (getOrientationChanging() || mAppFreezing) { 4214 pw.println(prefix + "mOrientationChanging=" + mOrientationChanging 4215 + " configOrientationChanging=" 4216 + (getLastReportedConfiguration().orientation != getConfiguration().orientation) 4217 + " mAppFreezing=" + mAppFreezing); 4218 } 4219 if (mLastFreezeDuration != 0) { 4220 pw.print(prefix + "mLastFreezeDuration="); 4221 TimeUtils.formatDuration(mLastFreezeDuration, pw); 4222 pw.println(); 4223 } 4224 pw.print(prefix + "mForceSeamlesslyRotate=" + mForceSeamlesslyRotate 4225 + " seamlesslyRotate: pending="); 4226 if (mPendingSeamlessRotate != null) { 4227 mPendingSeamlessRotate.dump(pw); 4228 } else { 4229 pw.print("null"); 4230 } 4231 pw.println(); 4232 4233 if (mXOffset != 0 || mYOffset != 0) { 4234 pw.println(prefix + "mXOffset=" + mXOffset + " mYOffset=" + mYOffset); 4235 } 4236 if (mHScale != 1 || mVScale != 1) { 4237 pw.println(prefix + "mHScale=" + mHScale 4238 + " mVScale=" + mVScale); 4239 } 4240 if (mWallpaperX != -1 || mWallpaperY != -1) { 4241 pw.println(prefix + "mWallpaperX=" + mWallpaperX 4242 + " mWallpaperY=" + mWallpaperY); 4243 } 4244 if (mWallpaperXStep != -1 || mWallpaperYStep != -1) { 4245 pw.println(prefix + "mWallpaperXStep=" + mWallpaperXStep 4246 + " mWallpaperYStep=" + mWallpaperYStep); 4247 } 4248 if (mWallpaperZoomOut != -1) { 4249 pw.println(prefix + "mWallpaperZoomOut=" + mWallpaperZoomOut); 4250 } 4251 if (mWallpaperDisplayOffsetX != Integer.MIN_VALUE 4252 || mWallpaperDisplayOffsetY != Integer.MIN_VALUE) { 4253 pw.println(prefix + "mWallpaperDisplayOffsetX=" + mWallpaperDisplayOffsetX 4254 + " mWallpaperDisplayOffsetY=" + mWallpaperDisplayOffsetY); 4255 } 4256 if (mDrawLock != null) { 4257 pw.println(prefix + "mDrawLock=" + mDrawLock); 4258 } 4259 if (isDragResizing()) { 4260 pw.println(prefix + "isDragResizing=" + isDragResizing()); 4261 } 4262 if (computeDragResizing()) { 4263 pw.println(prefix + "computeDragResizing=" + computeDragResizing()); 4264 } 4265 if (mImeInsetsConsumed) { 4266 pw.println(prefix + "mImeInsetsConsumed=true"); 4267 } 4268 pw.println(prefix + "isOnScreen=" + isOnScreen()); 4269 pw.println(prefix + "isVisible=" + isVisible()); 4270 pw.println(prefix + "keepClearAreas: restricted=" + mKeepClearAreas 4271 + ", unrestricted=" + mUnrestrictedKeepClearAreas); 4272 if (dumpAll) { 4273 if (mRequestedVisibleTypes != WindowInsets.Type.defaultVisible()) { 4274 pw.println(prefix + "Requested non-default-visibility types: " 4275 + WindowInsets.Type.toString( 4276 mRequestedVisibleTypes ^ WindowInsets.Type.defaultVisible())); 4277 } 4278 } 4279 4280 pw.println(prefix + "mPrepareSyncSeqId=" + mPrepareSyncSeqId); 4281 } 4282 4283 @Override getName()4284 String getName() { 4285 return Integer.toHexString(System.identityHashCode(this)) 4286 + " " + getWindowTag(); 4287 } 4288 getWindowTag()4289 CharSequence getWindowTag() { 4290 CharSequence tag = mAttrs.getTitle(); 4291 if (tag == null || tag.length() <= 0) { 4292 tag = mAttrs.packageName; 4293 } 4294 return tag; 4295 } 4296 4297 @Override toString()4298 public String toString() { 4299 final CharSequence title = getWindowTag(); 4300 if (mStringNameCache == null || mLastTitle != title || mWasExiting != mAnimatingExit) { 4301 mLastTitle = title; 4302 mWasExiting = mAnimatingExit; 4303 mStringNameCache = "Window{" + Integer.toHexString(System.identityHashCode(this)) 4304 + " u" + mShowUserId 4305 + " " + mLastTitle + (mAnimatingExit ? " EXITING}" : "}"); 4306 } 4307 return mStringNameCache; 4308 } 4309 isChildWindow()4310 boolean isChildWindow() { 4311 return mIsChildWindow; 4312 } 4313 4314 /** 4315 * Returns true if any window added by an application process that if of type 4316 * {@link android.view.WindowManager.LayoutParams#TYPE_TOAST} or that requires that requires 4317 * {@link android.app.AppOpsManager#OP_SYSTEM_ALERT_WINDOW} permission should be hidden when 4318 * this window is visible. 4319 */ hideNonSystemOverlayWindowsWhenVisible()4320 boolean hideNonSystemOverlayWindowsWhenVisible() { 4321 return (mAttrs.privateFlags & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0 4322 && mSession.mCanHideNonSystemOverlayWindows; 4323 } 4324 4325 /** Returns the parent window if this is a child of another window, else null. */ getParentWindow()4326 WindowState getParentWindow() { 4327 // NOTE: We are not calling getParent() directly as the WindowState might be a child of a 4328 // WindowContainer that isn't a WindowState. 4329 return (mIsChildWindow) ? ((WindowState) super.getParent()) : null; 4330 } 4331 4332 /** Returns the topmost parent window if this is a child of another window, else this. */ getTopParentWindow()4333 WindowState getTopParentWindow() { 4334 WindowState current = this; 4335 WindowState topParent = current; 4336 while (current != null && current.mIsChildWindow) { 4337 current = current.getParentWindow(); 4338 // Parent window can be null if the child is detached from it's parent already, but 4339 // someone still has a reference to access it. So, we return the top parent value we 4340 // already have instead of null. 4341 if (current != null) { 4342 topParent = current; 4343 } 4344 } 4345 return topParent; 4346 } 4347 isParentWindowHidden()4348 boolean isParentWindowHidden() { 4349 final WindowState parent = getParentWindow(); 4350 return parent != null && parent.mHidden; 4351 } 4352 isParentWindowGoneForLayout()4353 private boolean isParentWindowGoneForLayout() { 4354 final WindowState parent = getParentWindow(); 4355 return parent != null && parent.isGoneForLayout(); 4356 } 4357 requestUpdateWallpaperIfNeeded()4358 void requestUpdateWallpaperIfNeeded() { 4359 final DisplayContent dc = getDisplayContent(); 4360 if (dc != null && ((mIsWallpaper && !mLastConfigReportedToClient) || hasWallpaper())) { 4361 dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 4362 dc.setLayoutNeeded(); 4363 mWmService.mWindowPlacerLocked.requestTraversal(); 4364 } 4365 4366 for (int i = mChildren.size() - 1; i >= 0; i--) { 4367 final WindowState c = mChildren.get(i); 4368 c.requestUpdateWallpaperIfNeeded(); 4369 } 4370 } 4371 translateToWindowX(float x)4372 float translateToWindowX(float x) { 4373 float winX = x - mWindowFrames.mFrame.left; 4374 if (mGlobalScale != 1f) { 4375 winX *= mInvGlobalScale; 4376 } 4377 return winX; 4378 } 4379 translateToWindowY(float y)4380 float translateToWindowY(float y) { 4381 float winY = y - mWindowFrames.mFrame.top; 4382 if (mGlobalScale != 1f) { 4383 winY *= mInvGlobalScale; 4384 } 4385 return winY; 4386 } 4387 getRotationAnimationHint()4388 int getRotationAnimationHint() { 4389 if (mActivityRecord != null) { 4390 return mActivityRecord.mRotationAnimationHint; 4391 } else { 4392 return -1; 4393 } 4394 } 4395 4396 /** Makes the surface of drawn window (COMMIT_DRAW_PENDING) to be visible. */ commitFinishDrawing(SurfaceControl.Transaction t)4397 boolean commitFinishDrawing(SurfaceControl.Transaction t) { 4398 boolean committed = mWinAnimator.commitFinishDrawingLocked(); 4399 if (committed) { 4400 // Ensure that the visibility of buffer layer is set. 4401 mWinAnimator.prepareSurfaceLocked(t); 4402 } 4403 for (int i = mChildren.size() - 1; i >= 0; i--) { 4404 committed |= mChildren.get(i).commitFinishDrawing(t); 4405 } 4406 return committed; 4407 } 4408 4409 // This must be called while inside a transaction. performShowLocked()4410 boolean performShowLocked() { 4411 if (!showToCurrentUser()) { 4412 if (DEBUG_VISIBILITY) Slog.w(TAG, "hiding " + this + ", belonging to " + mOwnerUid); 4413 clearPolicyVisibilityFlag(VISIBLE_FOR_USER); 4414 return false; 4415 } 4416 4417 logPerformShow("performShow on "); 4418 4419 final int drawState = mWinAnimator.mDrawState; 4420 if ((drawState == HAS_DRAWN || drawState == READY_TO_SHOW) && mActivityRecord != null) { 4421 if (mAttrs.type != TYPE_APPLICATION_STARTING) { 4422 mActivityRecord.onFirstWindowDrawn(this); 4423 } else { 4424 mActivityRecord.onStartingWindowDrawn(); 4425 } 4426 } 4427 4428 if (mWinAnimator.mDrawState != READY_TO_SHOW || !isReadyForDisplay()) { 4429 return false; 4430 } 4431 4432 logPerformShow("Showing "); 4433 4434 mWmService.enableScreenIfNeededLocked(); 4435 mWinAnimator.applyEnterAnimationLocked(); 4436 4437 // Force the show in the next prepareSurfaceLocked() call. 4438 mWinAnimator.mLastAlpha = -1; 4439 ProtoLog.v(WM_DEBUG_ANIM, "performShowLocked: mDrawState=HAS_DRAWN in %s", this); 4440 mWinAnimator.mDrawState = HAS_DRAWN; 4441 mWmService.scheduleAnimationLocked(); 4442 4443 if (mHidden) { 4444 mHidden = false; 4445 final DisplayContent displayContent = getDisplayContent(); 4446 4447 for (int i = mChildren.size() - 1; i >= 0; --i) { 4448 final WindowState c = mChildren.get(i); 4449 if (c.mWinAnimator.mSurfaceController != null) { 4450 c.performShowLocked(); 4451 // It hadn't been shown, which means layout not performed on it, so now we 4452 // want to make sure to do a layout. If called from within the transaction 4453 // loop, this will cause it to restart with a new layout. 4454 if (displayContent != null) { 4455 displayContent.setLayoutNeeded(); 4456 } 4457 } 4458 } 4459 } 4460 4461 return true; 4462 } 4463 logPerformShow(String prefix)4464 private void logPerformShow(String prefix) { 4465 if (DEBUG_VISIBILITY 4466 || (DEBUG_STARTING_WINDOW_VERBOSE && mAttrs.type == TYPE_APPLICATION_STARTING)) { 4467 Slog.v(TAG, prefix + this 4468 + ": mDrawState=" + mWinAnimator.drawStateToString() 4469 + " readyForDisplay=" + isReadyForDisplay() 4470 + " starting=" + (mAttrs.type == TYPE_APPLICATION_STARTING) 4471 + " during animation: policyVis=" + isVisibleByPolicy() 4472 + " parentHidden=" + isParentWindowHidden() 4473 + " tok.visibleRequested=" 4474 + (mActivityRecord != null && mActivityRecord.isVisibleRequested()) 4475 + " tok.visible=" + (mActivityRecord != null && mActivityRecord.isVisible()) 4476 + " animating=" + isAnimating(TRANSITION | PARENTS) 4477 + " tok animating=" 4478 + (mActivityRecord != null && mActivityRecord.isAnimating(TRANSITION | PARENTS)) 4479 + " Callers=" + Debug.getCallers(4)); 4480 } 4481 } 4482 getWindowInfo()4483 WindowInfo getWindowInfo() { 4484 WindowInfo windowInfo = WindowInfo.obtain(); 4485 windowInfo.displayId = getDisplayId(); 4486 windowInfo.type = mAttrs.type; 4487 windowInfo.layer = mLayer; 4488 windowInfo.token = mClient.asBinder(); 4489 if (mActivityRecord != null) { 4490 windowInfo.activityToken = mActivityRecord.token; 4491 } 4492 windowInfo.accessibilityIdOfAnchor = mAttrs.accessibilityIdOfAnchor; 4493 windowInfo.focused = isFocused(); 4494 Task task = getTask(); 4495 windowInfo.inPictureInPicture = (task != null) && task.inPinnedWindowingMode(); 4496 windowInfo.taskId = task == null ? ActivityTaskManager.INVALID_TASK_ID : task.mTaskId; 4497 windowInfo.hasFlagWatchOutsideTouch = 4498 (mAttrs.flags & WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH) != 0; 4499 4500 if (mIsChildWindow) { 4501 windowInfo.parentToken = getParentWindow().mClient.asBinder(); 4502 } 4503 4504 final int childCount = mChildren.size(); 4505 if (childCount > 0) { 4506 if (windowInfo.childTokens == null) { 4507 windowInfo.childTokens = new ArrayList(childCount); 4508 } 4509 for (int j = 0; j < childCount; j++) { 4510 final WindowState child = mChildren.get(j); 4511 windowInfo.childTokens.add(child.mClient.asBinder()); 4512 } 4513 } 4514 return windowInfo; 4515 } 4516 4517 @Override forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)4518 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) { 4519 if (mChildren.isEmpty()) { 4520 // The window has no children so we just return it. 4521 return applyInOrderWithImeWindows(callback, traverseTopToBottom); 4522 } 4523 4524 if (traverseTopToBottom) { 4525 return forAllWindowTopToBottom(callback); 4526 } else { 4527 return forAllWindowBottomToTop(callback); 4528 } 4529 } 4530 forAllWindowBottomToTop(ToBooleanFunction<WindowState> callback)4531 private boolean forAllWindowBottomToTop(ToBooleanFunction<WindowState> callback) { 4532 // We want to consume the negative sublayer children first because they need to appear 4533 // below the parent, then this window (the parent), and then the positive sublayer children 4534 // because they need to appear above the parent. 4535 int i = 0; 4536 final int count = mChildren.size(); 4537 WindowState child = mChildren.get(i); 4538 4539 while (i < count && child.mSubLayer < 0) { 4540 if (child.applyInOrderWithImeWindows(callback, false /* traverseTopToBottom */)) { 4541 return true; 4542 } 4543 i++; 4544 if (i >= count) { 4545 break; 4546 } 4547 child = mChildren.get(i); 4548 } 4549 4550 if (applyInOrderWithImeWindows(callback, false /* traverseTopToBottom */)) { 4551 return true; 4552 } 4553 4554 while (i < count) { 4555 if (child.applyInOrderWithImeWindows(callback, false /* traverseTopToBottom */)) { 4556 return true; 4557 } 4558 i++; 4559 if (i >= count) { 4560 break; 4561 } 4562 child = mChildren.get(i); 4563 } 4564 4565 return false; 4566 } 4567 4568 @Override updateAboveInsetsState(InsetsState aboveInsetsState, SparseArray<InsetsSource> localInsetsSourcesFromParent, ArraySet<WindowState> insetsChangedWindows)4569 void updateAboveInsetsState(InsetsState aboveInsetsState, 4570 SparseArray<InsetsSource> localInsetsSourcesFromParent, 4571 ArraySet<WindowState> insetsChangedWindows) { 4572 final SparseArray<InsetsSource> mergedLocalInsetsSources = 4573 createMergedSparseArray(localInsetsSourcesFromParent, mLocalInsetsSources); 4574 4575 // Insets provided by the IME window can effect all the windows below it and hence it needs 4576 // to be visited in the correct order. Because of which updateAboveInsetsState() can't be 4577 // used here and instead forAllWindows() is used. 4578 forAllWindows(w -> { 4579 if (!w.mAboveInsetsState.equals(aboveInsetsState)) { 4580 w.mAboveInsetsState.set(aboveInsetsState); 4581 insetsChangedWindows.add(w); 4582 } 4583 4584 if (!mergedLocalInsetsSources.contentEquals(w.mMergedLocalInsetsSources)) { 4585 w.mMergedLocalInsetsSources = mergedLocalInsetsSources; 4586 insetsChangedWindows.add(w); 4587 } 4588 4589 final SparseArray<InsetsSourceProvider> providers = w.mInsetsSourceProviders; 4590 if (providers != null) { 4591 for (int i = providers.size() - 1; i >= 0; i--) { 4592 aboveInsetsState.addSource(providers.valueAt(i).getSource()); 4593 } 4594 } 4595 }, true /* traverseTopToBottom */); 4596 } 4597 forAllWindowTopToBottom(ToBooleanFunction<WindowState> callback)4598 private boolean forAllWindowTopToBottom(ToBooleanFunction<WindowState> callback) { 4599 // We want to consume the positive sublayer children first because they need to appear 4600 // above the parent, then this window (the parent), and then the negative sublayer children 4601 // because they need to appear above the parent. 4602 int i = mChildren.size() - 1; 4603 WindowState child = mChildren.get(i); 4604 4605 while (i >= 0 && child.mSubLayer >= 0) { 4606 if (child.applyInOrderWithImeWindows(callback, true /* traverseTopToBottom */)) { 4607 return true; 4608 } 4609 --i; 4610 if (i < 0) { 4611 break; 4612 } 4613 child = mChildren.get(i); 4614 } 4615 4616 if (applyInOrderWithImeWindows(callback, true /* traverseTopToBottom */)) { 4617 return true; 4618 } 4619 4620 while (i >= 0) { 4621 if (child.applyInOrderWithImeWindows(callback, true /* traverseTopToBottom */)) { 4622 return true; 4623 } 4624 --i; 4625 if (i < 0) { 4626 break; 4627 } 4628 child = mChildren.get(i); 4629 } 4630 4631 return false; 4632 } 4633 applyImeWindowsIfNeeded(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)4634 private boolean applyImeWindowsIfNeeded(ToBooleanFunction<WindowState> callback, 4635 boolean traverseTopToBottom) { 4636 // No need to apply to IME window if the window is not the current IME layering target. 4637 if (!isImeLayeringTarget()) { 4638 return false; 4639 } 4640 // Note that we don't process IME window if the IME input target is not on the screen. 4641 // In case some unexpected IME visibility cases happen like starting the remote 4642 // animation on the keyguard but seeing the IME window that originally on the app 4643 // which behinds the keyguard. 4644 final WindowState imeInputTarget = getImeInputTarget(); 4645 if (imeInputTarget != null 4646 && !(imeInputTarget.isDrawn() || imeInputTarget.isVisibleRequested())) { 4647 return false; 4648 } 4649 return mDisplayContent.forAllImeWindows(callback, traverseTopToBottom); 4650 } 4651 applyInOrderWithImeWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)4652 private boolean applyInOrderWithImeWindows(ToBooleanFunction<WindowState> callback, 4653 boolean traverseTopToBottom) { 4654 if (traverseTopToBottom) { 4655 if (applyImeWindowsIfNeeded(callback, traverseTopToBottom) 4656 || callback.apply(this)) { 4657 return true; 4658 } 4659 } else { 4660 if (callback.apply(this) 4661 || applyImeWindowsIfNeeded(callback, traverseTopToBottom)) { 4662 return true; 4663 } 4664 } 4665 return false; 4666 } 4667 getWindow(Predicate<WindowState> callback)4668 WindowState getWindow(Predicate<WindowState> callback) { 4669 if (mChildren.isEmpty()) { 4670 return callback.test(this) ? this : null; 4671 } 4672 4673 // We want to consume the positive sublayer children first because they need to appear 4674 // above the parent, then this window (the parent), and then the negative sublayer children 4675 // because they need to appear above the parent. 4676 int i = mChildren.size() - 1; 4677 WindowState child = mChildren.get(i); 4678 4679 while (i >= 0 && child.mSubLayer >= 0) { 4680 if (callback.test(child)) { 4681 return child; 4682 } 4683 --i; 4684 if (i < 0) { 4685 break; 4686 } 4687 child = mChildren.get(i); 4688 } 4689 4690 if (callback.test(this)) { 4691 return this; 4692 } 4693 4694 while (i >= 0) { 4695 if (callback.test(child)) { 4696 return child; 4697 } 4698 --i; 4699 if (i < 0) { 4700 break; 4701 } 4702 child = mChildren.get(i); 4703 } 4704 4705 return null; 4706 } 4707 4708 /** 4709 * @return True if we our one of our ancestors has {@link #mAnimatingExit} set to true, false 4710 * otherwise. 4711 */ 4712 @VisibleForTesting isSelfOrAncestorWindowAnimatingExit()4713 boolean isSelfOrAncestorWindowAnimatingExit() { 4714 WindowState window = this; 4715 do { 4716 if (window.mAnimatingExit) { 4717 return true; 4718 } 4719 window = window.getParentWindow(); 4720 } while (window != null); 4721 return false; 4722 } 4723 isAnimationRunningSelfOrParent()4724 boolean isAnimationRunningSelfOrParent() { 4725 return inTransitionSelfOrParent() 4726 || isAnimating(0 /* flags */, ANIMATION_TYPE_WINDOW_ANIMATION); 4727 } 4728 shouldFinishAnimatingExit()4729 private boolean shouldFinishAnimatingExit() { 4730 // Exit animation might be applied soon. 4731 if (inTransition()) { 4732 ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, "shouldWaitAnimatingExit: isTransition: %s", 4733 this); 4734 return false; 4735 } 4736 if (!mDisplayContent.okToAnimate()) { 4737 return true; 4738 } 4739 // Exit animation is running. 4740 if (isAnimationRunningSelfOrParent()) { 4741 ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, "shouldWaitAnimatingExit: isAnimating: %s", 4742 this); 4743 return false; 4744 } 4745 // If the wallpaper is currently behind this app window, we need to change both of 4746 // them inside of a transaction to avoid artifacts. 4747 if (mDisplayContent.mWallpaperController.isWallpaperTarget(this)) { 4748 ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, 4749 "shouldWaitAnimatingExit: isWallpaperTarget: %s", this); 4750 return false; 4751 } 4752 return true; 4753 } 4754 4755 /** 4756 * If this is window is stuck in the animatingExit status, resume clean up procedure blocked 4757 * by the exit animation. 4758 */ cleanupAnimatingExitWindow()4759 void cleanupAnimatingExitWindow() { 4760 // TODO(b/205335975): WindowManagerService#tryStartExitingAnimation starts an exit animation 4761 // and set #mAnimationExit. After the exit animation finishes, #onExitAnimationDone shall 4762 // be called, but there seems to be a case that #onExitAnimationDone is not triggered, so 4763 // a windows stuck in the animatingExit status. 4764 if (mAnimatingExit && shouldFinishAnimatingExit()) { 4765 ProtoLog.w(WM_DEBUG_APP_TRANSITIONS, "Clear window stuck on animatingExit status: %s", 4766 this); 4767 onExitAnimationDone(); 4768 } 4769 } 4770 onExitAnimationDone()4771 void onExitAnimationDone() { 4772 if (ProtoLog.isEnabled(WM_DEBUG_ANIM, LogLevel.VERBOSE)) { 4773 final AnimationAdapter animationAdapter = mSurfaceAnimator.getAnimation(); 4774 StringWriter sw = new StringWriter(); 4775 if (animationAdapter != null) { 4776 PrintWriter pw = new PrintWriter(sw); 4777 animationAdapter.dump(pw, ""); 4778 } 4779 ProtoLog.v(WM_DEBUG_ANIM, "onExitAnimationDone in %s" 4780 + ": exiting=%b remove=%b selfAnimating=%b anim=%s", 4781 this, mAnimatingExit, mRemoveOnExit, isAnimating(), sw); 4782 } 4783 4784 if (!mChildren.isEmpty()) { 4785 // Copying to a different list as multiple children can be removed. 4786 final ArrayList<WindowState> childWindows = new ArrayList<>(mChildren); 4787 for (int i = childWindows.size() - 1; i >= 0; i--) { 4788 childWindows.get(i).onExitAnimationDone(); 4789 } 4790 } 4791 4792 if (mWinAnimator.mEnteringAnimation) { 4793 mWinAnimator.mEnteringAnimation = false; 4794 mWmService.requestTraversal(); 4795 // System windows don't have an activity and an app token as a result, but need a way 4796 // to be informed about their entrance animation end. 4797 if (mActivityRecord == null) { 4798 try { 4799 mClient.dispatchWindowShown(); 4800 } catch (RemoteException e) { 4801 } 4802 } 4803 } 4804 4805 if (isAnimating()) { 4806 return; 4807 } 4808 4809 if (!isSelfOrAncestorWindowAnimatingExit()) { 4810 return; 4811 } 4812 4813 ProtoLog.v(WM_DEBUG_ADD_REMOVE, "Exit animation finished in %s: remove=%b", 4814 this, mRemoveOnExit); 4815 4816 mDestroying = true; 4817 4818 final boolean hasSurface = mWinAnimator.hasSurface(); 4819 4820 // Use pendingTransaction here so hide is done the same transaction as the other 4821 // animations when exiting 4822 mWinAnimator.hide(getPendingTransaction(), "onExitAnimationDone"); 4823 4824 // If we have an app token, we ask it to destroy the surface for us, so that it can take 4825 // care to ensure the activity has actually stopped and the surface is not still in use. 4826 // Otherwise we add the service to mDestroySurface and allow it to be processed in our next 4827 // transaction. 4828 if (mActivityRecord != null) { 4829 if (mAttrs.type == TYPE_BASE_APPLICATION) { 4830 mActivityRecord.destroySurfaces(); 4831 } else { 4832 destroySurface(false /* cleanupOnResume */, mActivityRecord.mAppStopped); 4833 } 4834 } else { 4835 if (hasSurface) { 4836 mWmService.mDestroySurface.add(this); 4837 } 4838 } 4839 mAnimatingExit = false; 4840 ProtoLog.d(WM_DEBUG_ANIM, "Clear animatingExit: reason=exitAnimationDone win=%s", this); 4841 getDisplayContent().mWallpaperController.hideWallpapers(this); 4842 } 4843 4844 @Override handleCompleteDeferredRemoval()4845 boolean handleCompleteDeferredRemoval() { 4846 if (mRemoveOnExit && !isSelfAnimating(0 /* flags */, ANIMATION_TYPE_WINDOW_ANIMATION)) { 4847 mRemoveOnExit = false; 4848 removeImmediately(); 4849 } 4850 return super.handleCompleteDeferredRemoval(); 4851 } 4852 clearAnimatingFlags()4853 boolean clearAnimatingFlags() { 4854 boolean didSomething = false; 4855 // We also don't clear the mAnimatingExit flag for windows which have the 4856 // mRemoveOnExit flag. This indicates an explicit remove request has been issued 4857 // by the client. We should let animation proceed and not clear this flag or 4858 // they won't eventually be removed by WindowStateAnimator#finishExit. 4859 if (!mRemoveOnExit) { 4860 // Clear mAnimating flag together with mAnimatingExit. When animation 4861 // changes from exiting to entering, we need to clear this flag until the 4862 // new animation gets applied, so that isAnimationStarting() becomes true 4863 // until then. 4864 // Otherwise applySurfaceChangesTransaction will fail to skip surface 4865 // placement for this window during this period, one or more frame will 4866 // show up with wrong position or scale. 4867 if (mAnimatingExit) { 4868 mAnimatingExit = false; 4869 ProtoLog.d(WM_DEBUG_ANIM, "Clear animatingExit: reason=clearAnimatingFlags win=%s", 4870 this); 4871 didSomething = true; 4872 } 4873 if (mDestroying) { 4874 mDestroying = false; 4875 mWmService.mDestroySurface.remove(this); 4876 didSomething = true; 4877 } 4878 } 4879 4880 for (int i = mChildren.size() - 1; i >= 0; --i) { 4881 didSomething |= (mChildren.get(i)).clearAnimatingFlags(); 4882 } 4883 4884 return didSomething; 4885 } 4886 isRtl()4887 public boolean isRtl() { 4888 return getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL; 4889 } 4890 updateReportedVisibility(UpdateReportedVisibilityResults results)4891 void updateReportedVisibility(UpdateReportedVisibilityResults results) { 4892 for (int i = mChildren.size() - 1; i >= 0; --i) { 4893 final WindowState c = mChildren.get(i); 4894 c.updateReportedVisibility(results); 4895 } 4896 4897 if (mAppFreezing || mViewVisibility != View.VISIBLE 4898 || mAttrs.type == TYPE_APPLICATION_STARTING 4899 || mDestroying) { 4900 return; 4901 } 4902 if (DEBUG_VISIBILITY) { 4903 Slog.v(TAG, "Win " + this + ": isDrawn=" + isDrawn() 4904 + ", animating=" + isAnimating(TRANSITION | PARENTS)); 4905 if (!isDrawn()) { 4906 Slog.v(TAG, "Not displayed: s=" + mWinAnimator.mSurfaceController 4907 + " pv=" + isVisibleByPolicy() 4908 + " mDrawState=" + mWinAnimator.mDrawState 4909 + " ph=" + isParentWindowHidden() 4910 + " th=" + (mActivityRecord != null && mActivityRecord.isVisibleRequested()) 4911 + " a=" + isAnimating(TRANSITION | PARENTS)); 4912 } 4913 } 4914 4915 results.numInteresting++; 4916 if (isDrawn()) { 4917 results.numDrawn++; 4918 if (!isAnimating(TRANSITION | PARENTS)) { 4919 results.numVisible++; 4920 } 4921 results.nowGone = false; 4922 } else if (isAnimating(TRANSITION | PARENTS)) { 4923 results.nowGone = false; 4924 } 4925 } 4926 surfaceInsetsChanging()4927 boolean surfaceInsetsChanging() { 4928 return !mLastSurfaceInsets.equals(mAttrs.surfaceInsets); 4929 } 4930 relayoutVisibleWindow(int result)4931 int relayoutVisibleWindow(int result) { 4932 final boolean wasVisible = isVisible(); 4933 4934 result |= (!wasVisible || !isDrawn()) ? RELAYOUT_RES_FIRST_TIME : 0; 4935 4936 if (mAnimatingExit) { 4937 Slog.d(TAG, "relayoutVisibleWindow: " + this + " mAnimatingExit=true, mRemoveOnExit=" 4938 + mRemoveOnExit + ", mDestroying=" + mDestroying); 4939 4940 mAnimatingExit = false; 4941 // Cancel the existing exit animation for the next enter animation. 4942 if (isAnimating()) { 4943 cancelAnimation(); 4944 } 4945 ProtoLog.d(WM_DEBUG_ANIM, "Clear animatingExit: reason=relayoutVisibleWindow win=%s", 4946 this); 4947 } 4948 if (mDestroying) { 4949 mDestroying = false; 4950 mWmService.mDestroySurface.remove(this); 4951 } 4952 if (!wasVisible) { 4953 mWinAnimator.mEnterAnimationPending = true; 4954 } 4955 4956 mLastVisibleLayoutRotation = getDisplayContent().getRotation(); 4957 4958 mWinAnimator.mEnteringAnimation = true; 4959 4960 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "prepareToDisplay"); 4961 try { 4962 prepareWindowToDisplayDuringRelayout(wasVisible); 4963 } finally { 4964 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 4965 } 4966 4967 return result; 4968 } 4969 4970 /** 4971 * @return True if this window has been laid out at least once; false otherwise. 4972 */ isLaidOut()4973 boolean isLaidOut() { 4974 return mLayoutSeq != -1; 4975 } 4976 4977 /** Updates the last frames and relative frames to the current ones. */ updateLastFrames()4978 void updateLastFrames() { 4979 mWindowFrames.mLastFrame.set(mWindowFrames.mFrame); 4980 mWindowFrames.mLastRelFrame.set(mWindowFrames.mRelFrame); 4981 } 4982 4983 /** 4984 * Clears factors that would cause report-resize. 4985 */ onResizeHandled()4986 void onResizeHandled() { 4987 mWindowFrames.onResizeHandled(); 4988 } 4989 4990 @Override isSelfAnimating(int flags, int typesToCheck)4991 protected boolean isSelfAnimating(int flags, int typesToCheck) { 4992 if (mControllableInsetProvider != null) { 4993 return false; 4994 } 4995 return super.isSelfAnimating(flags, typesToCheck); 4996 } 4997 startAnimation(Animation anim)4998 void startAnimation(Animation anim) { 4999 5000 // If we are an inset provider, all our animations are driven by the inset client. 5001 if (mControllableInsetProvider != null) { 5002 return; 5003 } 5004 5005 final DisplayInfo displayInfo = getDisplayInfo(); 5006 anim.initialize(mWindowFrames.mFrame.width(), mWindowFrames.mFrame.height(), 5007 displayInfo.appWidth, displayInfo.appHeight); 5008 anim.restrictDuration(MAX_ANIMATION_DURATION); 5009 anim.scaleCurrentDuration(mWmService.getWindowAnimationScaleLocked()); 5010 final Point position = new Point(); 5011 if (com.android.window.flags.Flags.removePrepareSurfaceInPlacement()) { 5012 transformFrameToSurfacePosition(mWindowFrames.mFrame.left, mWindowFrames.mFrame.top, 5013 position); 5014 } else { 5015 position.set(mSurfacePosition); 5016 } 5017 final AnimationAdapter adapter = new LocalAnimationAdapter( 5018 new WindowAnimationSpec(anim, position, false /* canSkipFirstFrame */, 5019 0 /* windowCornerRadius */), 5020 mWmService.mSurfaceAnimationRunner); 5021 startAnimation(getPendingTransaction(), adapter); 5022 commitPendingTransaction(); 5023 } 5024 startMoveAnimation(int left, int top)5025 private void startMoveAnimation(int left, int top) { 5026 5027 // If we are an inset provider, all our animations are driven by the inset client. 5028 if (mControllableInsetProvider != null) { 5029 return; 5030 } 5031 5032 ProtoLog.v(WM_DEBUG_ANIM, "Setting move animation on %s", this); 5033 final Point oldPosition = new Point(); 5034 final Point newPosition = new Point(); 5035 transformFrameToSurfacePosition(mWindowFrames.mLastFrame.left, mWindowFrames.mLastFrame.top, 5036 oldPosition); 5037 transformFrameToSurfacePosition(left, top, newPosition); 5038 final AnimationAdapter adapter = new LocalAnimationAdapter( 5039 new MoveAnimationSpec(oldPosition.x, oldPosition.y, newPosition.x, newPosition.y), 5040 mWmService.mSurfaceAnimationRunner); 5041 startAnimation(getPendingTransaction(), adapter); 5042 } 5043 startAnimation(Transaction t, AnimationAdapter adapter)5044 private void startAnimation(Transaction t, AnimationAdapter adapter) { 5045 startAnimation(t, adapter, mWinAnimator.mLastHidden, ANIMATION_TYPE_WINDOW_ANIMATION); 5046 } 5047 5048 @Override onAnimationFinished(@nimationType int type, AnimationAdapter anim)5049 protected void onAnimationFinished(@AnimationType int type, AnimationAdapter anim) { 5050 super.onAnimationFinished(type, anim); 5051 mWinAnimator.onAnimationFinished(); 5052 } 5053 5054 /** 5055 * Retrieves the current transformation matrix of the window, relative to the display. 5056 * 5057 * @param float9 A temporary array of 9 floats. 5058 * @param outMatrix Matrix to fill in the transformation. 5059 */ getTransformationMatrix(float[] float9, Matrix outMatrix)5060 void getTransformationMatrix(float[] float9, Matrix outMatrix) { 5061 float9[Matrix.MSCALE_X] = mGlobalScale; 5062 float9[Matrix.MSKEW_Y] = 0; 5063 float9[Matrix.MSKEW_X] = 0; 5064 float9[Matrix.MSCALE_Y] = mGlobalScale; 5065 transformSurfaceInsetsPosition(mTmpPoint, mAttrs.surfaceInsets); 5066 int x = mSurfacePosition.x + mTmpPoint.x; 5067 int y = mSurfacePosition.y + mTmpPoint.y; 5068 5069 // If changed, also adjust transformFrameToSurfacePosition 5070 final WindowContainer parent = getParent(); 5071 if (isChildWindow()) { 5072 final WindowState parentWindow = getParentWindow(); 5073 x += parentWindow.mWindowFrames.mFrame.left - parentWindow.mAttrs.surfaceInsets.left; 5074 y += parentWindow.mWindowFrames.mFrame.top - parentWindow.mAttrs.surfaceInsets.top; 5075 } else if (parent != null) { 5076 final Rect parentBounds = parent.getBounds(); 5077 x += parentBounds.left; 5078 y += parentBounds.top; 5079 } 5080 float9[Matrix.MTRANS_X] = x; 5081 float9[Matrix.MTRANS_Y] = y; 5082 float9[Matrix.MPERSP_0] = 0; 5083 float9[Matrix.MPERSP_1] = 0; 5084 float9[Matrix.MPERSP_2] = 1; 5085 outMatrix.setValues(float9); 5086 } 5087 5088 // TODO: Hack to work around the number of states ActivityRecord needs to access without having 5089 // access to its windows children. Need to investigate re-writing 5090 // {@link ActivityRecord#updateReportedVisibilityLocked} so this can be removed. 5091 static final class UpdateReportedVisibilityResults { 5092 int numInteresting; 5093 int numVisible; 5094 int numDrawn; 5095 boolean nowGone = true; 5096 reset()5097 void reset() { 5098 numInteresting = 0; 5099 numVisible = 0; 5100 numDrawn = 0; 5101 nowGone = true; 5102 } 5103 } 5104 5105 private static final class WindowId extends IWindowId.Stub { 5106 private final WeakReference<WindowState> mOuter; 5107 WindowId(WindowState outer)5108 private WindowId(WindowState outer) { 5109 5110 // Use a weak reference for the outer class. This is important to prevent the following 5111 // leak: Since we send this class to the client process, binder will keep it alive as 5112 // long as the client keeps it alive. Now, if the window is removed, we need to clear 5113 // out our reference so even though this class is kept alive we don't leak WindowState, 5114 // which can keep a whole lot of classes alive. 5115 mOuter = new WeakReference<>(outer); 5116 } 5117 5118 @Override registerFocusObserver(IWindowFocusObserver observer)5119 public void registerFocusObserver(IWindowFocusObserver observer) { 5120 final WindowState outer = mOuter.get(); 5121 if (outer != null) { 5122 outer.registerFocusObserver(observer); 5123 } 5124 } 5125 @Override unregisterFocusObserver(IWindowFocusObserver observer)5126 public void unregisterFocusObserver(IWindowFocusObserver observer) { 5127 final WindowState outer = mOuter.get(); 5128 if (outer != null) { 5129 outer.unregisterFocusObserver(observer); 5130 } 5131 } 5132 @Override isFocused()5133 public boolean isFocused() { 5134 final WindowState outer = mOuter.get(); 5135 if (outer != null) { 5136 synchronized (outer.mWmService.mGlobalLock) { 5137 return outer.isFocused(); 5138 } 5139 } 5140 return false; 5141 } 5142 } 5143 5144 5145 @Override shouldMagnify()5146 boolean shouldMagnify() { 5147 if (mAttrs.type == TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY 5148 || mAttrs.type == TYPE_INPUT_METHOD 5149 || mAttrs.type == TYPE_INPUT_METHOD_DIALOG 5150 || mAttrs.type == TYPE_MAGNIFICATION_OVERLAY 5151 || mAttrs.type == TYPE_NAVIGATION_BAR 5152 // It's tempting to wonder: Have we forgotten the rounded corners overlay? 5153 // worry not: it's a fake TYPE_NAVIGATION_BAR_PANEL 5154 || mAttrs.type == TYPE_NAVIGATION_BAR_PANEL) { 5155 return false; 5156 } 5157 if ((mAttrs.privateFlags & PRIVATE_FLAG_NOT_MAGNIFIABLE) != 0) { 5158 return false; 5159 } 5160 return true; 5161 } 5162 5163 @Override getSession()5164 SurfaceSession getSession() { 5165 if (mSession.mSurfaceSession != null) { 5166 return mSession.mSurfaceSession; 5167 } else { 5168 return getParent().getSession(); 5169 } 5170 } 5171 5172 @Override needsZBoost()5173 boolean needsZBoost() { 5174 final InsetsControlTarget target = getDisplayContent().getImeTarget(IME_TARGET_LAYERING); 5175 if (mIsImWindow && target != null) { 5176 final ActivityRecord activity = target.getWindow().mActivityRecord; 5177 if (activity != null) { 5178 return activity.needsZBoost(); 5179 } 5180 } 5181 return false; 5182 } 5183 isStartingWindowAssociatedToTask()5184 private boolean isStartingWindowAssociatedToTask() { 5185 return mStartingData != null && mStartingData.mAssociatedTask != null; 5186 } 5187 applyDims()5188 private void applyDims() { 5189 if (((mAttrs.flags & FLAG_DIM_BEHIND) != 0 || shouldDrawBlurBehind()) 5190 && (Dimmer.DIMMER_REFACTOR ? mWinAnimator.getShown() : isVisibleNow()) 5191 && !mHidden && mTransitionController.canApplyDim(getTask())) { 5192 // Only show the Dimmer when the following is satisfied: 5193 // 1. The window has the flag FLAG_DIM_BEHIND or blur behind is requested 5194 // 2. The WindowToken is not hidden so dims aren't shown when the window is exiting. 5195 // 3. The WS is considered visible according to the isVisible() method 5196 // 4. The WS is not hidden. 5197 // 5. The window is not in a transition or is in a transition that allows to dim. 5198 mIsDimming = true; 5199 final float dimAmount = (mAttrs.flags & FLAG_DIM_BEHIND) != 0 ? mAttrs.dimAmount : 0; 5200 final int blurRadius = shouldDrawBlurBehind() ? mAttrs.getBlurBehindRadius() : 0; 5201 // If the window is visible from surface flinger perspective (mWinAnimator.getShown()) 5202 // but not window manager visible (!isVisibleNow()), it can still be the parent of the 5203 // dim, but can not create a new surface or continue a dim alone. 5204 if (isVisibleNow()) { 5205 getDimmer().adjustAppearance(this, dimAmount, blurRadius); 5206 } 5207 getDimmer().adjustRelativeLayer(this, -1 /* relativeLayer */); 5208 } 5209 } 5210 shouldDrawBlurBehind()5211 private boolean shouldDrawBlurBehind() { 5212 return (mAttrs.flags & FLAG_BLUR_BEHIND) != 0 5213 && mWmService.mBlurController.getBlurEnabled(); 5214 } 5215 5216 /** 5217 * Notifies SF about the priority of the window, if it changed. SF then uses this information 5218 * to decide which window's desired rendering rate should have a priority when deciding about 5219 * the refresh rate of the screen. Priority 5220 * {@link RefreshRatePolicy#LAYER_PRIORITY_FOCUSED_WITH_MODE} is considered the highest. 5221 */ 5222 @VisibleForTesting updateFrameRateSelectionPriorityIfNeeded()5223 void updateFrameRateSelectionPriorityIfNeeded() { 5224 RefreshRatePolicy refreshRatePolicy = 5225 getDisplayContent().getDisplayPolicy().getRefreshRatePolicy(); 5226 final int priority = refreshRatePolicy.calculatePriority(this); 5227 if (mFrameRateSelectionPriority != priority) { 5228 mFrameRateSelectionPriority = priority; 5229 getPendingTransaction().setFrameRateSelectionPriority(mSurfaceControl, 5230 mFrameRateSelectionPriority); 5231 } 5232 5233 boolean voteChanged = refreshRatePolicy.updateFrameRateVote(this); 5234 if (voteChanged) { 5235 getPendingTransaction() 5236 .setFrameRate(mSurfaceControl, mFrameRateVote.mRefreshRate, 5237 mFrameRateVote.mCompatibility, Surface.CHANGE_FRAME_RATE_ALWAYS); 5238 if (explicitRefreshRateHints()) { 5239 getPendingTransaction().setFrameRateSelectionStrategy(mSurfaceControl, 5240 mFrameRateVote.mSelectionStrategy); 5241 } 5242 5243 } 5244 } 5245 updateScaleIfNeeded()5246 private void updateScaleIfNeeded() { 5247 if (!isVisibleRequested() && !(mIsWallpaper && mToken.isVisible())) { 5248 // Skip if it is requested to be invisible, but if it is wallpaper, it may be in 5249 // transition that still needs to update the scale for zoom effect. 5250 return; 5251 } 5252 float globalScale = mGlobalScale; 5253 final WindowState parent = getParentWindow(); 5254 if (parent != null) { 5255 // Undo parent's scale because the child surface has inherited scale from parent. 5256 globalScale *= parent.mInvGlobalScale; 5257 } 5258 final float newHScale = mHScale * globalScale * mWallpaperScale; 5259 final float newVScale = mVScale * globalScale * mWallpaperScale; 5260 if (mLastHScale != newHScale || mLastVScale != newVScale) { 5261 getSyncTransaction().setMatrix(mSurfaceControl, newHScale, 0, 0, newVScale); 5262 mLastHScale = newHScale; 5263 mLastVScale = newVScale; 5264 } 5265 } 5266 5267 @Override prepareSurfaces()5268 void prepareSurfaces() { 5269 mIsDimming = false; 5270 if (mHasSurface) { 5271 if (!Dimmer.DIMMER_REFACTOR) { 5272 applyDims(); 5273 } 5274 updateSurfacePositionNonOrganized(); 5275 // Send information to SurfaceFlinger about the priority of the current window. 5276 updateFrameRateSelectionPriorityIfNeeded(); 5277 updateScaleIfNeeded(); 5278 mWinAnimator.prepareSurfaceLocked(getSyncTransaction()); 5279 if (Dimmer.DIMMER_REFACTOR) { 5280 applyDims(); 5281 } 5282 } 5283 super.prepareSurfaces(); 5284 } 5285 5286 @Override 5287 @VisibleForTesting updateSurfacePosition(Transaction t)5288 void updateSurfacePosition(Transaction t) { 5289 if (mSurfaceControl == null || mIsSurfacePositionPaused) { 5290 return; 5291 } 5292 if (mActivityRecord != null && mActivityRecord.isConfigurationDispatchPaused()) { 5293 // Don't update surface-position while dispatch paused. This is calculated from 5294 // the server-side activity configuration so return early. 5295 return; 5296 } 5297 5298 if ((mWmService.mWindowPlacerLocked.isLayoutDeferred() || isGoneForLayout()) 5299 && !mSurfacePlacementNeeded) { 5300 // Since this relies on mWindowFrames, changes made while layout is deferred are 5301 // likely to be invalid. Similarly, if it's goneForLayout, mWindowFrames may not be 5302 // up-to-date and thus can't be relied on. 5303 return; 5304 } 5305 5306 mSurfacePlacementNeeded = false; 5307 transformFrameToSurfacePosition(mWindowFrames.mFrame.left, mWindowFrames.mFrame.top, 5308 mSurfacePosition); 5309 5310 if (mWallpaperScale != 1f) { 5311 final Rect bounds = getParentFrame(); 5312 Matrix matrix = mTmpMatrix; 5313 matrix.setTranslate(mXOffset, mYOffset); 5314 matrix.postScale(mWallpaperScale, mWallpaperScale, bounds.exactCenterX(), 5315 bounds.exactCenterY()); 5316 matrix.getValues(mTmpMatrixArray); 5317 mSurfacePosition.offset(Math.round(mTmpMatrixArray[Matrix.MTRANS_X]), 5318 Math.round(mTmpMatrixArray[Matrix.MTRANS_Y])); 5319 } else { 5320 mSurfacePosition.offset(mXOffset, mYOffset); 5321 } 5322 5323 final AsyncRotationController asyncRotationController = 5324 mDisplayContent.getAsyncRotationController(); 5325 if ((asyncRotationController != null 5326 && asyncRotationController.hasSeamlessOperation(mToken)) 5327 || mPendingSeamlessRotate != null) { 5328 // Freeze position while un-rotating the window, so its surface remains at the position 5329 // corresponding to the original rotation. 5330 return; 5331 } 5332 5333 if (!mSurfaceAnimator.hasLeash() && !mLastSurfacePosition.equals(mSurfacePosition)) { 5334 final boolean frameSizeChanged = mWindowFrames.isFrameSizeChangeReported(); 5335 final boolean surfaceInsetsChanged = surfaceInsetsChanging(); 5336 final boolean surfaceSizeChanged = frameSizeChanged || surfaceInsetsChanged; 5337 mLastSurfacePosition.set(mSurfacePosition.x, mSurfacePosition.y); 5338 if (surfaceInsetsChanged) { 5339 mLastSurfaceInsets.set(mAttrs.surfaceInsets); 5340 } 5341 final boolean surfaceResizedWithoutMoveAnimation = surfaceSizeChanged 5342 && mWinAnimator.getShown() && !canPlayMoveAnimation() && okToDisplay() 5343 && mSyncState == SYNC_STATE_NONE; 5344 final ActivityRecord activityRecord = getActivityRecord(); 5345 // If this window belongs to an activity that is relaunching due to an orientation 5346 // change then delay the position update until it has redrawn to avoid any flickers. 5347 final boolean isLetterboxedAndRelaunching = activityRecord != null 5348 && activityRecord.areBoundsLetterboxed() 5349 && activityRecord.mLetterboxUiController 5350 .getIsRelaunchingAfterRequestedOrientationChanged(); 5351 if (surfaceResizedWithoutMoveAnimation || isLetterboxedAndRelaunching) { 5352 applyWithNextDraw(mSetSurfacePositionConsumer); 5353 } else { 5354 mSetSurfacePositionConsumer.accept(t); 5355 } 5356 } 5357 } 5358 transformFrameToSurfacePosition(int left, int top, Point outPoint)5359 void transformFrameToSurfacePosition(int left, int top, Point outPoint) { 5360 outPoint.set(left, top); 5361 5362 // If changed, also adjust getTransformationMatrix 5363 final WindowContainer parentWindowContainer = getParent(); 5364 if (isChildWindow()) { 5365 final WindowState parent = getParentWindow(); 5366 outPoint.offset(-parent.mWindowFrames.mFrame.left, -parent.mWindowFrames.mFrame.top); 5367 // Undo the scale of window position because the relative coordinates for child are 5368 // based on the scaled parent. 5369 if (mInvGlobalScale != 1f) { 5370 outPoint.x = (int) (outPoint.x * mInvGlobalScale + 0.5f); 5371 outPoint.y = (int) (outPoint.y * mInvGlobalScale + 0.5f); 5372 } 5373 // Since the parent was outset by its surface insets, we need to undo the outsetting 5374 // with insetting by the same amount. 5375 transformSurfaceInsetsPosition(mTmpPoint, parent.mAttrs.surfaceInsets); 5376 outPoint.offset(mTmpPoint.x, mTmpPoint.y); 5377 } else if (parentWindowContainer != null) { 5378 final Rect parentBounds = isStartingWindowAssociatedToTask() 5379 ? mStartingData.mAssociatedTask.getBounds() 5380 : parentWindowContainer.getBounds(); 5381 outPoint.offset(-parentBounds.left, -parentBounds.top); 5382 } 5383 5384 // The surface size is larger than the window if the window has positive surface insets. 5385 transformSurfaceInsetsPosition(mTmpPoint, mAttrs.surfaceInsets); 5386 outPoint.offset(-mTmpPoint.x, -mTmpPoint.y); 5387 5388 outPoint.y += mSurfaceTranslationY; 5389 } 5390 5391 /** 5392 * The surface insets from layout parameter are in application coordinate. If the window is 5393 * scaled, the insets also need to be scaled for surface position in global coordinate. 5394 */ transformSurfaceInsetsPosition(Point outPos, Rect surfaceInsets)5395 private void transformSurfaceInsetsPosition(Point outPos, Rect surfaceInsets) { 5396 // Ignore the scale for child window because its insets have been scaled with the 5397 // parent surface. 5398 if (mGlobalScale == 1f || mIsChildWindow) { 5399 outPos.x = surfaceInsets.left; 5400 outPos.y = surfaceInsets.top; 5401 return; 5402 } 5403 outPos.x = (int) (surfaceInsets.left * mGlobalScale + 0.5f); 5404 outPos.y = (int) (surfaceInsets.top * mGlobalScale + 0.5f); 5405 } 5406 needsRelativeLayeringToIme()5407 boolean needsRelativeLayeringToIme() { 5408 // We use the relative layering when IME isn't attached to the app. Such as part of 5409 // elevating the IME and windows above it's target above the docked divider in 5410 // split-screen, or make the popupMenu to be above the IME when the parent window is the 5411 // IME layering target in bubble/freeform mode. 5412 if (mDisplayContent.shouldImeAttachedToApp()) { 5413 return false; 5414 } 5415 5416 // We don't need to set the window to be relatively above IME if the IME is not visible. 5417 // In case seeing the window is animating above the app transition layer because its 5418 // relative layer is above the IME container on the display area but actually not necessary. 5419 if (!getDisplayContent().getImeContainer().isVisible()) { 5420 return false; 5421 } 5422 5423 if (isChildWindow()) { 5424 // If we are a child of the input method target we need this promotion. 5425 if (getParentWindow().isImeLayeringTarget()) { 5426 return true; 5427 } 5428 } else if (mActivityRecord != null) { 5429 // Likewise if we share a token with the Input method target and are ordered 5430 // above it but not necessarily a child (e.g. a Dialog) then we also need 5431 // this promotion. 5432 final WindowState imeTarget = getImeLayeringTarget(); 5433 boolean inTokenWithAndAboveImeTarget = imeTarget != null && imeTarget != this 5434 && imeTarget.mToken == mToken 5435 && mAttrs.type != TYPE_APPLICATION_STARTING 5436 && getParent() != null 5437 && imeTarget.compareTo(this) <= 0; 5438 return inTokenWithAndAboveImeTarget; 5439 } 5440 5441 // The condition is for the system dialog not belonging to any Activity. 5442 // (^FLAG_NOT_FOCUSABLE & FLAG_ALT_FOCUSABLE_IM) means the dialog is still focusable but 5443 // should be placed above the IME window. 5444 if ((mAttrs.flags & (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM)) 5445 == FLAG_ALT_FOCUSABLE_IM && isTrustedOverlay() && canAddInternalSystemWindow()) { 5446 // Check the current IME target so that it does not lift this window above the IME if 5447 // the Z-order of the current IME layering target is greater than it. 5448 final WindowState imeTarget = getImeLayeringTarget(); 5449 return imeTarget != null && imeTarget != this && imeTarget.compareTo(this) <= 0; 5450 } 5451 return false; 5452 } 5453 5454 /** 5455 * Get IME target that should host IME. 5456 * Note: IME is never hosted by a display that doesn't support IME/system decorations. 5457 * When window calling 5458 * {@link android.view.inputmethod.InputMethodManager#showSoftInput(View, int)} is unknown, 5459 * use {@link DisplayContent#getImeControlTarget()} instead. 5460 * 5461 * @return {@link InsetsControlTarget} of host that controls the IME. 5462 * When window is doesn't have a parent, it is returned as-is. 5463 */ 5464 @Override getImeControlTarget()5465 public InsetsControlTarget getImeControlTarget() { 5466 return getDisplayContent().getImeHostOrFallback(this); 5467 } 5468 5469 @Override assignLayer(Transaction t, int layer)5470 void assignLayer(Transaction t, int layer) { 5471 if (mStartingData != null) { 5472 // The starting window should cover the task. 5473 t.setLayer(mSurfaceControl, Integer.MAX_VALUE); 5474 return; 5475 } 5476 // See comment in assignRelativeLayerForImeTargetChild 5477 if (needsRelativeLayeringToIme()) { 5478 getDisplayContent().assignRelativeLayerForImeTargetChild(t, this); 5479 return; 5480 } 5481 super.assignLayer(t, layer); 5482 } 5483 isDimming()5484 boolean isDimming() { 5485 return mIsDimming; 5486 } 5487 5488 @Override reparentSurfaceControl(Transaction t, SurfaceControl newParent)5489 protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) { 5490 if (isStartingWindowAssociatedToTask()) { 5491 // Its surface is already put in task. Don't reparent when transferring starting window 5492 // across activities. 5493 return; 5494 } 5495 super.reparentSurfaceControl(t, newParent); 5496 } 5497 5498 @Override getAnimationLeashParent()5499 public SurfaceControl getAnimationLeashParent() { 5500 if (isStartingWindowAssociatedToTask()) { 5501 return mStartingData.mAssociatedTask.mSurfaceControl; 5502 } 5503 return super.getAnimationLeashParent(); 5504 } 5505 5506 @Override onAnimationLeashCreated(Transaction t, SurfaceControl leash)5507 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) { 5508 super.onAnimationLeashCreated(t, leash); 5509 if (isStartingWindowAssociatedToTask()) { 5510 // Make sure the animation leash is still on top of the task. 5511 t.setLayer(leash, Integer.MAX_VALUE); 5512 } 5513 } 5514 5515 // TODO(b/70040778): We should aim to eliminate the last user of TYPE_APPLICATION_MEDIA 5516 // then we can drop all negative layering on the windowing side and simply inherit 5517 // the default implementation here. assignChildLayers(Transaction t)5518 public void assignChildLayers(Transaction t) { 5519 // The surface of the main window might be preserved. So the child window on top of the main 5520 // window should be also on top of the preserved surface. 5521 int layer = PRESERVED_SURFACE_LAYER + 1; 5522 for (int i = 0; i < mChildren.size(); i++) { 5523 final WindowState w = mChildren.get(i); 5524 5525 // APPLICATION_MEDIA_OVERLAY needs to go above APPLICATION_MEDIA 5526 // while they both need to go below the main window. However the 5527 // relative layering of multiple APPLICATION_MEDIA/OVERLAY has never 5528 // been defined and so we can use static layers and leave it that way. 5529 if (w.mAttrs.type == TYPE_APPLICATION_MEDIA) { 5530 if (mWinAnimator.hasSurface()) { 5531 w.assignRelativeLayer(t, mWinAnimator.mSurfaceController.mSurfaceControl, -2); 5532 } else { 5533 w.assignLayer(t, -2); 5534 } 5535 } else if (w.mAttrs.type == TYPE_APPLICATION_MEDIA_OVERLAY) { 5536 if (mWinAnimator.hasSurface()) { 5537 w.assignRelativeLayer(t, mWinAnimator.mSurfaceController.mSurfaceControl, -1); 5538 } else { 5539 w.assignLayer(t, -1); 5540 } 5541 } else { 5542 w.assignLayer(t, layer); 5543 } 5544 w.assignChildLayers(t); 5545 layer++; 5546 } 5547 } 5548 5549 /** 5550 * Update a tap exclude region identified by provided id. The requested area will be clipped to 5551 * the window bounds. 5552 */ updateTapExcludeRegion(Region region)5553 void updateTapExcludeRegion(Region region) { 5554 final DisplayContent currentDisplay = getDisplayContent(); 5555 if (currentDisplay == null) { 5556 throw new IllegalStateException("Trying to update window not attached to any display."); 5557 } 5558 5559 // Clear the tap excluded region if the region passed in is null or empty. 5560 if (region == null || region.isEmpty()) { 5561 mTapExcludeRegion.setEmpty(); 5562 } else { 5563 mTapExcludeRegion.set(region); 5564 } 5565 5566 // Trigger touchable region update for this window. 5567 currentDisplay.getInputMonitor().updateInputWindowsLw(true /* force */); 5568 } 5569 5570 /** 5571 * Get the tap excluded region for this window in screen coordinates. 5572 * 5573 * @param outRegion The returned tap excluded region. It is on the screen coordinates. 5574 */ getTapExcludeRegion(Region outRegion)5575 void getTapExcludeRegion(Region outRegion) { 5576 mTmpRect.set(mWindowFrames.mFrame); 5577 mTmpRect.offsetTo(0, 0); 5578 5579 outRegion.set(mTapExcludeRegion); 5580 outRegion.op(mTmpRect, Region.Op.INTERSECT); 5581 5582 // The region is on the window coordinates, so it needs to be translated into screen 5583 // coordinates. There's no need to scale since that will be done by native code. 5584 outRegion.translate(mWindowFrames.mFrame.left, mWindowFrames.mFrame.top); 5585 } 5586 isImeLayeringTarget()5587 boolean isImeLayeringTarget() { 5588 return getDisplayContent().getImeTarget(IME_TARGET_LAYERING) == this; 5589 } 5590 5591 /** 5592 * Whether the window is non-focusable IME overlay layering target. 5593 */ isImeOverlayLayeringTarget()5594 boolean isImeOverlayLayeringTarget() { 5595 return isImeLayeringTarget() 5596 && (mAttrs.flags & (FLAG_ALT_FOCUSABLE_IM | FLAG_NOT_FOCUSABLE)) != 0; 5597 } 5598 getImeLayeringTarget()5599 WindowState getImeLayeringTarget() { 5600 final InsetsControlTarget target = getDisplayContent().getImeTarget(IME_TARGET_LAYERING); 5601 return target != null ? target.getWindow() : null; 5602 } 5603 getImeInputTarget()5604 WindowState getImeInputTarget() { 5605 final InputTarget target = mDisplayContent.getImeInputTarget(); 5606 return target != null ? target.getWindowState() : null; 5607 } 5608 forceReportingResized()5609 void forceReportingResized() { 5610 mWindowFrames.forceReportingResized(); 5611 } 5612 5613 /** Returns the {@link WindowFrames} associated with this {@link WindowState}. */ getWindowFrames()5614 WindowFrames getWindowFrames() { 5615 return mWindowFrames; 5616 } 5617 resetContentChanged()5618 void resetContentChanged() { 5619 mWindowFrames.setContentChanged(false); 5620 } 5621 5622 private final class MoveAnimationSpec implements AnimationSpec { 5623 5624 private final long mDuration; 5625 private Interpolator mInterpolator; 5626 private Point mFrom = new Point(); 5627 private Point mTo = new Point(); 5628 MoveAnimationSpec(int fromX, int fromY, int toX, int toY)5629 private MoveAnimationSpec(int fromX, int fromY, int toX, int toY) { 5630 final Animation anim = AnimationUtils.loadAnimation(mContext, 5631 com.android.internal.R.anim.window_move_from_decor); 5632 mDuration = (long) 5633 (anim.computeDurationHint() * mWmService.getWindowAnimationScaleLocked()); 5634 mInterpolator = anim.getInterpolator(); 5635 mFrom.set(fromX, fromY); 5636 mTo.set(toX, toY); 5637 } 5638 5639 @Override getDuration()5640 public long getDuration() { 5641 return mDuration; 5642 } 5643 5644 @Override apply(Transaction t, SurfaceControl leash, long currentPlayTime)5645 public void apply(Transaction t, SurfaceControl leash, long currentPlayTime) { 5646 final float fraction = getFraction(currentPlayTime); 5647 final float v = mInterpolator.getInterpolation(fraction); 5648 t.setPosition(leash, mFrom.x + (mTo.x - mFrom.x) * v, 5649 mFrom.y + (mTo.y - mFrom.y) * v); 5650 } 5651 5652 @Override dump(PrintWriter pw, String prefix)5653 public void dump(PrintWriter pw, String prefix) { 5654 pw.println(prefix + "from=" + mFrom 5655 + " to=" + mTo 5656 + " duration=" + mDuration); 5657 } 5658 5659 @Override dumpDebugInner(ProtoOutputStream proto)5660 public void dumpDebugInner(ProtoOutputStream proto) { 5661 final long token = proto.start(MOVE); 5662 dumpPointProto(mFrom, proto, FROM); 5663 dumpPointProto(mTo, proto, TO); 5664 proto.write(DURATION_MS, mDuration); 5665 proto.end(token); 5666 } 5667 } 5668 getKeyInterceptionInfo()5669 KeyInterceptionInfo getKeyInterceptionInfo() { 5670 if (mKeyInterceptionInfo == null 5671 || mKeyInterceptionInfo.layoutParamsPrivateFlags != getAttrs().privateFlags 5672 || mKeyInterceptionInfo.layoutParamsType != getAttrs().type 5673 || mKeyInterceptionInfo.windowTitle != getWindowTag() 5674 || mKeyInterceptionInfo.windowOwnerUid != getOwningUid()) { 5675 mKeyInterceptionInfo = new KeyInterceptionInfo(getAttrs().type, getAttrs().privateFlags, 5676 getWindowTag().toString(), getOwningUid()); 5677 } 5678 return mKeyInterceptionInfo; 5679 } 5680 5681 @Override getAnimationFrames(Rect outFrame, Rect outInsets, Rect outStableInsets, Rect outSurfaceInsets)5682 void getAnimationFrames(Rect outFrame, Rect outInsets, Rect outStableInsets, 5683 Rect outSurfaceInsets) { 5684 // Containing frame will usually cover the whole screen, including dialog windows. 5685 // For freeform workspace windows it will not cover the whole screen and it also 5686 // won't exactly match the final freeform window frame (e.g. when overlapping with 5687 // the status bar). In that case we need to use the final frame. 5688 if (inFreeformWindowingMode()) { 5689 outFrame.set(getFrame()); 5690 } else if (areAppWindowBoundsLetterboxed() || mToken.isFixedRotationTransforming()) { 5691 // 1. The letterbox surfaces should be animated with the owner activity, so use task 5692 // bounds to include them. 5693 // 2. If the activity has fixed rotation transform, its windows are rotated in activity 5694 // level. Because the animation runs before display is rotated, task bounds should 5695 // represent the frames in display space coordinates. 5696 outFrame.set(getTask().getBounds()); 5697 } else { 5698 outFrame.set(getParentFrame()); 5699 } 5700 outSurfaceInsets.set(getAttrs().surfaceInsets); 5701 final InsetsState state = getInsetsStateWithVisibilityOverride(); 5702 outInsets.set(state.calculateInsets(outFrame, systemBars(), 5703 false /* ignoreVisibility */).toRect()); 5704 outStableInsets.set(state.calculateInsets(outFrame, systemBars(), 5705 true /* ignoreVisibility */).toRect()); 5706 } 5707 setViewVisibility(int viewVisibility)5708 void setViewVisibility(int viewVisibility) { 5709 mViewVisibility = viewVisibility; 5710 } 5711 getClientViewRootSurface()5712 SurfaceControl getClientViewRootSurface() { 5713 return mWinAnimator.getSurfaceControl(); 5714 } 5715 5716 /** Drops a buffer for this window's view-root from a transaction */ dropBufferFrom(Transaction t)5717 private void dropBufferFrom(Transaction t) { 5718 SurfaceControl viewSurface = getClientViewRootSurface(); 5719 if (viewSurface == null) return; 5720 t.unsetBuffer(viewSurface); 5721 } 5722 5723 @Override shouldUpdateSyncOnReparent()5724 protected boolean shouldUpdateSyncOnReparent() { 5725 // Keep the sync state in case the client is drawing for the latest conifguration or the 5726 // configuration is not changed after reparenting. This avoids a redundant redraw request. 5727 return mSyncState != SYNC_STATE_NONE && !mLastConfigReportedToClient; 5728 } 5729 5730 @Override prepareSync()5731 boolean prepareSync() { 5732 if (!mDrawHandlers.isEmpty()) { 5733 Slog.w(TAG, "prepareSync with mDrawHandlers, " + this + ", " + Debug.getCallers(8)); 5734 } 5735 if (!super.prepareSync()) { 5736 return false; 5737 } 5738 if (mIsWallpaper) { 5739 // TODO(b/233286785): Add sync support to wallpaper. 5740 return true; 5741 } 5742 if (mActivityRecord != null && mViewVisibility != View.VISIBLE 5743 && mWinAnimator.mAttrType != TYPE_BASE_APPLICATION 5744 && mWinAnimator.mAttrType != TYPE_APPLICATION_STARTING) { 5745 // Skip sync for invisible app windows which are not managed by activity lifecycle. 5746 return false; 5747 } 5748 // In the WindowContainer implementation we immediately mark ready 5749 // since a generic WindowContainer only needs to wait for its 5750 // children to finish and is immediately ready from its own 5751 // perspective but at the WindowState level we need to wait for ourselves 5752 // to draw even if the children draw first or don't need to sync, so we start 5753 // in WAITING state rather than READY. 5754 mSyncState = SYNC_STATE_WAITING_FOR_DRAW; 5755 5756 if (mPrepareSyncSeqId > 0) { 5757 // another prepareSync during existing sync (eg. reparented), so pre-emptively 5758 // drop buffer (if exists). If the buffer hasn't been received yet, it will be 5759 // dropped in finishDrawing. 5760 ProtoLog.d(WM_DEBUG_SYNC_ENGINE, "Preparing to sync a window that was already in the" 5761 + " sync, so try dropping buffer. win=%s", this); 5762 dropBufferFrom(mSyncTransaction); 5763 } 5764 5765 mSyncSeqId++; 5766 if (getSyncMethod() == BLASTSyncEngine.METHOD_BLAST) { 5767 mPrepareSyncSeqId = mSyncSeqId; 5768 requestRedrawForSync(); 5769 } else if (mHasSurface && mWinAnimator.mDrawState != DRAW_PENDING) { 5770 // Only need to request redraw if the window has reported draw. 5771 requestRedrawForSync(); 5772 } 5773 return true; 5774 } 5775 5776 @Override isSyncFinished(BLASTSyncEngine.SyncGroup group)5777 boolean isSyncFinished(BLASTSyncEngine.SyncGroup group) { 5778 if (!isVisibleRequested() || isFullyTransparent()) { 5779 // Don't wait for invisible windows. However, we don't alter the state in case the 5780 // window becomes visible while the sync group is still active. 5781 return true; 5782 } 5783 if (mSyncState == SYNC_STATE_WAITING_FOR_DRAW && mLastConfigReportedToClient && isDrawn() 5784 && mPrepareSyncSeqId <= 0) { 5785 // Complete the sync state immediately for a drawn window that doesn't need to redraw. 5786 onSyncFinishedDrawing(); 5787 } 5788 return super.isSyncFinished(group); 5789 } 5790 5791 @Override finishSync(Transaction outMergedTransaction, BLASTSyncEngine.SyncGroup group, boolean cancel)5792 void finishSync(Transaction outMergedTransaction, BLASTSyncEngine.SyncGroup group, 5793 boolean cancel) { 5794 final BLASTSyncEngine.SyncGroup syncGroup = getSyncGroup(); 5795 if (syncGroup != null && group != syncGroup) return; 5796 mPrepareSyncSeqId = 0; 5797 if (cancel) { 5798 // This is leaving sync so any buffers left in the sync have a chance of 5799 // being applied out-of-order and can also block the buffer queue for this 5800 // window. To prevent this, drop the buffer. 5801 dropBufferFrom(mSyncTransaction); 5802 } 5803 super.finishSync(outMergedTransaction, group, cancel); 5804 } 5805 finishDrawing(SurfaceControl.Transaction postDrawTransaction, int syncSeqId)5806 boolean finishDrawing(SurfaceControl.Transaction postDrawTransaction, int syncSeqId) { 5807 if (mOrientationChangeRedrawRequestTime > 0) { 5808 final long duration = 5809 SystemClock.elapsedRealtime() - mOrientationChangeRedrawRequestTime; 5810 Slog.i(TAG, "finishDrawing of orientation change: " + this + " " + duration + "ms"); 5811 mOrientationChangeRedrawRequestTime = 0; 5812 } else if (mActivityRecord != null && mActivityRecord.mRelaunchStartTime != 0 5813 && mActivityRecord.findMainWindow(false /* includeStartingApp */) == this) { 5814 final long duration = 5815 SystemClock.elapsedRealtime() - mActivityRecord.mRelaunchStartTime; 5816 Slog.i(TAG, "finishDrawing of relaunch: " + this + " " + duration + "ms"); 5817 mActivityRecord.finishOrAbortReplacingWindow(); 5818 } 5819 if (mActivityRecord != null && mAttrs.type == TYPE_APPLICATION_STARTING) { 5820 mWmService.mAtmService.mTaskSupervisor.getActivityMetricsLogger() 5821 .notifyStartingWindowDrawn(mActivityRecord); 5822 } 5823 5824 final boolean syncActive = mPrepareSyncSeqId > 0; 5825 final boolean syncStillPending = syncActive && mPrepareSyncSeqId > syncSeqId; 5826 if (syncStillPending && postDrawTransaction != null) { 5827 ProtoLog.d(WM_DEBUG_SYNC_ENGINE, "Got a buffer for request id=%d but latest request is" 5828 + " id=%d. Since the buffer is out-of-date, drop it. win=%s", syncSeqId, 5829 mPrepareSyncSeqId, this); 5830 // sync is waiting for a newer seqId, so this buffer is obsolete and can be dropped 5831 // to free up the buffer queue. 5832 dropBufferFrom(postDrawTransaction); 5833 } 5834 5835 final boolean hasSyncHandlers = executeDrawHandlers(postDrawTransaction, syncSeqId); 5836 5837 boolean skipLayout = false; 5838 boolean layoutNeeded = false; 5839 // Control the timing to switch the appearance of window with different rotations. 5840 final AsyncRotationController asyncRotationController = 5841 mDisplayContent.getAsyncRotationController(); 5842 if (asyncRotationController != null 5843 && asyncRotationController.handleFinishDrawing(this, postDrawTransaction)) { 5844 // Consume the transaction because the controller will apply it with fade animation. 5845 // Layout is not needed because the window will be hidden by the fade leash. 5846 postDrawTransaction = null; 5847 skipLayout = true; 5848 } else if (syncActive) { 5849 // Currently in a Sync that is using BLAST. 5850 if (!syncStillPending) { 5851 layoutNeeded = onSyncFinishedDrawing(); 5852 } 5853 if (postDrawTransaction != null) { 5854 mSyncTransaction.merge(postDrawTransaction); 5855 // Consume the transaction because the sync group will merge it. 5856 postDrawTransaction = null; 5857 } 5858 } else if (syncNextBuffer()) { 5859 // Sync that is not using BLAST 5860 layoutNeeded = onSyncFinishedDrawing(); 5861 } 5862 5863 layoutNeeded |= mWinAnimator.finishDrawingLocked(postDrawTransaction); 5864 // We always want to force a traversal after a finish draw for blast sync. 5865 return !skipLayout && (hasSyncHandlers || layoutNeeded); 5866 } 5867 immediatelyNotifyBlastSync()5868 void immediatelyNotifyBlastSync() { 5869 // We could be more subtle with Integer.MAX_VALUE and track a seqId in the timeout. 5870 finishDrawing(null, Integer.MAX_VALUE); 5871 mWmService.mH.removeMessages(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this); 5872 } 5873 5874 @Override fillsParent()5875 boolean fillsParent() { 5876 return mAttrs.type == TYPE_APPLICATION_STARTING; 5877 } 5878 5879 @Override showWallpaper()5880 boolean showWallpaper() { 5881 if (!isVisibleRequested() 5882 // in multi-window mode, wallpaper is always visible at the back and not tied to 5883 // the app (there is no wallpaper target). 5884 || inMultiWindowMode()) { 5885 return false; 5886 } 5887 return hasWallpaper(); 5888 } 5889 5890 @Override hasWallpaper()5891 boolean hasWallpaper() { 5892 return (mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0 || hasWallpaperForLetterboxBackground(); 5893 } 5894 hasWallpaperForLetterboxBackground()5895 boolean hasWallpaperForLetterboxBackground() { 5896 return mActivityRecord != null && mActivityRecord.hasWallpaperBackgroundForLetterbox(); 5897 } 5898 5899 /** 5900 * When using the two WindowOrganizer sync-primitives (BoundsChangeTransaction, BLASTSync) 5901 * it can be a little difficult to predict whether your change will actually trigger redrawing 5902 * on the client side. To ease the burden on shell developers, we force send MSG_RESIZED 5903 * for Windows involved in these Syncs 5904 */ shouldSendRedrawForSync()5905 private boolean shouldSendRedrawForSync() { 5906 if (mRedrawForSyncReported) { 5907 return false; 5908 } 5909 if (mInRelayout && (mPrepareSyncSeqId > 0 || (mViewVisibility == View.VISIBLE 5910 && mWinAnimator.mDrawState == DRAW_PENDING))) { 5911 // The client will report draw if it gets the sync seq id from relayout or it is 5912 // drawing for being visible, then no need to request redraw. 5913 return false; 5914 } 5915 return syncNextBuffer(); 5916 } 5917 getSyncMethod()5918 int getSyncMethod() { 5919 final BLASTSyncEngine.SyncGroup syncGroup = getSyncGroup(); 5920 if (syncGroup == null) return BLASTSyncEngine.METHOD_NONE; 5921 if (mSyncMethodOverride != BLASTSyncEngine.METHOD_UNDEFINED) return mSyncMethodOverride; 5922 return syncGroup.mSyncMethod; 5923 } 5924 shouldSyncWithBuffers()5925 boolean shouldSyncWithBuffers() { 5926 if (!mDrawHandlers.isEmpty()) return true; 5927 return getSyncMethod() == BLASTSyncEngine.METHOD_BLAST; 5928 } 5929 requestRedrawForSync()5930 void requestRedrawForSync() { 5931 mRedrawForSyncReported = false; 5932 } 5933 5934 /** 5935 * This method is used to control whether we return the BLAST_SYNC flag 5936 * from relayoutWindow calls on this window (triggering the client to redirect 5937 * it's next draw in to a transaction). If we have pending draw handlers, we are 5938 * looking for the client to sync. 5939 * 5940 * See {@link WindowState#mDrawHandlers} 5941 */ 5942 @Override syncNextBuffer()5943 boolean syncNextBuffer() { 5944 return super.syncNextBuffer() || (mDrawHandlers.size() != 0); 5945 } 5946 5947 /** 5948 * Apply the transaction with the next window redraw. A full relayout/finishDrawing 5949 * cycle must occur before completion. This means if you call the function while 5950 * "in relayout", the results may be undefined but at all other times the function 5951 * should sort of transparently work like this: 5952 * 1. Make changes to WM hierarchy (say change app configuration) 5953 * 2. Call applyWithNextDraw 5954 * 3. After finishDrawing, our consumer will be passed the Transaction 5955 * containing the buffer, and we can merge in additional operations. 5956 * See {@link WindowState#mDrawHandlers} 5957 */ applyWithNextDraw(Consumer<SurfaceControl.Transaction> consumer)5958 void applyWithNextDraw(Consumer<SurfaceControl.Transaction> consumer) { 5959 if (mSyncState != SYNC_STATE_NONE) { 5960 Slog.w(TAG, "applyWithNextDraw with mSyncState=" + mSyncState + ", " + this 5961 + ", " + Debug.getCallers(8)); 5962 } 5963 mSyncSeqId++; 5964 mDrawHandlers.add(new DrawHandler(mSyncSeqId, consumer)); 5965 5966 requestRedrawForSync(); 5967 5968 mWmService.mH.sendNewMessageDelayed(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this, 5969 BLAST_TIMEOUT_DURATION); 5970 } 5971 5972 /** 5973 * Drain the draw handlers, called from finishDrawing() 5974 * See {@link WindowState#mPendingDrawHandlers} 5975 */ executeDrawHandlers(SurfaceControl.Transaction t, int seqId)5976 boolean executeDrawHandlers(SurfaceControl.Transaction t, int seqId) { 5977 boolean hadHandlers = false; 5978 boolean applyHere = false; 5979 if (t == null) { 5980 t = mTmpTransaction; 5981 applyHere = true; 5982 } 5983 5984 final List<DrawHandler> handlersToRemove = new ArrayList<>(); 5985 // Iterate forwards to ensure we process in the same order 5986 // we added. 5987 for (int i = 0; i < mDrawHandlers.size(); i++) { 5988 final DrawHandler h = mDrawHandlers.get(i); 5989 if (h.mSeqId <= seqId) { 5990 h.mConsumer.accept(t); 5991 handlersToRemove.add(h); 5992 hadHandlers = true; 5993 } 5994 } 5995 for (int i = 0; i < handlersToRemove.size(); i++) { 5996 final DrawHandler h = handlersToRemove.get(i); 5997 mDrawHandlers.remove(h); 5998 } 5999 6000 if (hadHandlers) { 6001 mWmService.mH.removeMessages(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this); 6002 } 6003 6004 if (applyHere) { 6005 t.apply(); 6006 } 6007 6008 return hadHandlers; 6009 } 6010 6011 /** 6012 * Adds an additional translation offset to be applied when positioning the surface. Used to 6013 * correct offsets in specific reparenting situations, e.g. the navigation bar window attached 6014 * on the lower split-screen app. 6015 */ setSurfaceTranslationY(int translationY)6016 void setSurfaceTranslationY(int translationY) { 6017 mSurfaceTranslationY = translationY; 6018 } 6019 6020 @Override getWindowType()6021 @WindowManager.LayoutParams.WindowType int getWindowType() { 6022 return mAttrs.type; 6023 } 6024 markRedrawForSyncReported()6025 void markRedrawForSyncReported() { 6026 mRedrawForSyncReported = true; 6027 } 6028 setWallpaperOffset(int dx, int dy, float scale)6029 boolean setWallpaperOffset(int dx, int dy, float scale) { 6030 if (mXOffset == dx && mYOffset == dy && Float.compare(mWallpaperScale, scale) == 0) { 6031 return false; 6032 } 6033 mXOffset = dx; 6034 mYOffset = dy; 6035 mWallpaperScale = scale; 6036 scheduleAnimation(); 6037 return true; 6038 } 6039 isTrustedOverlay()6040 boolean isTrustedOverlay() { 6041 if (surfaceTrustedOverlay()) { 6042 WindowState parentWindow = getParentWindow(); 6043 return isWindowTrustedOverlay() || (parentWindow != null 6044 && parentWindow.isWindowTrustedOverlay()); 6045 } else { 6046 return mInputWindowHandle.isTrustedOverlay(); 6047 } 6048 } 6049 receiveFocusFromTapOutside()6050 public boolean receiveFocusFromTapOutside() { 6051 return canReceiveKeys(true); 6052 } 6053 6054 @Override handleTapOutsideFocusOutsideSelf()6055 public void handleTapOutsideFocusOutsideSelf() { 6056 // Nothing to do here since raising the other window will naturally take care of 6057 // us loosing focus 6058 } 6059 6060 @Override handleTapOutsideFocusInsideSelf()6061 public void handleTapOutsideFocusInsideSelf() { 6062 mWmService.moveDisplayToTopInternal(getDisplayId()); 6063 mWmService.handleTaskFocusChange(getTask(), mActivityRecord); 6064 } 6065 clearClientTouchableRegion()6066 void clearClientTouchableRegion() { 6067 mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME; 6068 mGivenTouchableRegion.setEmpty(); 6069 } 6070 6071 @Override shouldControlIme()6072 public boolean shouldControlIme() { 6073 return !inMultiWindowMode(); 6074 } 6075 6076 @Override canScreenshotIme()6077 public boolean canScreenshotIme() { 6078 return !isSecureLocked(); 6079 } 6080 6081 @Override getActivityRecord()6082 public ActivityRecord getActivityRecord() { 6083 return mActivityRecord; 6084 } 6085 6086 @Override isInputMethodClientFocus(int uid, int pid)6087 public boolean isInputMethodClientFocus(int uid, int pid) { 6088 return getDisplayContent().isInputMethodClientFocus(uid, pid); 6089 } 6090 6091 @Override dumpProto(ProtoOutputStream proto, long fieldId, @WindowTraceLogLevel int logLevel)6092 public void dumpProto(ProtoOutputStream proto, long fieldId, 6093 @WindowTraceLogLevel int logLevel) { 6094 dumpDebug(proto, fieldId, logLevel); 6095 } 6096 cancelAndRedraw()6097 public boolean cancelAndRedraw() { 6098 // Cancel any draw requests during a sync. 6099 return mPrepareSyncSeqId > 0; 6100 } 6101 isActivityWindow()6102 public boolean isActivityWindow() { 6103 return mActivityRecord != null; 6104 } 6105 setSecureLocked(boolean isSecure)6106 void setSecureLocked(boolean isSecure) { 6107 ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE isSecure=%b: %s", isSecure, getName()); 6108 if (secureWindowState()) { 6109 if (mSurfaceControl == null) { 6110 return; 6111 } 6112 getPendingTransaction().setSecure(mSurfaceControl, isSecure); 6113 } else { 6114 if (mWinAnimator.mSurfaceController == null 6115 || mWinAnimator.mSurfaceController.mSurfaceControl == null) { 6116 return; 6117 } 6118 getPendingTransaction().setSecure(mWinAnimator.mSurfaceController.mSurfaceControl, 6119 isSecure); 6120 } 6121 if (mDisplayContent != null) { 6122 mDisplayContent.refreshImeSecureFlag(getSyncTransaction()); 6123 } 6124 mWmService.scheduleAnimationLocked(); 6125 } 6126 } 6127