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