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