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_STACK_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.isSplitScreenWindowingMode; 24 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; 25 import static android.os.PowerManager.DRAW_WAKE_LOCK; 26 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; 27 import static android.view.Display.DEFAULT_DISPLAY; 28 import static android.view.SurfaceControl.Transaction; 29 import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; 30 import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; 31 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT; 32 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME; 33 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION; 34 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE; 35 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; 36 import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW; 37 import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON; 38 import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; 39 import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND; 40 import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD; 41 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS; 42 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 43 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; 44 import static android.view.WindowManager.LayoutParams.FLAG_SCALED; 45 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; 46 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; 47 import static android.view.WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON; 48 import static android.view.WindowManager.LayoutParams.FORMAT_CHANGED; 49 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW; 50 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; 51 import static android.view.WindowManager.LayoutParams.MATCH_PARENT; 52 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW; 53 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME; 54 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION; 55 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH; 56 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; 57 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST; 58 import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; 59 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; 60 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA; 61 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY; 62 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; 63 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; 64 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; 65 import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION; 66 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; 67 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; 68 import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY; 69 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; 70 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL; 71 import static android.view.WindowManager.LayoutParams.TYPE_TOAST; 72 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; 73 import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType; 74 import static android.view.WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_DOCKED; 75 import static android.view.WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_FREEFORM; 76 import static android.view.WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME; 77 import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED; 78 79 import static com.android.server.am.ActivityManagerService.MY_PID; 80 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 81 import static com.android.server.policy.WindowManagerPolicy.TRANSIT_ENTER; 82 import static com.android.server.policy.WindowManagerPolicy.TRANSIT_EXIT; 83 import static com.android.server.policy.WindowManagerPolicy.TRANSIT_PREVIEW_DONE; 84 import static com.android.server.wm.AnimationSpecProto.MOVE; 85 import static com.android.server.wm.DisplayContent.logsGestureExclusionRestrictions; 86 import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER; 87 import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM; 88 import static com.android.server.wm.IdentifierProto.HASH_CODE; 89 import static com.android.server.wm.IdentifierProto.TITLE; 90 import static com.android.server.wm.IdentifierProto.USER_ID; 91 import static com.android.server.wm.MoveAnimationSpecProto.DURATION_MS; 92 import static com.android.server.wm.MoveAnimationSpecProto.FROM; 93 import static com.android.server.wm.MoveAnimationSpecProto.TO; 94 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE; 95 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM; 96 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS; 97 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_CONFIGURATION; 98 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS; 99 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT; 100 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD; 101 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT; 102 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS; 103 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION; 104 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_POWER; 105 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RESIZE; 106 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW; 107 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE; 108 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; 109 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT; 110 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; 111 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 112 import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION; 113 import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER; 114 import static com.android.server.wm.WindowManagerService.TYPE_LAYER_OFFSET; 115 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL; 116 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_REMOVING_FOCUS; 117 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES; 118 import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_TIMEOUT; 119 import static com.android.server.wm.WindowManagerService.localLOGV; 120 import static com.android.server.wm.WindowStateAnimator.COMMIT_DRAW_PENDING; 121 import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING; 122 import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN; 123 import static com.android.server.wm.WindowStateAnimator.PRESERVED_SURFACE_LAYER; 124 import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW; 125 import static com.android.server.wm.WindowStateProto.ANIMATING_EXIT; 126 import static com.android.server.wm.WindowStateProto.ANIMATOR; 127 import static com.android.server.wm.WindowStateProto.ATTRIBUTES; 128 import static com.android.server.wm.WindowStateProto.CHILD_WINDOWS; 129 import static com.android.server.wm.WindowStateProto.DESTROYING; 130 import static com.android.server.wm.WindowStateProto.DISPLAY_ID; 131 import static com.android.server.wm.WindowStateProto.FINISHED_SEAMLESS_ROTATION_FRAME; 132 import static com.android.server.wm.WindowStateProto.FORCE_SEAMLESS_ROTATION; 133 import static com.android.server.wm.WindowStateProto.GIVEN_CONTENT_INSETS; 134 import static com.android.server.wm.WindowStateProto.HAS_SURFACE; 135 import static com.android.server.wm.WindowStateProto.IDENTIFIER; 136 import static com.android.server.wm.WindowStateProto.IS_ON_SCREEN; 137 import static com.android.server.wm.WindowStateProto.IS_READY_FOR_DISPLAY; 138 import static com.android.server.wm.WindowStateProto.IS_VISIBLE; 139 import static com.android.server.wm.WindowStateProto.PENDING_SEAMLESS_ROTATION; 140 import static com.android.server.wm.WindowStateProto.REMOVED; 141 import static com.android.server.wm.WindowStateProto.REMOVE_ON_EXIT; 142 import static com.android.server.wm.WindowStateProto.REQUESTED_HEIGHT; 143 import static com.android.server.wm.WindowStateProto.REQUESTED_WIDTH; 144 import static com.android.server.wm.WindowStateProto.STACK_ID; 145 import static com.android.server.wm.WindowStateProto.SURFACE_INSETS; 146 import static com.android.server.wm.WindowStateProto.SURFACE_POSITION; 147 import static com.android.server.wm.WindowStateProto.SYSTEM_UI_VISIBILITY; 148 import static com.android.server.wm.WindowStateProto.VIEW_VISIBILITY; 149 import static com.android.server.wm.WindowStateProto.WINDOW_CONTAINER; 150 import static com.android.server.wm.WindowStateProto.WINDOW_FRAMES; 151 152 import android.annotation.CallSuper; 153 import android.annotation.Nullable; 154 import android.app.AppOpsManager; 155 import android.content.Context; 156 import android.content.res.Configuration; 157 import android.graphics.Matrix; 158 import android.graphics.PixelFormat; 159 import android.graphics.Point; 160 import android.graphics.Rect; 161 import android.graphics.Region; 162 import android.os.Binder; 163 import android.os.Build; 164 import android.os.Debug; 165 import android.os.IBinder; 166 import android.os.PowerManager; 167 import android.os.PowerManager.WakeReason; 168 import android.os.RemoteCallbackList; 169 import android.os.RemoteException; 170 import android.os.SystemClock; 171 import android.os.Trace; 172 import android.os.UserHandle; 173 import android.os.WorkSource; 174 import android.provider.Settings; 175 import android.text.TextUtils; 176 import android.util.ArraySet; 177 import android.util.DisplayMetrics; 178 import android.util.MergedConfiguration; 179 import android.util.Slog; 180 import android.util.StatsLog; 181 import android.util.TimeUtils; 182 import android.util.proto.ProtoOutputStream; 183 import android.view.Display; 184 import android.view.DisplayCutout; 185 import android.view.DisplayInfo; 186 import android.view.Gravity; 187 import android.view.IApplicationToken; 188 import android.view.IWindow; 189 import android.view.IWindowFocusObserver; 190 import android.view.IWindowId; 191 import android.view.InputChannel; 192 import android.view.InputEvent; 193 import android.view.InputEventReceiver; 194 import android.view.InputWindowHandle; 195 import android.view.Surface.Rotation; 196 import android.view.SurfaceControl; 197 import android.view.SurfaceSession; 198 import android.view.View; 199 import android.view.ViewTreeObserver; 200 import android.view.WindowInfo; 201 import android.view.WindowManager; 202 import android.view.animation.Animation; 203 import android.view.animation.AnimationUtils; 204 import android.view.animation.Interpolator; 205 206 import com.android.internal.annotations.VisibleForTesting; 207 import com.android.internal.util.ToBooleanFunction; 208 import com.android.server.policy.WindowManagerPolicy; 209 import com.android.server.wm.LocalAnimationAdapter.AnimationSpec; 210 import com.android.server.wm.utils.InsetUtils; 211 import com.android.server.wm.utils.WmDisplayCutout; 212 213 import java.io.PrintWriter; 214 import java.lang.ref.WeakReference; 215 import java.util.ArrayList; 216 import java.util.Comparator; 217 import java.util.List; 218 import java.util.function.Predicate; 219 220 /** A window in the window manager. */ 221 class WindowState extends WindowContainer<WindowState> implements WindowManagerPolicy.WindowState { 222 static final String TAG = TAG_WITH_CLASS_NAME ? "WindowState" : TAG_WM; 223 224 // The minimal size of a window within the usable area of the freeform stack. 225 // TODO(multi-window): fix the min sizes when we have minimum width/height support, 226 // use hard-coded min sizes for now. 227 static final int MINIMUM_VISIBLE_WIDTH_IN_DP = 48; 228 static final int MINIMUM_VISIBLE_HEIGHT_IN_DP = 32; 229 230 // The thickness of a window resize handle outside the window bounds on the free form workspace 231 // to capture touch events in that area. 232 static final int RESIZE_HANDLE_WIDTH_IN_DP = 30; 233 234 static final int EXCLUSION_LEFT = 0; 235 static final int EXCLUSION_RIGHT = 1; 236 237 final WindowManagerPolicy mPolicy; 238 final Context mContext; 239 final Session mSession; 240 final IWindow mClient; 241 final int mAppOp; 242 // UserId and appId of the owner. Don't display windows of non-current user. 243 final int mOwnerUid; 244 /** The owner has {@link android.Manifest.permission#INTERNAL_SYSTEM_WINDOW} */ 245 final boolean mOwnerCanAddInternalSystemWindow; 246 final WindowId mWindowId; 247 WindowToken mToken; 248 // The same object as mToken if this is an app window and null for non-app windows. 249 AppWindowToken mAppToken; 250 251 // mAttrs.flags is tested in animation without being locked. If the bits tested are ever 252 // modified they will need to be locked. 253 final WindowManager.LayoutParams mAttrs = new WindowManager.LayoutParams(); 254 final DeathRecipient mDeathRecipient; 255 private boolean mIsChildWindow; 256 final int mBaseLayer; 257 final int mSubLayer; 258 final boolean mLayoutAttached; 259 final boolean mIsImWindow; 260 final boolean mIsWallpaper; 261 private final boolean mIsFloatingLayer; 262 int mSeq; 263 int mViewVisibility; 264 int mSystemUiVisibility; 265 266 /** 267 * The visibility flag of the window based on policy like {@link WindowManagerPolicy}. 268 * Normally set by calling {@link #showLw} and {@link #hideLw}. 269 * 270 * TODO: b/131253938 This will eventually be split into individual visibility policy flags. 271 */ 272 static final int LEGACY_POLICY_VISIBILITY = 1; 273 /** 274 * The visibility flag that determines whether this window is visible for the current user. 275 */ 276 private static final int VISIBLE_FOR_USER = 1 << 1; 277 private static final int POLICY_VISIBILITY_ALL = VISIBLE_FOR_USER | LEGACY_POLICY_VISIBILITY; 278 /** 279 * The Bitwise-or of flags that contribute to visibility of the WindowState 280 */ 281 private int mPolicyVisibility = POLICY_VISIBILITY_ALL; 282 283 /** 284 * Whether {@link #LEGACY_POLICY_VISIBILITY} flag should be set after a transition animation. 285 * For example, {@link #LEGACY_POLICY_VISIBILITY} might be set during an exit animation to hide 286 * it and then unset when the value of {@link #mLegacyPolicyVisibilityAfterAnim} is false 287 * after the exit animation is done. 288 * 289 * TODO: b/131253938 Determine whether this can be changed to use a visibility flag instead. 290 */ 291 boolean mLegacyPolicyVisibilityAfterAnim = true; 292 // overlay window is hidden because the owning app is suspended 293 private boolean mHiddenWhileSuspended; 294 private boolean mAppOpVisibility = true; 295 boolean mPermanentlyHidden; // the window should never be shown again 296 // This is a non-system overlay window that is currently force hidden. 297 private boolean mForceHideNonSystemOverlayWindow; 298 boolean mAppFreezing; 299 boolean mHidden = true; // Used to determine if to show child windows. 300 boolean mWallpaperVisible; // for wallpaper, what was last vis report? 301 private boolean mDragResizing; 302 private boolean mDragResizingChangeReported = true; 303 private int mResizeMode; 304 /** 305 * Special mode that is intended only for the rounded corner overlay: during rotation 306 * transition, we un-rotate the window token such that the window appears as it did before the 307 * rotation. 308 */ 309 final boolean mForceSeamlesslyRotate; 310 SeamlessRotator mPendingSeamlessRotate; 311 long mFinishSeamlessRotateFrameNumber; 312 313 private RemoteCallbackList<IWindowFocusObserver> mFocusCallbacks; 314 315 /** 316 * The window size that was requested by the application. These are in 317 * the application's coordinate space (without compatibility scale applied). 318 */ 319 int mRequestedWidth; 320 int mRequestedHeight; 321 private int mLastRequestedWidth; 322 private int mLastRequestedHeight; 323 324 int mLayer; 325 boolean mHaveFrame; 326 boolean mObscured; 327 328 int mLayoutSeq = -1; 329 330 /** @see #addEmbeddedDisplayContent(DisplayContent dc) */ 331 private final ArraySet<DisplayContent> mEmbeddedDisplayContents = new ArraySet<>(); 332 333 /** 334 * Used to store last reported to client configuration and check if we have newer available. 335 * We'll send configuration to client only if it is different from the last applied one and 336 * client won't perform unnecessary updates. 337 */ 338 private final MergedConfiguration mLastReportedConfiguration = new MergedConfiguration(); 339 340 /** @see #isLastConfigReportedToClient() */ 341 private boolean mLastConfigReportedToClient; 342 343 private final Configuration mTempConfiguration = new Configuration(); 344 345 /** 346 * The last content insets returned to the client in relayout. We use 347 * these in the bounds animation to ensure we only observe inset changes 348 * at the same time that a client resizes it's surface so that we may use 349 * the geometryAppliesWithResize synchronization mechanism to keep 350 * the contents in place. 351 */ 352 final Rect mLastRelayoutContentInsets = new Rect(); 353 354 /** 355 * Set to true if we are waiting for this window to receive its 356 * given internal insets before laying out other windows based on it. 357 */ 358 boolean mGivenInsetsPending; 359 360 /** 361 * These are the content insets that were given during layout for 362 * this window, to be applied to windows behind it. 363 */ 364 final Rect mGivenContentInsets = new Rect(); 365 366 /** 367 * These are the visible insets that were given during layout for 368 * this window, to be applied to windows behind it. 369 */ 370 final Rect mGivenVisibleInsets = new Rect(); 371 372 /** 373 * This is the given touchable area relative to the window frame, or null if none. 374 */ 375 final Region mGivenTouchableRegion = new Region(); 376 377 /** 378 * Flag indicating whether the touchable region should be adjusted by 379 * the visible insets; if false the area outside the visible insets is 380 * NOT touchable, so we must use those to adjust the frame during hit 381 * tests. 382 */ 383 int mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME; 384 385 // Current transformation being applied. 386 float mGlobalScale=1; 387 float mInvGlobalScale=1; 388 float mHScale=1, mVScale=1; 389 float mLastHScale=1, mLastVScale=1; 390 final Matrix mTmpMatrix = new Matrix(); 391 392 private final WindowFrames mWindowFrames = new WindowFrames(); 393 394 /** 395 * Usually empty. Set to the task's tempInsetFrame. See 396 *{@link android.app.IActivityTaskManager#resizeDockedStack}. 397 */ 398 private final Rect mInsetFrame = new Rect(); 399 400 /** 401 * List of rects where system gestures should be ignored. 402 * 403 * Coordinates are relative to the window's position. 404 */ 405 private final List<Rect> mExclusionRects = new ArrayList<>(); 406 407 // 0 = left, 1 = right 408 private final int[] mLastRequestedExclusionHeight = {0, 0}; 409 private final int[] mLastGrantedExclusionHeight = {0, 0}; 410 private final long[] mLastExclusionLogUptimeMillis = {0, 0}; 411 412 private boolean mLastShownChangedReported; 413 414 // If a window showing a wallpaper: the requested offset for the 415 // wallpaper; if a wallpaper window: the currently applied offset. 416 float mWallpaperX = -1; 417 float mWallpaperY = -1; 418 419 // If a window showing a wallpaper: what fraction of the offset 420 // range corresponds to a full virtual screen. 421 float mWallpaperXStep = -1; 422 float mWallpaperYStep = -1; 423 424 // If a window showing a wallpaper: a raw pixel offset to forcibly apply 425 // to its window; if a wallpaper window: not used. 426 int mWallpaperDisplayOffsetX = Integer.MIN_VALUE; 427 int mWallpaperDisplayOffsetY = Integer.MIN_VALUE; 428 429 /** 430 * This is set after IWindowSession.relayout() has been called at 431 * least once for the window. It allows us to detect the situation 432 * where we don't yet have a surface, but should have one soon, so 433 * we can give the window focus before waiting for the relayout. 434 */ 435 boolean mRelayoutCalled; 436 437 boolean mInRelayout; 438 439 /** 440 * If the application has called relayout() with changes that can 441 * impact its window's size, we need to perform a layout pass on it 442 * even if it is not currently visible for layout. This is set 443 * when in that case until the layout is done. 444 */ 445 boolean mLayoutNeeded; 446 447 /** Currently running an exit animation? */ 448 boolean mAnimatingExit; 449 450 /** Currently on the mDestroySurface list? */ 451 boolean mDestroying; 452 453 /** Completely remove from window manager after exit animation? */ 454 boolean mRemoveOnExit; 455 456 /** 457 * Whether the app died while it was visible, if true we might need 458 * to continue to show it until it's restarted. 459 */ 460 boolean mAppDied; 461 462 /** 463 * Set when the orientation is changing and this window has not yet 464 * been updated for the new orientation. 465 */ 466 private boolean mOrientationChanging; 467 468 /** 469 * Sometimes in addition to the mOrientationChanging 470 * flag we report that the orientation is changing 471 * due to a mismatch in current and reported configuration. 472 * 473 * In the case of timeout we still need to make sure we 474 * leave the orientation changing state though, so we 475 * use this as a special time out escape hatch. 476 */ 477 private boolean mOrientationChangeTimedOut; 478 479 /** 480 * The orientation during the last visible call to relayout. If our 481 * current orientation is different, the window can't be ready 482 * to be shown. 483 */ 484 int mLastVisibleLayoutRotation = -1; 485 486 /** 487 * Set when we need to report the orientation change to client to trigger a relayout. 488 */ 489 boolean mReportOrientationChanged; 490 491 /** 492 * How long we last kept the screen frozen. 493 */ 494 int mLastFreezeDuration; 495 496 /** Is this window now (or just being) removed? */ 497 boolean mRemoved; 498 499 /** 500 * It is save to remove the window and destroy the surface because the client requested removal 501 * or some other higher level component said so (e.g. activity manager). 502 * TODO: We should either have different booleans for the removal reason or use a bit-field. 503 */ 504 boolean mWindowRemovalAllowed; 505 506 // Input channel and input window handle used by the input dispatcher. 507 final InputWindowHandle mInputWindowHandle; 508 InputChannel mInputChannel; 509 private InputChannel mClientChannel; 510 511 // Used to improve performance of toString() 512 private String mStringNameCache; 513 private CharSequence mLastTitle; 514 private boolean mWasExiting; 515 516 final WindowStateAnimator mWinAnimator; 517 518 boolean mHasSurface = false; 519 520 /** When true this window can be displayed on screens owther than mOwnerUid's */ 521 private boolean mShowToOwnerOnly; 522 523 // Whether the window was visible when we set the app to invisible last time. WM uses 524 // this as a hint to restore the surface (if available) for early animation next time 525 // the app is brought visible. 526 private boolean mWasVisibleBeforeClientHidden; 527 528 // This window will be replaced due to relaunch. This allows window manager 529 // to differentiate between simple removal of a window and replacement. In the latter case it 530 // will preserve the old window until the new one is drawn. 531 boolean mWillReplaceWindow = false; 532 // If true, the replaced window was already requested to be removed. 533 private boolean mReplacingRemoveRequested = false; 534 // Whether the replacement of the window should trigger app transition animation. 535 private boolean mAnimateReplacingWindow = false; 536 // If not null, the window that will be used to replace the old one. This is being set when 537 // the window is added and unset when this window reports its first draw. 538 private WindowState mReplacementWindow = null; 539 // For the new window in the replacement transition, if we have 540 // requested to replace without animation, then we should 541 // make sure we also don't apply an enter animation for 542 // the new window. 543 boolean mSkipEnterAnimationForSeamlessReplacement = false; 544 // Whether this window is being moved via the resize API 545 private boolean mMovedByResize; 546 547 /** 548 * Wake lock for drawing. 549 * Even though it's slightly more expensive to do so, we will use a separate wake lock 550 * for each app that is requesting to draw while dozing so that we can accurately track 551 * who is preventing the system from suspending. 552 * This lock is only acquired on first use. 553 */ 554 private PowerManager.WakeLock mDrawLock; 555 556 private final Rect mTmpRect = new Rect(); 557 private final Point mTmpPoint = new Point(); 558 559 /** 560 * If a window is on a display which has been re-parented to a view in another window, 561 * use this offset to indicate the correct location. 562 */ 563 private final Point mLastReportedDisplayOffset = new Point(); 564 565 /** 566 * Whether the window was resized by us while it was gone for layout. 567 */ 568 boolean mResizedWhileGone = false; 569 570 /** 571 * During seamless rotation we have two phases, first the old window contents 572 * are rotated to look as if they didn't move in the new coordinate system. Then we 573 * have to freeze updates to this layer (to preserve the transformation) until 574 * the resize actually occurs. This is true from when the transformation is set 575 * and false until the transaction to resize is sent. 576 */ 577 boolean mSeamlesslyRotated = false; 578 579 /** 580 * Surface insets from the previous call to relayout(), used to track 581 * if we are changing the Surface insets. 582 */ 583 final Rect mLastSurfaceInsets = new Rect(); 584 585 /** 586 * A flag set by the {@link WindowState} parent to indicate that the parent has examined this 587 * {@link WindowState} in its overall drawing context. This book-keeping allows the parent to 588 * make sure all children have been considered. 589 */ 590 private boolean mDrawnStateEvaluated; 591 592 private final Point mSurfacePosition = new Point(); 593 594 /** 595 * A region inside of this window to be excluded from touch. 596 */ 597 private TapExcludeRegionHolder mTapExcludeRegionHolder; 598 599 /** 600 * Used for testing because the real PowerManager is final. 601 */ 602 private PowerManagerWrapper mPowerManagerWrapper; 603 604 /** 605 * A frame number in which changes requested in this layout will be rendered. 606 */ 607 private long mFrameNumber = -1; 608 609 private static final StringBuilder sTmpSB = new StringBuilder(); 610 611 /** 612 * Compares two window sub-layers and returns -1 if the first is lesser than the second in terms 613 * of z-order and 1 otherwise. 614 */ 615 private static final Comparator<WindowState> sWindowSubLayerComparator = 616 new Comparator<WindowState>() { 617 @Override 618 public int compare(WindowState w1, WindowState w2) { 619 final int layer1 = w1.mSubLayer; 620 final int layer2 = w2.mSubLayer; 621 if (layer1 < layer2 || (layer1 == layer2 && layer2 < 0 )) { 622 // We insert the child window into the list ordered by 623 // the sub-layer. For same sub-layers, the negative one 624 // should go below others; the positive one should go 625 // above others. 626 return -1; 627 } 628 return 1; 629 }; 630 }; 631 632 /** 633 * Indicates whether we have requested a Dim (in the sense of {@link Dimmer}) from our host 634 * container. 635 */ 636 private boolean mIsDimming = false; 637 638 private @Nullable InsetsSourceProvider mInsetProvider; 639 640 private static final float DEFAULT_DIM_AMOUNT_DEAD_WINDOW = 0.5f; 641 seamlesslyRotateIfAllowed(Transaction transaction, @Rotation int oldRotation, @Rotation int rotation, boolean requested)642 void seamlesslyRotateIfAllowed(Transaction transaction, @Rotation int oldRotation, 643 @Rotation int rotation, boolean requested) { 644 // Invisible windows and the wallpaper do not participate in the seamless rotation animation 645 if (!isVisibleNow() || mIsWallpaper) { 646 return; 647 } 648 649 if (mPendingSeamlessRotate != null) { 650 oldRotation = mPendingSeamlessRotate.getOldRotation(); 651 } 652 653 if (mForceSeamlesslyRotate || requested) { 654 mPendingSeamlessRotate = new SeamlessRotator(oldRotation, rotation, getDisplayInfo()); 655 mPendingSeamlessRotate.unrotate(transaction, this); 656 mWmService.markForSeamlessRotation(this, true); 657 } 658 } 659 finishSeamlessRotation(boolean timeout)660 void finishSeamlessRotation(boolean timeout) { 661 if (mPendingSeamlessRotate != null) { 662 mPendingSeamlessRotate.finish(this, timeout); 663 mFinishSeamlessRotateFrameNumber = getFrameNumber(); 664 mPendingSeamlessRotate = null; 665 mWmService.markForSeamlessRotation(this, false); 666 } 667 } 668 getSystemGestureExclusion()669 List<Rect> getSystemGestureExclusion() { 670 return mExclusionRects; 671 } 672 673 /** 674 * Sets the system gesture exclusion rects. 675 * 676 * @return {@code true} if anything changed 677 */ setSystemGestureExclusion(List<Rect> exclusionRects)678 boolean setSystemGestureExclusion(List<Rect> exclusionRects) { 679 if (mExclusionRects.equals(exclusionRects)) { 680 return false; 681 } 682 mExclusionRects.clear(); 683 mExclusionRects.addAll(exclusionRects); 684 return true; 685 } 686 isImplicitlyExcludingAllSystemGestures()687 boolean isImplicitlyExcludingAllSystemGestures() { 688 final int immersiveStickyFlags = 689 SYSTEM_UI_FLAG_HIDE_NAVIGATION | SYSTEM_UI_FLAG_IMMERSIVE_STICKY; 690 final boolean immersiveSticky = 691 (mSystemUiVisibility & immersiveStickyFlags) == immersiveStickyFlags; 692 return immersiveSticky && mWmService.mSystemGestureExcludedByPreQStickyImmersive 693 && mAppToken != null && mAppToken.mTargetSdk < Build.VERSION_CODES.Q; 694 } 695 setLastExclusionHeights(int side, int requested, int granted)696 void setLastExclusionHeights(int side, int requested, int granted) { 697 boolean changed = mLastGrantedExclusionHeight[side] != granted 698 || mLastRequestedExclusionHeight[side] != requested; 699 700 if (changed) { 701 if (mLastShownChangedReported) { 702 logExclusionRestrictions(side); 703 } 704 705 mLastGrantedExclusionHeight[side] = granted; 706 mLastRequestedExclusionHeight[side] = requested; 707 } 708 } 709 710 interface PowerManagerWrapper { wakeUp(long time, @WakeReason int reason, String details)711 void wakeUp(long time, @WakeReason int reason, String details); 712 isInteractive()713 boolean isInteractive(); 714 715 } 716 WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token, WindowState parentWindow, int appOp, int seq, WindowManager.LayoutParams a, int viewVisibility, int ownerId, boolean ownerCanAddInternalSystemWindow)717 WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token, 718 WindowState parentWindow, int appOp, int seq, WindowManager.LayoutParams a, 719 int viewVisibility, int ownerId, boolean ownerCanAddInternalSystemWindow) { 720 this(service, s, c, token, parentWindow, appOp, seq, a, viewVisibility, ownerId, 721 ownerCanAddInternalSystemWindow, new PowerManagerWrapper() { 722 @Override 723 public void wakeUp(long time, @WakeReason int reason, String details) { 724 service.mPowerManager.wakeUp(time, reason, details); 725 } 726 727 @Override 728 public boolean isInteractive() { 729 return service.mPowerManager.isInteractive(); 730 } 731 }); 732 } 733 WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token, WindowState parentWindow, int appOp, int seq, WindowManager.LayoutParams a, int viewVisibility, int ownerId, boolean ownerCanAddInternalSystemWindow, PowerManagerWrapper powerManagerWrapper)734 WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token, 735 WindowState parentWindow, int appOp, int seq, WindowManager.LayoutParams a, 736 int viewVisibility, int ownerId, boolean ownerCanAddInternalSystemWindow, 737 PowerManagerWrapper powerManagerWrapper) { 738 super(service); 739 mSession = s; 740 mClient = c; 741 mAppOp = appOp; 742 mToken = token; 743 mAppToken = mToken.asAppWindowToken(); 744 mOwnerUid = ownerId; 745 mOwnerCanAddInternalSystemWindow = ownerCanAddInternalSystemWindow; 746 mWindowId = new WindowId(this); 747 mAttrs.copyFrom(a); 748 mLastSurfaceInsets.set(mAttrs.surfaceInsets); 749 mViewVisibility = viewVisibility; 750 mPolicy = mWmService.mPolicy; 751 mContext = mWmService.mContext; 752 DeathRecipient deathRecipient = new DeathRecipient(); 753 mSeq = seq; 754 mPowerManagerWrapper = powerManagerWrapper; 755 mForceSeamlesslyRotate = token.mRoundedCornerOverlay; 756 if (localLOGV) Slog.v( 757 TAG, "Window " + this + " client=" + c.asBinder() 758 + " token=" + token + " (" + mAttrs.token + ")" + " params=" + a); 759 try { 760 c.asBinder().linkToDeath(deathRecipient, 0); 761 } catch (RemoteException e) { 762 mDeathRecipient = null; 763 mIsChildWindow = false; 764 mLayoutAttached = false; 765 mIsImWindow = false; 766 mIsWallpaper = false; 767 mIsFloatingLayer = false; 768 mBaseLayer = 0; 769 mSubLayer = 0; 770 mInputWindowHandle = null; 771 mWinAnimator = null; 772 return; 773 } 774 mDeathRecipient = deathRecipient; 775 776 if (mAttrs.type >= FIRST_SUB_WINDOW && mAttrs.type <= LAST_SUB_WINDOW) { 777 // The multiplier here is to reserve space for multiple 778 // windows in the same type layer. 779 mBaseLayer = mPolicy.getWindowLayerLw(parentWindow) 780 * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET; 781 mSubLayer = mPolicy.getSubWindowLayerFromTypeLw(a.type); 782 mIsChildWindow = true; 783 784 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + this + " to " + parentWindow); 785 parentWindow.addChild(this, sWindowSubLayerComparator); 786 787 mLayoutAttached = mAttrs.type != 788 WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; 789 mIsImWindow = parentWindow.mAttrs.type == TYPE_INPUT_METHOD 790 || parentWindow.mAttrs.type == TYPE_INPUT_METHOD_DIALOG; 791 mIsWallpaper = parentWindow.mAttrs.type == TYPE_WALLPAPER; 792 } else { 793 // The multiplier here is to reserve space for multiple 794 // windows in the same type layer. 795 mBaseLayer = mPolicy.getWindowLayerLw(this) 796 * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET; 797 mSubLayer = 0; 798 mIsChildWindow = false; 799 mLayoutAttached = false; 800 mIsImWindow = mAttrs.type == TYPE_INPUT_METHOD 801 || mAttrs.type == TYPE_INPUT_METHOD_DIALOG; 802 mIsWallpaper = mAttrs.type == TYPE_WALLPAPER; 803 } 804 mIsFloatingLayer = mIsImWindow || mIsWallpaper; 805 806 if (mAppToken != null && mAppToken.mShowForAllUsers) { 807 // Windows for apps that can show for all users should also show when the device is 808 // locked. 809 mAttrs.flags |= FLAG_SHOW_WHEN_LOCKED; 810 } 811 812 mWinAnimator = new WindowStateAnimator(this); 813 mWinAnimator.mAlpha = a.alpha; 814 815 mRequestedWidth = 0; 816 mRequestedHeight = 0; 817 mLastRequestedWidth = 0; 818 mLastRequestedHeight = 0; 819 mLayer = 0; 820 mInputWindowHandle = new InputWindowHandle( 821 mAppToken != null ? mAppToken.mInputApplicationHandle : null, c, 822 getDisplayId()); 823 } 824 attach()825 void attach() { 826 if (localLOGV) Slog.v(TAG, "Attaching " + this + " token=" + mToken); 827 mSession.windowAddedLocked(mAttrs.packageName); 828 } 829 830 /** 831 * @return {@code true} if the application runs in size compatibility mode. 832 * @see android.content.res.CompatibilityInfo#supportsScreen 833 * @see ActivityRecord#inSizeCompatMode 834 */ inSizeCompatMode()835 boolean inSizeCompatMode() { 836 return (mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0 837 || (mAppToken != null && mAppToken.inSizeCompatMode() 838 // Exclude starting window because it is not displayed by the application. 839 && mAttrs.type != TYPE_APPLICATION_STARTING); 840 } 841 842 /** 843 * Returns whether this {@link WindowState} has been considered for drawing by its parent. 844 */ getDrawnStateEvaluated()845 boolean getDrawnStateEvaluated() { 846 return mDrawnStateEvaluated; 847 } 848 849 /** 850 * Sets whether this {@link WindowState} has been considered for drawing by its parent. Should 851 * be cleared when detached from parent. 852 */ setDrawnStateEvaluated(boolean evaluated)853 void setDrawnStateEvaluated(boolean evaluated) { 854 mDrawnStateEvaluated = evaluated; 855 } 856 857 @Override onParentChanged()858 void onParentChanged() { 859 super.onParentChanged(); 860 setDrawnStateEvaluated(false /*evaluated*/); 861 862 getDisplayContent().reapplyMagnificationSpec(); 863 } 864 865 @Override getOwningUid()866 public int getOwningUid() { 867 return mOwnerUid; 868 } 869 870 @Override getOwningPackage()871 public String getOwningPackage() { 872 return mAttrs.packageName; 873 } 874 875 @Override canAddInternalSystemWindow()876 public boolean canAddInternalSystemWindow() { 877 return mOwnerCanAddInternalSystemWindow; 878 } 879 880 @Override canAcquireSleepToken()881 public boolean canAcquireSleepToken() { 882 return mSession.mCanAcquireSleepToken; 883 } 884 885 /** 886 * Subtracts the insets calculated by intersecting {@param layoutFrame} with {@param insetFrame} 887 * from {@param frame}. In other words, it applies the insets that would result if 888 * {@param frame} would be shifted to {@param layoutFrame} and then applying the insets from 889 * {@param insetFrame}. Also it respects {@param displayFrame} in case window has minimum 890 * width/height applied and insets should be overridden. 891 */ subtractInsets(Rect frame, Rect layoutFrame, Rect insetFrame, Rect displayFrame)892 private void subtractInsets(Rect frame, Rect layoutFrame, Rect insetFrame, Rect displayFrame) { 893 final int left = Math.max(0, insetFrame.left - Math.max(layoutFrame.left, displayFrame.left)); 894 final int top = Math.max(0, insetFrame.top - Math.max(layoutFrame.top, displayFrame.top)); 895 final int right = Math.max(0, Math.min(layoutFrame.right, displayFrame.right) - insetFrame.right); 896 final int bottom = Math.max(0, Math.min(layoutFrame.bottom, displayFrame.bottom) - insetFrame.bottom); 897 frame.inset(left, top, right, bottom); 898 } 899 900 @Override getDisplayedBounds()901 public Rect getDisplayedBounds() { 902 final Task task = getTask(); 903 if (task != null) { 904 Rect bounds = task.getOverrideDisplayedBounds(); 905 if (!bounds.isEmpty()) { 906 return bounds; 907 } 908 } 909 return super.getDisplayedBounds(); 910 } 911 912 @Override computeFrameLw()913 public void computeFrameLw() { 914 if (mWillReplaceWindow && (mAnimatingExit || !mReplacingRemoveRequested)) { 915 // This window is being replaced and either already got information that it's being 916 // removed or we are still waiting for some information. Because of this we don't 917 // want to apply any more changes to it, so it remains in this state until new window 918 // appears. 919 return; 920 } 921 mHaveFrame = true; 922 923 final Task task = getTask(); 924 final boolean isFullscreenAndFillsDisplay = !inMultiWindowMode() && matchesDisplayBounds(); 925 final boolean windowsAreFloating = task != null && task.isFloating(); 926 final DisplayContent dc = getDisplayContent(); 927 928 mInsetFrame.set(getBounds()); 929 930 // Denotes the actual frame used to calculate the insets and to perform the layout. When 931 // resizing in docked mode, we'd like to freeze the layout, so we also need to freeze the 932 // insets temporarily. By the notion of a task having a different layout frame, we can 933 // achieve that while still moving the task around. 934 final Rect layoutContainingFrame; 935 final Rect layoutDisplayFrame; 936 937 // The offset from the layout containing frame to the actual containing frame. 938 final int layoutXDiff; 939 final int layoutYDiff; 940 final WindowState imeWin = mWmService.mRoot.getCurrentInputMethodWindow(); 941 final boolean isImeTarget = 942 imeWin != null && imeWin.isVisibleNow() && isInputMethodTarget(); 943 if (isFullscreenAndFillsDisplay || layoutInParentFrame()) { 944 // We use the parent frame as the containing frame for fullscreen and child windows 945 mWindowFrames.mContainingFrame.set(mWindowFrames.mParentFrame); 946 layoutDisplayFrame = mWindowFrames.mDisplayFrame; 947 layoutContainingFrame = mWindowFrames.mParentFrame; 948 layoutXDiff = 0; 949 layoutYDiff = 0; 950 } else { 951 mWindowFrames.mContainingFrame.set(getDisplayedBounds()); 952 if (mAppToken != null && !mAppToken.mFrozenBounds.isEmpty()) { 953 954 // If the bounds are frozen, we still want to translate the window freely and only 955 // freeze the size. 956 Rect frozen = mAppToken.mFrozenBounds.peek(); 957 mWindowFrames.mContainingFrame.right = 958 mWindowFrames.mContainingFrame.left + frozen.width(); 959 mWindowFrames.mContainingFrame.bottom = 960 mWindowFrames.mContainingFrame.top + frozen.height(); 961 } 962 // IME is up and obscuring this window. Adjust the window position so it is visible. 963 if (isImeTarget) { 964 if (inFreeformWindowingMode()) { 965 // Push the freeform window up to make room for the IME. However, don't push 966 // it up past the top of the screen. 967 final int bottomOverlap = mWindowFrames.mContainingFrame.bottom 968 - mWindowFrames.mVisibleFrame.bottom; 969 if (bottomOverlap > 0) { 970 final int distanceToTop = Math.max(mWindowFrames.mContainingFrame.top 971 - mWindowFrames.mDisplayFrame.top, 0); 972 int offs = Math.min(bottomOverlap, distanceToTop); 973 mWindowFrames.mContainingFrame.top -= offs; 974 } 975 } else if (!inPinnedWindowingMode() && mWindowFrames.mContainingFrame.bottom 976 > mWindowFrames.mParentFrame.bottom) { 977 // But in docked we want to behave like fullscreen and behave as if the task 978 // were given smaller bounds for the purposes of layout. Skip adjustments for 979 // the pinned stack, they are handled separately in the PinnedStackController. 980 mWindowFrames.mContainingFrame.bottom = mWindowFrames.mParentFrame.bottom; 981 } 982 } 983 984 if (windowsAreFloating) { 985 // In floating modes (e.g. freeform, pinned) we have only to set the rectangle 986 // if it wasn't set already. No need to intersect it with the (visible) 987 // "content frame" since it is allowed to be outside the visible desktop. 988 if (mWindowFrames.mContainingFrame.isEmpty()) { 989 mWindowFrames.mContainingFrame.set(mWindowFrames.mContentFrame); 990 } 991 } 992 993 final TaskStack stack = getStack(); 994 if (inPinnedWindowingMode() && stack != null 995 && stack.lastAnimatingBoundsWasToFullscreen()) { 996 // PIP edge case: When going from pinned to fullscreen, we apply a 997 // tempInsetFrame for the full task - but we're still at the start of the animation. 998 // To prevent a jump if there's a letterbox, restrict to the parent frame. 999 mInsetFrame.intersectUnchecked(mWindowFrames.mParentFrame); 1000 mWindowFrames.mContainingFrame.intersectUnchecked(mWindowFrames.mParentFrame); 1001 } 1002 1003 layoutDisplayFrame = new Rect(mWindowFrames.mDisplayFrame); 1004 mWindowFrames.mDisplayFrame.set(mWindowFrames.mContainingFrame); 1005 layoutXDiff = mInsetFrame.left - mWindowFrames.mContainingFrame.left; 1006 layoutYDiff = mInsetFrame.top - mWindowFrames.mContainingFrame.top; 1007 layoutContainingFrame = mInsetFrame; 1008 mTmpRect.set(0, 0, dc.getDisplayInfo().logicalWidth, dc.getDisplayInfo().logicalHeight); 1009 subtractInsets(mWindowFrames.mDisplayFrame, layoutContainingFrame, layoutDisplayFrame, 1010 mTmpRect); 1011 if (!layoutInParentFrame()) { 1012 subtractInsets(mWindowFrames.mContainingFrame, layoutContainingFrame, 1013 mWindowFrames.mParentFrame, mTmpRect); 1014 subtractInsets(mInsetFrame, layoutContainingFrame, mWindowFrames.mParentFrame, 1015 mTmpRect); 1016 } 1017 layoutDisplayFrame.intersect(layoutContainingFrame); 1018 } 1019 1020 final int pw = mWindowFrames.mContainingFrame.width(); 1021 final int ph = mWindowFrames.mContainingFrame.height(); 1022 1023 if (mRequestedWidth != mLastRequestedWidth || mRequestedHeight != mLastRequestedHeight) { 1024 mLastRequestedWidth = mRequestedWidth; 1025 mLastRequestedHeight = mRequestedHeight; 1026 mWindowFrames.setContentChanged(true); 1027 } 1028 1029 final int fw = mWindowFrames.mFrame.width(); 1030 final int fh = mWindowFrames.mFrame.height(); 1031 1032 applyGravityAndUpdateFrame(layoutContainingFrame, layoutDisplayFrame); 1033 1034 // Calculate the outsets before the content frame gets shrinked to the window frame. 1035 mWindowFrames.calculateOutsets(); 1036 1037 // Make sure the content and visible frames are inside of the 1038 // final window frame. 1039 if (windowsAreFloating && !mWindowFrames.mFrame.isEmpty()) { 1040 final int visBottom = mWindowFrames.mVisibleFrame.bottom; 1041 final int contentBottom = mWindowFrames.mContentFrame.bottom; 1042 mWindowFrames.mContentFrame.set(mWindowFrames.mFrame); 1043 mWindowFrames.mVisibleFrame.set(mWindowFrames.mContentFrame); 1044 mWindowFrames.mStableFrame.set(mWindowFrames.mContentFrame); 1045 if (isImeTarget && inFreeformWindowingMode()) { 1046 // After displacing a freeform window to make room for the ime, any part of 1047 // the window still covered by IME should be inset. 1048 if (contentBottom + layoutYDiff < mWindowFrames.mContentFrame.bottom) { 1049 mWindowFrames.mContentFrame.bottom = contentBottom + layoutYDiff; 1050 } 1051 if (visBottom + layoutYDiff < mWindowFrames.mVisibleFrame.bottom) { 1052 mWindowFrames.mVisibleFrame.bottom = visBottom + layoutYDiff; 1053 } 1054 } 1055 } else if (mAttrs.type == TYPE_DOCK_DIVIDER) { 1056 dc.getDockedDividerController().positionDockedStackedDivider(mWindowFrames.mFrame); 1057 mWindowFrames.mContentFrame.set(mWindowFrames.mFrame); 1058 if (!mWindowFrames.mFrame.equals(mWindowFrames.mLastFrame)) { 1059 mMovedByResize = true; 1060 } 1061 } else { 1062 mWindowFrames.mContentFrame.set( 1063 Math.max(mWindowFrames.mContentFrame.left, mWindowFrames.mFrame.left), 1064 Math.max(mWindowFrames.mContentFrame.top, mWindowFrames.mFrame.top), 1065 Math.min(mWindowFrames.mContentFrame.right, mWindowFrames.mFrame.right), 1066 Math.min(mWindowFrames.mContentFrame.bottom, mWindowFrames.mFrame.bottom)); 1067 1068 mWindowFrames.mVisibleFrame.set( 1069 Math.max(mWindowFrames.mVisibleFrame.left, mWindowFrames.mFrame.left), 1070 Math.max(mWindowFrames.mVisibleFrame.top, mWindowFrames.mFrame.top), 1071 Math.min(mWindowFrames.mVisibleFrame.right, mWindowFrames.mFrame.right), 1072 Math.min(mWindowFrames.mVisibleFrame.bottom, mWindowFrames.mFrame.bottom)); 1073 1074 mWindowFrames.mStableFrame.set( 1075 Math.max(mWindowFrames.mStableFrame.left, mWindowFrames.mFrame.left), 1076 Math.max(mWindowFrames.mStableFrame.top, mWindowFrames.mFrame.top), 1077 Math.min(mWindowFrames.mStableFrame.right, mWindowFrames.mFrame.right), 1078 Math.min(mWindowFrames.mStableFrame.bottom, mWindowFrames.mFrame.bottom)); 1079 } 1080 1081 if (isFullscreenAndFillsDisplay && !windowsAreFloating) { 1082 // Windows that are not fullscreen can be positioned outside of the display frame, 1083 // but that is not a reason to provide them with overscan insets. 1084 InsetUtils.insetsBetweenFrames(layoutContainingFrame, mWindowFrames.mOverscanFrame, 1085 mWindowFrames.mOverscanInsets); 1086 } 1087 1088 if (mAttrs.type == TYPE_DOCK_DIVIDER) { 1089 final WmDisplayCutout c = mWindowFrames.mDisplayCutout.calculateRelativeTo( 1090 mWindowFrames.mDisplayFrame); 1091 mWindowFrames.calculateDockedDividerInsets(c.getDisplayCutout().getSafeInsets()); 1092 } else { 1093 getDisplayContent().getBounds(mTmpRect); 1094 mWindowFrames.calculateInsets( 1095 windowsAreFloating, isFullscreenAndFillsDisplay, mTmpRect); 1096 } 1097 1098 mWindowFrames.setDisplayCutout( 1099 mWindowFrames.mDisplayCutout.calculateRelativeTo(mWindowFrames.mFrame)); 1100 1101 // Offset the actual frame by the amount layout frame is off. 1102 mWindowFrames.offsetFrames(-layoutXDiff, -layoutYDiff); 1103 1104 mWindowFrames.mCompatFrame.set(mWindowFrames.mFrame); 1105 if (inSizeCompatMode()) { 1106 // If there is a size compatibility scale being applied to the 1107 // window, we need to apply this to its insets so that they are 1108 // reported to the app in its coordinate space. 1109 mWindowFrames.scaleInsets(mInvGlobalScale); 1110 1111 // Also the scaled frame that we report to the app needs to be 1112 // adjusted to be in its coordinate space. 1113 mWindowFrames.mCompatFrame.scale(mInvGlobalScale); 1114 } 1115 1116 if (mIsWallpaper && (fw != mWindowFrames.mFrame.width() 1117 || fh != mWindowFrames.mFrame.height())) { 1118 final DisplayContent displayContent = getDisplayContent(); 1119 if (displayContent != null) { 1120 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 1121 getDisplayContent().mWallpaperController.updateWallpaperOffset(this, 1122 displayInfo.logicalWidth, displayInfo.logicalHeight, false); 1123 } 1124 } 1125 1126 if (DEBUG_LAYOUT || localLOGV) Slog.v(TAG, 1127 "Resolving (mRequestedWidth=" 1128 + mRequestedWidth + ", mRequestedheight=" 1129 + mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph 1130 + "): frame=" + mWindowFrames.mFrame.toShortString() 1131 + " " + mWindowFrames.getInsetsInfo() 1132 + " " + mAttrs.getTitle()); 1133 } 1134 1135 // TODO: Look into whether this override is still necessary. 1136 @Override getBounds()1137 public Rect getBounds() { 1138 if (mAppToken != null) { 1139 return mAppToken.getBounds(); 1140 } else { 1141 return super.getBounds(); 1142 } 1143 } 1144 1145 @Override getFrameLw()1146 public Rect getFrameLw() { 1147 return mWindowFrames.mFrame; 1148 } 1149 1150 @Override getDisplayFrameLw()1151 public Rect getDisplayFrameLw() { 1152 return mWindowFrames.mDisplayFrame; 1153 } 1154 1155 @Override getOverscanFrameLw()1156 public Rect getOverscanFrameLw() { 1157 return mWindowFrames.mOverscanFrame; 1158 } 1159 1160 @Override getContentFrameLw()1161 public Rect getContentFrameLw() { 1162 return mWindowFrames.mContentFrame; 1163 } 1164 1165 @Override getVisibleFrameLw()1166 public Rect getVisibleFrameLw() { 1167 return mWindowFrames.mVisibleFrame; 1168 } 1169 getStableFrameLw()1170 Rect getStableFrameLw() { 1171 return mWindowFrames.mStableFrame; 1172 } 1173 getDecorFrame()1174 Rect getDecorFrame() { 1175 return mWindowFrames.mDecorFrame; 1176 } 1177 getParentFrame()1178 Rect getParentFrame() { 1179 return mWindowFrames.mParentFrame; 1180 } 1181 getContainingFrame()1182 Rect getContainingFrame() { 1183 return mWindowFrames.mContainingFrame; 1184 } 1185 getWmDisplayCutout()1186 WmDisplayCutout getWmDisplayCutout() { 1187 return mWindowFrames.mDisplayCutout; 1188 } 1189 getCompatFrame(Rect outFrame)1190 void getCompatFrame(Rect outFrame) { 1191 outFrame.set(mWindowFrames.mCompatFrame); 1192 } 1193 getCompatFrameSize(Rect outFrame)1194 void getCompatFrameSize(Rect outFrame) { 1195 outFrame.set(0, 0, mWindowFrames.mCompatFrame.width(), mWindowFrames.mCompatFrame.height()); 1196 } 1197 1198 @Override getGivenInsetsPendingLw()1199 public boolean getGivenInsetsPendingLw() { 1200 return mGivenInsetsPending; 1201 } 1202 1203 @Override getGivenContentInsetsLw()1204 public Rect getGivenContentInsetsLw() { 1205 return mGivenContentInsets; 1206 } 1207 1208 @Override getGivenVisibleInsetsLw()1209 public Rect getGivenVisibleInsetsLw() { 1210 return mGivenVisibleInsets; 1211 } 1212 1213 @Override getAttrs()1214 public WindowManager.LayoutParams getAttrs() { 1215 return mAttrs; 1216 } 1217 1218 @Override getNeedsMenuLw(WindowManagerPolicy.WindowState bottom)1219 public boolean getNeedsMenuLw(WindowManagerPolicy.WindowState bottom) { 1220 return getDisplayContent().getNeedsMenu(this, bottom); 1221 } 1222 1223 @Override getSystemUiVisibility()1224 public int getSystemUiVisibility() { 1225 return mSystemUiVisibility; 1226 } 1227 1228 @Override getSurfaceLayer()1229 public int getSurfaceLayer() { 1230 return mLayer; 1231 } 1232 1233 @Override getBaseType()1234 public int getBaseType() { 1235 return getTopParentWindow().mAttrs.type; 1236 } 1237 1238 @Override getAppToken()1239 public IApplicationToken getAppToken() { 1240 return mAppToken != null ? mAppToken.appToken : null; 1241 } 1242 1243 @Override isVoiceInteraction()1244 public boolean isVoiceInteraction() { 1245 return mAppToken != null && mAppToken.mVoiceInteraction; 1246 } 1247 setReportResizeHints()1248 boolean setReportResizeHints() { 1249 return mWindowFrames.setReportResizeHints(); 1250 } 1251 1252 /** 1253 * Adds the window to the resizing list if any of the parameters we use to track the window 1254 * dimensions or insets have changed. 1255 */ updateResizingWindowIfNeeded()1256 void updateResizingWindowIfNeeded() { 1257 final WindowStateAnimator winAnimator = mWinAnimator; 1258 if (!mHasSurface || getDisplayContent().mLayoutSeq != mLayoutSeq || isGoneForLayoutLw()) { 1259 return; 1260 } 1261 1262 final Task task = getTask(); 1263 // In the case of stack bound animations, the window frames will update (unlike other 1264 // animations which just modify various transformation properties). We don't want to 1265 // notify the client of frame changes in this case. Not only is it a lot of churn, but 1266 // the frame may not correspond to the surface size or the onscreen area at various 1267 // phases in the animation, and the client will become sad and confused. 1268 if (task != null && task.mStack.isAnimatingBounds()) { 1269 return; 1270 } 1271 1272 boolean didFrameInsetsChange = setReportResizeHints(); 1273 boolean configChanged = !isLastConfigReportedToClient(); 1274 if (DEBUG_CONFIGURATION && configChanged) { 1275 Slog.v(TAG_WM, "Win " + this + " config changed: " + getConfiguration()); 1276 } 1277 1278 final boolean dragResizingChanged = isDragResizeChanged() 1279 && !isDragResizingChangeReported(); 1280 1281 if (localLOGV) Slog.v(TAG_WM, "Resizing " + this + ": configChanged=" + configChanged 1282 + " dragResizingChanged=" + dragResizingChanged 1283 + " last=" + mWindowFrames.mLastFrame + " frame=" + mWindowFrames.mFrame); 1284 1285 // We update mLastFrame always rather than in the conditional with the last inset 1286 // variables, because mFrameSizeChanged only tracks the width and height changing. 1287 mWindowFrames.mLastFrame.set(mWindowFrames.mFrame); 1288 1289 if (didFrameInsetsChange 1290 || winAnimator.mSurfaceResized 1291 || configChanged 1292 || dragResizingChanged 1293 || mReportOrientationChanged) { 1294 if (DEBUG_RESIZE || DEBUG_ORIENTATION) { 1295 Slog.v(TAG_WM, "Resize reasons for w=" + this + ": " 1296 + " " + mWindowFrames.getInsetsChangedInfo() 1297 + " surfaceResized=" + winAnimator.mSurfaceResized 1298 + " configChanged=" + configChanged 1299 + " dragResizingChanged=" + dragResizingChanged 1300 + " reportOrientationChanged=" + mReportOrientationChanged); 1301 } 1302 1303 // If it's a dead window left on screen, and the configuration changed, there is nothing 1304 // we can do about it. Remove the window now. 1305 if (mAppToken != null && mAppDied) { 1306 mAppToken.removeDeadWindows(); 1307 return; 1308 } 1309 1310 updateLastInsetValues(); 1311 mWmService.makeWindowFreezingScreenIfNeededLocked(this); 1312 1313 // If the orientation is changing, or we're starting or ending a drag resizing action, 1314 // then we need to hold off on unfreezing the display until this window has been 1315 // redrawn; to do that, we need to go through the process of getting informed by the 1316 // application when it has finished drawing. 1317 if (getOrientationChanging() || dragResizingChanged) { 1318 if (DEBUG_ANIM || DEBUG_ORIENTATION || DEBUG_RESIZE) { 1319 Slog.v(TAG_WM, "Orientation or resize start waiting for draw" 1320 + ", mDrawState=DRAW_PENDING in " + this 1321 + ", surfaceController " + winAnimator.mSurfaceController); 1322 } 1323 winAnimator.mDrawState = DRAW_PENDING; 1324 if (mAppToken != null) { 1325 mAppToken.clearAllDrawn(); 1326 } 1327 } 1328 if (!mWmService.mResizingWindows.contains(this)) { 1329 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG_WM, "Resizing window " + this); 1330 mWmService.mResizingWindows.add(this); 1331 } 1332 } else if (getOrientationChanging()) { 1333 if (isDrawnLw()) { 1334 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Orientation not waiting for draw in " 1335 + this + ", surfaceController " + winAnimator.mSurfaceController); 1336 setOrientationChanging(false); 1337 mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 1338 - mWmService.mDisplayFreezeTime); 1339 } 1340 } 1341 } 1342 getOrientationChanging()1343 boolean getOrientationChanging() { 1344 // In addition to the local state flag, we must also consider the difference in the last 1345 // reported configuration vs. the current state. If the client code has not been informed of 1346 // the change, logic dependent on having finished processing the orientation, such as 1347 // unfreezing, could be improperly triggered. 1348 // TODO(b/62846907): Checking against {@link mLastReportedConfiguration} could be flaky as 1349 // this is not necessarily what the client has processed yet. Find a 1350 // better indicator consistent with the client. 1351 return (mOrientationChanging || (isVisible() 1352 && getConfiguration().orientation != getLastReportedConfiguration().orientation)) 1353 && !mSeamlesslyRotated 1354 && !mOrientationChangeTimedOut; 1355 } 1356 setOrientationChanging(boolean changing)1357 void setOrientationChanging(boolean changing) { 1358 mOrientationChanging = changing; 1359 mOrientationChangeTimedOut = false; 1360 } 1361 orientationChangeTimedOut()1362 void orientationChangeTimedOut() { 1363 mOrientationChangeTimedOut = true; 1364 } 1365 1366 @Override getDisplayContent()1367 DisplayContent getDisplayContent() { 1368 return mToken.getDisplayContent(); 1369 } 1370 1371 @Override onDisplayChanged(DisplayContent dc)1372 void onDisplayChanged(DisplayContent dc) { 1373 super.onDisplayChanged(dc); 1374 // Window was not laid out for this display yet, so make sure mLayoutSeq does not match. 1375 if (dc != null && mInputWindowHandle.displayId != dc.getDisplayId()) { 1376 mLayoutSeq = dc.mLayoutSeq - 1; 1377 mInputWindowHandle.displayId = dc.getDisplayId(); 1378 } 1379 } 1380 getDisplayInfo()1381 DisplayInfo getDisplayInfo() { 1382 final DisplayContent displayContent = getDisplayContent(); 1383 return displayContent != null ? displayContent.getDisplayInfo() : null; 1384 } 1385 1386 @Override getDisplayId()1387 public int getDisplayId() { 1388 final DisplayContent displayContent = getDisplayContent(); 1389 if (displayContent == null) { 1390 return Display.INVALID_DISPLAY; 1391 } 1392 return displayContent.getDisplayId(); 1393 } 1394 getTask()1395 Task getTask() { 1396 return mAppToken != null ? mAppToken.getTask() : null; 1397 } 1398 getStack()1399 TaskStack getStack() { 1400 Task task = getTask(); 1401 if (task != null) { 1402 if (task.mStack != null) { 1403 return task.mStack; 1404 } 1405 } 1406 // Some system windows (e.g. "Power off" dialog) don't have a task, but we would still 1407 // associate them with some stack to enable dimming. 1408 final DisplayContent dc = getDisplayContent(); 1409 return mAttrs.type >= FIRST_SYSTEM_WINDOW && dc != null ? dc.getHomeStack() : null; 1410 } 1411 1412 /** 1413 * Retrieves the visible bounds of the window. 1414 * @param bounds The rect which gets the bounds. 1415 */ getVisibleBounds(Rect bounds)1416 void getVisibleBounds(Rect bounds) { 1417 final Task task = getTask(); 1418 boolean intersectWithStackBounds = task != null && task.cropWindowsToStackBounds(); 1419 bounds.setEmpty(); 1420 mTmpRect.setEmpty(); 1421 if (intersectWithStackBounds) { 1422 final TaskStack stack = task.mStack; 1423 if (stack != null) { 1424 stack.getDimBounds(mTmpRect); 1425 } else { 1426 intersectWithStackBounds = false; 1427 } 1428 } 1429 1430 bounds.set(mWindowFrames.mVisibleFrame); 1431 if (intersectWithStackBounds) { 1432 bounds.intersect(mTmpRect); 1433 } 1434 1435 if (bounds.isEmpty()) { 1436 bounds.set(mWindowFrames.mFrame); 1437 if (intersectWithStackBounds) { 1438 bounds.intersect(mTmpRect); 1439 } 1440 return; 1441 } 1442 } 1443 getInputDispatchingTimeoutNanos()1444 public long getInputDispatchingTimeoutNanos() { 1445 return mAppToken != null 1446 ? mAppToken.mInputDispatchingTimeoutNanos 1447 : WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; 1448 } 1449 1450 @Override hasAppShownWindows()1451 public boolean hasAppShownWindows() { 1452 return mAppToken != null && (mAppToken.firstWindowDrawn || mAppToken.startingDisplayed); 1453 } 1454 isIdentityMatrix(float dsdx, float dtdx, float dsdy, float dtdy)1455 boolean isIdentityMatrix(float dsdx, float dtdx, float dsdy, float dtdy) { 1456 if (dsdx < .99999f || dsdx > 1.00001f) return false; 1457 if (dtdy < .99999f || dtdy > 1.00001f) return false; 1458 if (dtdx < -.000001f || dtdx > .000001f) return false; 1459 if (dsdy < -.000001f || dsdy > .000001f) return false; 1460 return true; 1461 } 1462 prelayout()1463 void prelayout() { 1464 if (inSizeCompatMode()) { 1465 mGlobalScale = mToken.getSizeCompatScale(); 1466 mInvGlobalScale = 1 / mGlobalScale; 1467 } else { 1468 mGlobalScale = mInvGlobalScale = 1; 1469 } 1470 } 1471 1472 @Override hasContentToDisplay()1473 boolean hasContentToDisplay() { 1474 if (!mAppFreezing && isDrawnLw() && (mViewVisibility == View.VISIBLE 1475 || (isAnimating() && !getDisplayContent().mAppTransition.isTransitionSet()))) { 1476 return true; 1477 } 1478 1479 return super.hasContentToDisplay(); 1480 } 1481 1482 @Override isVisible()1483 boolean isVisible() { 1484 return wouldBeVisibleIfPolicyIgnored() && isVisibleByPolicy() 1485 // If we don't have a provider, this window isn't used as a window generating 1486 // insets, so nobody can hide it over the inset APIs. 1487 && (mInsetProvider == null || mInsetProvider.isClientVisible()); 1488 } 1489 1490 /** 1491 * Ensures that all the policy visibility bits are set. 1492 * @return {@code true} if all flags about visiblity are set 1493 */ isVisibleByPolicy()1494 boolean isVisibleByPolicy() { 1495 return (mPolicyVisibility & POLICY_VISIBILITY_ALL) == POLICY_VISIBILITY_ALL; 1496 } 1497 clearPolicyVisibilityFlag(int policyVisibilityFlag)1498 void clearPolicyVisibilityFlag(int policyVisibilityFlag) { 1499 mPolicyVisibility &= ~policyVisibilityFlag; 1500 mWmService.scheduleAnimationLocked(); 1501 } 1502 setPolicyVisibilityFlag(int policyVisibilityFlag)1503 void setPolicyVisibilityFlag(int policyVisibilityFlag) { 1504 mPolicyVisibility |= policyVisibilityFlag; 1505 mWmService.scheduleAnimationLocked(); 1506 } 1507 isLegacyPolicyVisibility()1508 private boolean isLegacyPolicyVisibility() { 1509 return (mPolicyVisibility & LEGACY_POLICY_VISIBILITY) != 0; 1510 } 1511 1512 /** 1513 * @return {@code true} if the window would be visible if we'd ignore policy visibility, 1514 * {@code false} otherwise. 1515 */ wouldBeVisibleIfPolicyIgnored()1516 boolean wouldBeVisibleIfPolicyIgnored() { 1517 return mHasSurface && !isParentWindowHidden() 1518 && !mAnimatingExit && !mDestroying && (!mIsWallpaper || mWallpaperVisible); 1519 } 1520 1521 @Override isVisibleLw()1522 public boolean isVisibleLw() { 1523 return isVisible(); 1524 } 1525 1526 /** 1527 * Is this window visible, ignoring its app token? It is not visible if there is no surface, 1528 * or we are in the process of running an exit animation that will remove the surface. 1529 */ 1530 // TODO: Can we consolidate this with #isVisible() or have a more appropriate name for this? isWinVisibleLw()1531 boolean isWinVisibleLw() { 1532 return (mAppToken == null || !mAppToken.hiddenRequested || mAppToken.isSelfAnimating()) 1533 && isVisible(); 1534 } 1535 1536 /** 1537 * The same as isVisible(), but follows the current hidden state of the associated app token, 1538 * not the pending requested hidden state. 1539 */ isVisibleNow()1540 boolean isVisibleNow() { 1541 return (!mToken.isHidden() || mAttrs.type == TYPE_APPLICATION_STARTING) 1542 && isVisible(); 1543 } 1544 1545 /** 1546 * Can this window possibly be a drag/drop target? The test here is 1547 * a combination of the above "visible now" with the check that the 1548 * Input Manager uses when discarding windows from input consideration. 1549 */ isPotentialDragTarget()1550 boolean isPotentialDragTarget() { 1551 return isVisibleNow() && !mRemoved 1552 && mInputChannel != null && mInputWindowHandle != null; 1553 } 1554 1555 /** 1556 * Same as isVisible(), but we also count it as visible between the 1557 * call to IWindowSession.add() and the first relayout(). 1558 */ isVisibleOrAdding()1559 boolean isVisibleOrAdding() { 1560 final AppWindowToken atoken = mAppToken; 1561 return (mHasSurface || (!mRelayoutCalled && mViewVisibility == View.VISIBLE)) 1562 && isVisibleByPolicy() && !isParentWindowHidden() 1563 && (atoken == null || !atoken.hiddenRequested) 1564 && !mAnimatingExit && !mDestroying; 1565 } 1566 1567 /** 1568 * Is this window currently on-screen? It is on-screen either if it 1569 * is visible or it is currently running an animation before no longer 1570 * being visible. 1571 */ isOnScreen()1572 boolean isOnScreen() { 1573 if (!mHasSurface || mDestroying || !isVisibleByPolicy()) { 1574 return false; 1575 } 1576 final AppWindowToken atoken = mAppToken; 1577 if (atoken != null) { 1578 return ((!isParentWindowHidden() && !atoken.hiddenRequested) 1579 || isAnimating()); 1580 } 1581 return !isParentWindowHidden() || isAnimating(); 1582 } 1583 1584 /** 1585 * Whether this window's drawn state might affect the drawn states of the app token. 1586 * 1587 * @return true if the window should be considered while evaluating allDrawn flags. 1588 */ mightAffectAllDrawn()1589 boolean mightAffectAllDrawn() { 1590 final boolean isAppType = mWinAnimator.mAttrType == TYPE_BASE_APPLICATION 1591 || mWinAnimator.mAttrType == TYPE_DRAWN_APPLICATION; 1592 return (isOnScreen() || isAppType) && !mAnimatingExit && !mDestroying; 1593 } 1594 1595 /** 1596 * Whether this window is "interesting" when evaluating allDrawn. If it's interesting, 1597 * it must be drawn before allDrawn can become true. 1598 */ isInteresting()1599 boolean isInteresting() { 1600 return mAppToken != null && !mAppDied 1601 && (!mAppToken.isFreezingScreen() || !mAppFreezing) 1602 && mViewVisibility == View.VISIBLE; 1603 } 1604 1605 /** 1606 * Like isOnScreen(), but we don't return true if the window is part 1607 * of a transition that has not yet been started. 1608 */ isReadyForDisplay()1609 boolean isReadyForDisplay() { 1610 if (mToken.waitingToShow && getDisplayContent().mAppTransition.isTransitionSet()) { 1611 return false; 1612 } 1613 final boolean parentAndClientVisible = !isParentWindowHidden() 1614 && mViewVisibility == View.VISIBLE && !mToken.isHidden(); 1615 return mHasSurface && isVisibleByPolicy() && !mDestroying 1616 && (parentAndClientVisible || isAnimating()); 1617 } 1618 1619 // TODO: Another visibility method that was added late in the release to minimize risk. 1620 @Override canAffectSystemUiFlags()1621 public boolean canAffectSystemUiFlags() { 1622 final boolean translucent = mAttrs.alpha == 0.0f; 1623 if (translucent) { 1624 return false; 1625 } 1626 if (mAppToken == null) { 1627 final boolean shown = mWinAnimator.getShown(); 1628 final boolean exiting = mAnimatingExit || mDestroying; 1629 return shown && !exiting; 1630 } else { 1631 final Task task = getTask(); 1632 final boolean canFromTask = task != null && task.canAffectSystemUiFlags(); 1633 return canFromTask && !mAppToken.isHidden(); 1634 } 1635 } 1636 1637 /** 1638 * Like isOnScreen, but returns false if the surface hasn't yet 1639 * been drawn. 1640 */ 1641 @Override isDisplayedLw()1642 public boolean isDisplayedLw() { 1643 final AppWindowToken atoken = mAppToken; 1644 return isDrawnLw() && isVisibleByPolicy() 1645 && ((!isParentWindowHidden() && (atoken == null || !atoken.hiddenRequested)) 1646 || isAnimating()); 1647 } 1648 1649 /** 1650 * Return true if this window or its app token is currently animating. 1651 */ 1652 @Override isAnimatingLw()1653 public boolean isAnimatingLw() { 1654 return isAnimating(); 1655 } 1656 1657 @Override isGoneForLayoutLw()1658 public boolean isGoneForLayoutLw() { 1659 final AppWindowToken atoken = mAppToken; 1660 return mViewVisibility == View.GONE 1661 || !mRelayoutCalled 1662 || (atoken == null && mToken.isHidden()) 1663 || (atoken != null && atoken.hiddenRequested) 1664 || isParentWindowGoneForLayout() 1665 || (mAnimatingExit && !isAnimatingLw()) 1666 || mDestroying; 1667 } 1668 1669 /** 1670 * Returns true if the window has a surface that it has drawn a 1671 * complete UI in to. 1672 */ isDrawFinishedLw()1673 public boolean isDrawFinishedLw() { 1674 return mHasSurface && !mDestroying && 1675 (mWinAnimator.mDrawState == COMMIT_DRAW_PENDING 1676 || mWinAnimator.mDrawState == READY_TO_SHOW 1677 || mWinAnimator.mDrawState == HAS_DRAWN); 1678 } 1679 1680 /** 1681 * Returns true if the window has a surface that it has drawn a 1682 * complete UI in to. 1683 */ 1684 @Override isDrawnLw()1685 public boolean isDrawnLw() { 1686 return mHasSurface && !mDestroying && 1687 (mWinAnimator.mDrawState == READY_TO_SHOW || mWinAnimator.mDrawState == HAS_DRAWN); 1688 } 1689 1690 /** 1691 * Return true if the window is opaque and fully drawn. This indicates 1692 * it may obscure windows behind it. 1693 */ isOpaqueDrawn()1694 private boolean isOpaqueDrawn() { 1695 // When there is keyguard, wallpaper could be placed over the secure app 1696 // window but invisible. We need to check wallpaper visibility explicitly 1697 // to determine if it's occluding apps. 1698 return ((!mIsWallpaper && mAttrs.format == PixelFormat.OPAQUE) 1699 || (mIsWallpaper && mWallpaperVisible)) 1700 && isDrawnLw() && !isAnimating(); 1701 } 1702 1703 @Override onMovedByResize()1704 void onMovedByResize() { 1705 if (DEBUG_RESIZE) Slog.d(TAG, "onMovedByResize: Moving " + this); 1706 mMovedByResize = true; 1707 super.onMovedByResize(); 1708 } 1709 onAppVisibilityChanged(boolean visible, boolean runningAppAnimation)1710 boolean onAppVisibilityChanged(boolean visible, boolean runningAppAnimation) { 1711 boolean changed = false; 1712 1713 for (int i = mChildren.size() - 1; i >= 0; --i) { 1714 final WindowState c = mChildren.get(i); 1715 changed |= c.onAppVisibilityChanged(visible, runningAppAnimation); 1716 } 1717 1718 if (mAttrs.type == TYPE_APPLICATION_STARTING) { 1719 // Starting window that's exiting will be removed when the animation finishes. 1720 // Mark all relevant flags for that onExitAnimationDone will proceed all the way 1721 // to actually remove it. 1722 if (!visible && isVisibleNow() && mAppToken.isSelfAnimating()) { 1723 mAnimatingExit = true; 1724 mRemoveOnExit = true; 1725 mWindowRemovalAllowed = true; 1726 } 1727 return changed; 1728 } 1729 1730 final boolean isVisibleNow = isVisibleNow(); 1731 if (visible != isVisibleNow) { 1732 // Run exit animation if: 1733 // 1. App visibility and WS visibility are different 1734 // 2. App is not running an animation 1735 // 3. WS is currently visible 1736 if (!runningAppAnimation && isVisibleNow) { 1737 final AccessibilityController accessibilityController = 1738 mWmService.mAccessibilityController; 1739 final int winTransit = TRANSIT_EXIT; 1740 mWinAnimator.applyAnimationLocked(winTransit, false /* isEntrance */); 1741 if (accessibilityController != null) { 1742 accessibilityController.onWindowTransitionLocked(this, winTransit); 1743 } 1744 } 1745 changed = true; 1746 setDisplayLayoutNeeded(); 1747 } 1748 1749 return changed; 1750 } 1751 onSetAppExiting()1752 boolean onSetAppExiting() { 1753 final DisplayContent displayContent = getDisplayContent(); 1754 boolean changed = false; 1755 1756 if (isVisibleNow()) { 1757 mWinAnimator.applyAnimationLocked(TRANSIT_EXIT, false); 1758 if (mWmService.mAccessibilityController != null) { 1759 mWmService.mAccessibilityController.onWindowTransitionLocked(this, TRANSIT_EXIT); 1760 } 1761 changed = true; 1762 if (displayContent != null) { 1763 displayContent.setLayoutNeeded(); 1764 } 1765 } 1766 1767 for (int i = mChildren.size() - 1; i >= 0; --i) { 1768 final WindowState c = mChildren.get(i); 1769 changed |= c.onSetAppExiting(); 1770 } 1771 1772 return changed; 1773 } 1774 1775 @Override onResize()1776 void onResize() { 1777 final ArrayList<WindowState> resizingWindows = mWmService.mResizingWindows; 1778 if (mHasSurface && !isGoneForLayoutLw() && !resizingWindows.contains(this)) { 1779 if (DEBUG_RESIZE) Slog.d(TAG, "onResize: Resizing " + this); 1780 resizingWindows.add(this); 1781 } 1782 if (isGoneForLayoutLw()) { 1783 mResizedWhileGone = true; 1784 } 1785 1786 super.onResize(); 1787 } 1788 onUnfreezeBounds()1789 void onUnfreezeBounds() { 1790 for (int i = mChildren.size() - 1; i >= 0; --i) { 1791 final WindowState c = mChildren.get(i); 1792 c.onUnfreezeBounds(); 1793 } 1794 1795 if (!mHasSurface) { 1796 return; 1797 } 1798 1799 mLayoutNeeded = true; 1800 setDisplayLayoutNeeded(); 1801 if (!mWmService.mResizingWindows.contains(this)) { 1802 mWmService.mResizingWindows.add(this); 1803 } 1804 } 1805 1806 /** 1807 * If the window has moved due to its containing content frame changing, then notify the 1808 * listeners and optionally animate it. Simply checking a change of position is not enough, 1809 * because being move due to dock divider is not a trigger for animation. 1810 */ handleWindowMovedIfNeeded()1811 void handleWindowMovedIfNeeded() { 1812 if (!hasMoved()) { 1813 return; 1814 } 1815 1816 // Frame has moved, containing content frame has also moved, and we're not currently 1817 // animating... let's do something. 1818 final int left = mWindowFrames.mFrame.left; 1819 final int top = mWindowFrames.mFrame.top; 1820 final Task task = getTask(); 1821 final boolean adjustedForMinimizedDockOrIme = task != null 1822 && (task.mStack.isAdjustedForMinimizedDockedStack() 1823 || task.mStack.isAdjustedForIme()); 1824 if (mToken.okToAnimate() 1825 && (mAttrs.privateFlags & PRIVATE_FLAG_NO_MOVE_ANIMATION) == 0 1826 && !isDragResizing() && !adjustedForMinimizedDockOrIme 1827 && getWindowConfiguration().hasMovementAnimations() 1828 && !mWinAnimator.mLastHidden 1829 && !mSeamlesslyRotated) { 1830 startMoveAnimation(left, top); 1831 } 1832 1833 // TODO (multidisplay): Accessibility supported only for the default display and 1834 // embedded displays 1835 if (mWmService.mAccessibilityController != null && (getDisplayId() == DEFAULT_DISPLAY 1836 || getDisplayContent().getParentWindow() != null)) { 1837 mWmService.mAccessibilityController.onSomeWindowResizedOrMovedLocked(); 1838 } 1839 updateLocationInParentDisplayIfNeeded(); 1840 1841 try { 1842 mClient.moved(left, top); 1843 } catch (RemoteException e) { 1844 } 1845 mMovedByResize = false; 1846 } 1847 1848 /** 1849 * Return whether this window has moved. (Only makes 1850 * sense to call from performLayoutAndPlaceSurfacesLockedInner().) 1851 */ hasMoved()1852 private boolean hasMoved() { 1853 return mHasSurface && (mWindowFrames.hasContentChanged() || mMovedByResize) 1854 && !mAnimatingExit 1855 && (mWindowFrames.mFrame.top != mWindowFrames.mLastFrame.top 1856 || mWindowFrames.mFrame.left != mWindowFrames.mLastFrame.left) 1857 && (!mIsChildWindow || !getParentWindow().hasMoved()); 1858 } 1859 isObscuringDisplay()1860 boolean isObscuringDisplay() { 1861 Task task = getTask(); 1862 if (task != null && task.mStack != null && !task.mStack.fillsParent()) { 1863 return false; 1864 } 1865 return isOpaqueDrawn() && fillsDisplay(); 1866 } 1867 fillsDisplay()1868 boolean fillsDisplay() { 1869 final DisplayInfo displayInfo = getDisplayInfo(); 1870 return mWindowFrames.mFrame.left <= 0 && mWindowFrames.mFrame.top <= 0 1871 && mWindowFrames.mFrame.right >= displayInfo.appWidth 1872 && mWindowFrames.mFrame.bottom >= displayInfo.appHeight; 1873 } 1874 matchesDisplayBounds()1875 private boolean matchesDisplayBounds() { 1876 return getDisplayContent().getBounds().equals(getBounds()); 1877 } 1878 1879 /** 1880 * @return {@code true} if last applied config was reported to the client already, {@code false} 1881 * otherwise. 1882 */ isLastConfigReportedToClient()1883 boolean isLastConfigReportedToClient() { 1884 return mLastConfigReportedToClient; 1885 } 1886 1887 @Override onMergedOverrideConfigurationChanged()1888 void onMergedOverrideConfigurationChanged() { 1889 super.onMergedOverrideConfigurationChanged(); 1890 mLastConfigReportedToClient = false; 1891 } 1892 onWindowReplacementTimeout()1893 void onWindowReplacementTimeout() { 1894 if (mWillReplaceWindow) { 1895 // Since the window already timed out, remove it immediately now. 1896 // Use WindowState#removeImmediately() instead of WindowState#removeIfPossible(), as the latter 1897 // delays removal on certain conditions, which will leave the stale window in the 1898 // stack and marked mWillReplaceWindow=false, so the window will never be removed. 1899 // 1900 // Also removes child windows. 1901 removeImmediately(); 1902 } else { 1903 for (int i = mChildren.size() - 1; i >= 0; --i) { 1904 final WindowState c = mChildren.get(i); 1905 c.onWindowReplacementTimeout(); 1906 } 1907 } 1908 } 1909 1910 @Override forceWindowsScaleableInTransaction(boolean force)1911 void forceWindowsScaleableInTransaction(boolean force) { 1912 if (mWinAnimator != null && mWinAnimator.hasSurface()) { 1913 mWinAnimator.mSurfaceController.forceScaleableInTransaction(force); 1914 } 1915 1916 super.forceWindowsScaleableInTransaction(force); 1917 } 1918 1919 @Override removeImmediately()1920 void removeImmediately() { 1921 super.removeImmediately(); 1922 1923 if (mRemoved) { 1924 // Nothing to do. 1925 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, 1926 "WS.removeImmediately: " + this + " Already removed..."); 1927 return; 1928 } 1929 1930 mRemoved = true; 1931 1932 mWillReplaceWindow = false; 1933 if (mReplacementWindow != null) { 1934 mReplacementWindow.mSkipEnterAnimationForSeamlessReplacement = false; 1935 } 1936 1937 final DisplayContent dc = getDisplayContent(); 1938 if (isInputMethodTarget()) { 1939 dc.computeImeTarget(true /* updateImeTarget */); 1940 } 1941 1942 final int type = mAttrs.type; 1943 if (WindowManagerService.excludeWindowTypeFromTapOutTask(type)) { 1944 dc.mTapExcludedWindows.remove(this); 1945 } 1946 if (mTapExcludeRegionHolder != null) { 1947 // If a tap exclude region container was initialized for this window, then it should've 1948 // also been registered in display. 1949 dc.mTapExcludeProvidingWindows.remove(this); 1950 } 1951 dc.getDisplayPolicy().removeWindowLw(this); 1952 1953 disposeInputChannel(); 1954 1955 mWinAnimator.destroyDeferredSurfaceLocked(); 1956 mWinAnimator.destroySurfaceLocked(); 1957 mSession.windowRemovedLocked(); 1958 try { 1959 mClient.asBinder().unlinkToDeath(mDeathRecipient, 0); 1960 } catch (RuntimeException e) { 1961 // Ignore if it has already been removed (usually because 1962 // we are doing this as part of processing a death note.) 1963 } 1964 1965 mWmService.postWindowRemoveCleanupLocked(this); 1966 } 1967 1968 @Override removeIfPossible()1969 void removeIfPossible() { 1970 super.removeIfPossible(); 1971 removeIfPossible(false /*keepVisibleDeadWindow*/); 1972 } 1973 removeIfPossible(boolean keepVisibleDeadWindow)1974 private void removeIfPossible(boolean keepVisibleDeadWindow) { 1975 mWindowRemovalAllowed = true; 1976 if (DEBUG_ADD_REMOVE) Slog.v(TAG, 1977 "removeIfPossible: " + this + " callers=" + Debug.getCallers(5)); 1978 1979 final boolean startingWindow = mAttrs.type == TYPE_APPLICATION_STARTING; 1980 if (startingWindow && DEBUG_STARTING_WINDOW) Slog.d(TAG_WM, 1981 "Starting window removed " + this); 1982 1983 if (localLOGV || DEBUG_FOCUS || DEBUG_FOCUS_LIGHT && isFocused()) 1984 Slog.v(TAG_WM, "Remove " + this + " client=" 1985 + Integer.toHexString(System.identityHashCode(mClient.asBinder())) 1986 + ", surfaceController=" + mWinAnimator.mSurfaceController + " Callers=" 1987 + Debug.getCallers(5)); 1988 1989 final long origId = Binder.clearCallingIdentity(); 1990 1991 try { 1992 disposeInputChannel(); 1993 1994 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Remove " + this 1995 + ": mSurfaceController=" + mWinAnimator.mSurfaceController 1996 + " mAnimatingExit=" + mAnimatingExit 1997 + " mRemoveOnExit=" + mRemoveOnExit 1998 + " mHasSurface=" + mHasSurface 1999 + " surfaceShowing=" + mWinAnimator.getShown() 2000 + " animating=" + isAnimating() 2001 + " app-animation=" 2002 + (mAppToken != null ? mAppToken.isSelfAnimating() : "false") 2003 + " mWillReplaceWindow=" + mWillReplaceWindow 2004 + " inPendingTransaction=" 2005 + (mAppToken != null ? mAppToken.inPendingTransaction : false) 2006 + " mDisplayFrozen=" + mWmService.mDisplayFrozen 2007 + " callers=" + Debug.getCallers(6)); 2008 2009 // Visibility of the removed window. Will be used later to update orientation later on. 2010 boolean wasVisible = false; 2011 2012 final int displayId = getDisplayId(); 2013 2014 // First, see if we need to run an animation. If we do, we have to hold off on removing the 2015 // window until the animation is done. If the display is frozen, just remove immediately, 2016 // since the animation wouldn't be seen. 2017 if (mHasSurface && mToken.okToAnimate()) { 2018 if (mWillReplaceWindow) { 2019 // This window is going to be replaced. We need to keep it around until the new one 2020 // gets added, then we will get rid of this one. 2021 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, 2022 "Preserving " + this + " until the new one is " + "added"); 2023 // TODO: We are overloading mAnimatingExit flag to prevent the window state from 2024 // been removed. We probably need another flag to indicate that window removal 2025 // should be deffered vs. overloading the flag that says we are playing an exit 2026 // animation. 2027 mAnimatingExit = true; 2028 mReplacingRemoveRequested = true; 2029 return; 2030 } 2031 2032 // If we are not currently running the exit animation, we need to see about starting one 2033 wasVisible = isWinVisibleLw(); 2034 2035 if (keepVisibleDeadWindow) { 2036 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, 2037 "Not removing " + this + " because app died while it's visible"); 2038 2039 mAppDied = true; 2040 setDisplayLayoutNeeded(); 2041 mWmService.mWindowPlacerLocked.performSurfacePlacement(); 2042 2043 // Set up a replacement input channel since the app is now dead. 2044 // We need to catch tapping on the dead window to restart the app. 2045 openInputChannel(null); 2046 getDisplayContent().getInputMonitor().updateInputWindowsLw(true /*force*/); 2047 return; 2048 } 2049 2050 if (wasVisible) { 2051 final int transit = (!startingWindow) ? TRANSIT_EXIT : TRANSIT_PREVIEW_DONE; 2052 2053 // Try starting an animation. 2054 if (mWinAnimator.applyAnimationLocked(transit, false)) { 2055 mAnimatingExit = true; 2056 2057 // mAnimatingExit affects canAffectSystemUiFlags(). Run layout such that 2058 // any change from that is performed immediately. 2059 setDisplayLayoutNeeded(); 2060 mWmService.requestTraversal(); 2061 } 2062 if (mWmService.mAccessibilityController != null) { 2063 mWmService.mAccessibilityController.onWindowTransitionLocked(this, transit); 2064 } 2065 } 2066 final boolean isAnimating = isAnimating() 2067 && (mAppToken == null || !mAppToken.isWaitingForTransitionStart()); 2068 final boolean lastWindowIsStartingWindow = startingWindow && mAppToken != null 2069 && mAppToken.isLastWindow(this); 2070 // We delay the removal of a window if it has a showing surface that can be used to run 2071 // exit animation and it is marked as exiting. 2072 // Also, If isn't the an animating starting window that is the last window in the app. 2073 // We allow the removal of the non-animating starting window now as there is no 2074 // additional window or animation that will trigger its removal. 2075 if (mWinAnimator.getShown() && mAnimatingExit 2076 && (!lastWindowIsStartingWindow || isAnimating)) { 2077 // The exit animation is running or should run... wait for it! 2078 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, 2079 "Not removing " + this + " due to exit animation "); 2080 setupWindowForRemoveOnExit(); 2081 if (mAppToken != null) { 2082 mAppToken.updateReportedVisibilityLocked(); 2083 } 2084 return; 2085 } 2086 } 2087 2088 removeImmediately(); 2089 // Removing a visible window will effect the computed orientation 2090 // So just update orientation if needed. 2091 if (wasVisible) { 2092 final DisplayContent displayContent = getDisplayContent(); 2093 if (displayContent.updateOrientationFromAppTokens()) { 2094 displayContent.sendNewConfiguration(); 2095 } 2096 } 2097 mWmService.updateFocusedWindowLocked(isFocused() 2098 ? UPDATE_FOCUS_REMOVING_FOCUS 2099 : UPDATE_FOCUS_NORMAL, 2100 true /*updateInputWindows*/); 2101 } finally { 2102 Binder.restoreCallingIdentity(origId); 2103 } 2104 } 2105 setupWindowForRemoveOnExit()2106 private void setupWindowForRemoveOnExit() { 2107 mRemoveOnExit = true; 2108 setDisplayLayoutNeeded(); 2109 // Request a focus update as this window's input channel is already gone. Otherwise 2110 // we could have no focused window in input manager. 2111 final boolean focusChanged = mWmService.updateFocusedWindowLocked( 2112 UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/); 2113 mWmService.mWindowPlacerLocked.performSurfacePlacement(); 2114 if (focusChanged) { 2115 getDisplayContent().getInputMonitor().updateInputWindowsLw(false /*force*/); 2116 } 2117 } 2118 setHasSurface(boolean hasSurface)2119 void setHasSurface(boolean hasSurface) { 2120 mHasSurface = hasSurface; 2121 } 2122 canBeImeTarget()2123 boolean canBeImeTarget() { 2124 if (mIsImWindow) { 2125 // IME windows can't be IME targets. IME targets are required to be below the IME 2126 // windows and that wouldn't be possible if the IME window is its own target...silly. 2127 return false; 2128 } 2129 2130 final boolean windowsAreFocusable = mAppToken == null || mAppToken.windowsAreFocusable(); 2131 if (!windowsAreFocusable) { 2132 // This window can't be an IME target if the app's windows should not be focusable. 2133 return false; 2134 } 2135 2136 final int fl = mAttrs.flags & (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM); 2137 final int type = mAttrs.type; 2138 2139 // Can only be an IME target if both FLAG_NOT_FOCUSABLE and FLAG_ALT_FOCUSABLE_IM are set or 2140 // both are cleared...and not a starting window. 2141 if (fl != 0 && fl != (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM) 2142 && type != TYPE_APPLICATION_STARTING) { 2143 return false; 2144 } 2145 2146 if (DEBUG_INPUT_METHOD) { 2147 Slog.i(TAG_WM, "isVisibleOrAdding " + this + ": " + isVisibleOrAdding()); 2148 if (!isVisibleOrAdding()) { 2149 Slog.i(TAG_WM, " mSurfaceController=" + mWinAnimator.mSurfaceController 2150 + " relayoutCalled=" + mRelayoutCalled 2151 + " viewVis=" + mViewVisibility 2152 + " policyVis=" + isVisibleByPolicy() 2153 + " policyVisAfterAnim=" + mLegacyPolicyVisibilityAfterAnim 2154 + " parentHidden=" + isParentWindowHidden() 2155 + " exiting=" + mAnimatingExit + " destroying=" + mDestroying); 2156 if (mAppToken != null) { 2157 Slog.i(TAG_WM, " mAppToken.hiddenRequested=" + mAppToken.hiddenRequested); 2158 } 2159 } 2160 } 2161 return isVisibleOrAdding(); 2162 } 2163 2164 private final class DeadWindowEventReceiver extends InputEventReceiver { DeadWindowEventReceiver(InputChannel inputChannel)2165 DeadWindowEventReceiver(InputChannel inputChannel) { 2166 super(inputChannel, mWmService.mH.getLooper()); 2167 } 2168 @Override onInputEvent(InputEvent event)2169 public void onInputEvent(InputEvent event) { 2170 finishInputEvent(event, true); 2171 } 2172 } 2173 /** 2174 * Dummy event receiver for windows that died visible. 2175 */ 2176 private DeadWindowEventReceiver mDeadWindowEventReceiver; 2177 openInputChannel(InputChannel outInputChannel)2178 void openInputChannel(InputChannel outInputChannel) { 2179 if (mInputChannel != null) { 2180 throw new IllegalStateException("Window already has an input channel."); 2181 } 2182 String name = getName(); 2183 InputChannel[] inputChannels = InputChannel.openInputChannelPair(name); 2184 mInputChannel = inputChannels[0]; 2185 mClientChannel = inputChannels[1]; 2186 mInputWindowHandle.token = mClient.asBinder(); 2187 if (outInputChannel != null) { 2188 mClientChannel.transferTo(outInputChannel); 2189 mClientChannel.dispose(); 2190 mClientChannel = null; 2191 } else { 2192 // If the window died visible, we setup a dummy input channel, so that taps 2193 // can still detected by input monitor channel, and we can relaunch the app. 2194 // Create dummy event receiver that simply reports all events as handled. 2195 mDeadWindowEventReceiver = new DeadWindowEventReceiver(mClientChannel); 2196 } 2197 mWmService.mInputManager.registerInputChannel(mInputChannel, mClient.asBinder()); 2198 } 2199 disposeInputChannel()2200 void disposeInputChannel() { 2201 if (mDeadWindowEventReceiver != null) { 2202 mDeadWindowEventReceiver.dispose(); 2203 mDeadWindowEventReceiver = null; 2204 } 2205 2206 // unregister server channel first otherwise it complains about broken channel 2207 if (mInputChannel != null) { 2208 mWmService.mInputManager.unregisterInputChannel(mInputChannel); 2209 2210 mInputChannel.dispose(); 2211 mInputChannel = null; 2212 } 2213 if (mClientChannel != null) { 2214 mClientChannel.dispose(); 2215 mClientChannel = null; 2216 } 2217 mInputWindowHandle.token = null; 2218 } 2219 2220 /** Returns true if the replacement window was removed. */ removeReplacedWindowIfNeeded(WindowState replacement)2221 boolean removeReplacedWindowIfNeeded(WindowState replacement) { 2222 if (mWillReplaceWindow && mReplacementWindow == replacement && replacement.hasDrawnLw()) { 2223 replacement.mSkipEnterAnimationForSeamlessReplacement = false; 2224 removeReplacedWindow(); 2225 return true; 2226 } 2227 2228 for (int i = mChildren.size() - 1; i >= 0; --i) { 2229 final WindowState c = mChildren.get(i); 2230 if (c.removeReplacedWindowIfNeeded(replacement)) { 2231 return true; 2232 } 2233 } 2234 return false; 2235 } 2236 removeReplacedWindow()2237 private void removeReplacedWindow() { 2238 if (DEBUG_ADD_REMOVE) Slog.d(TAG, "Removing replaced window: " + this); 2239 mWillReplaceWindow = false; 2240 mAnimateReplacingWindow = false; 2241 mReplacingRemoveRequested = false; 2242 mReplacementWindow = null; 2243 if (mAnimatingExit || !mAnimateReplacingWindow) { 2244 removeImmediately(); 2245 } 2246 } 2247 setReplacementWindowIfNeeded(WindowState replacementCandidate)2248 boolean setReplacementWindowIfNeeded(WindowState replacementCandidate) { 2249 boolean replacementSet = false; 2250 2251 if (mWillReplaceWindow && mReplacementWindow == null 2252 && getWindowTag().toString().equals(replacementCandidate.getWindowTag().toString())) { 2253 2254 mReplacementWindow = replacementCandidate; 2255 replacementCandidate.mSkipEnterAnimationForSeamlessReplacement = !mAnimateReplacingWindow; 2256 replacementSet = true; 2257 } 2258 2259 for (int i = mChildren.size() - 1; i >= 0; --i) { 2260 final WindowState c = mChildren.get(i); 2261 replacementSet |= c.setReplacementWindowIfNeeded(replacementCandidate); 2262 } 2263 2264 return replacementSet; 2265 } 2266 setDisplayLayoutNeeded()2267 void setDisplayLayoutNeeded() { 2268 final DisplayContent dc = getDisplayContent(); 2269 if (dc != null) { 2270 dc.setLayoutNeeded(); 2271 } 2272 } 2273 applyAdjustForImeIfNeeded()2274 void applyAdjustForImeIfNeeded() { 2275 final Task task = getTask(); 2276 if (task != null && task.mStack != null && task.mStack.isAdjustedForIme()) { 2277 task.mStack.applyAdjustForImeIfNeeded(task); 2278 } 2279 } 2280 2281 @Override switchUser()2282 void switchUser() { 2283 super.switchUser(); 2284 if (isHiddenFromUserLocked()) { 2285 if (DEBUG_VISIBILITY) Slog.w(TAG_WM, "user changing, hiding " + this 2286 + ", attrs=" + mAttrs.type + ", belonging to " + mOwnerUid); 2287 clearPolicyVisibilityFlag(VISIBLE_FOR_USER); 2288 } else { 2289 setPolicyVisibilityFlag(VISIBLE_FOR_USER); 2290 } 2291 } 2292 getSurfaceTouchableRegion(InputWindowHandle inputWindowHandle, int flags)2293 int getSurfaceTouchableRegion(InputWindowHandle inputWindowHandle, int flags) { 2294 final boolean modal = (flags & (FLAG_NOT_TOUCH_MODAL | FLAG_NOT_FOCUSABLE)) == 0; 2295 final Region region = inputWindowHandle.touchableRegion; 2296 setTouchableRegionCropIfNeeded(inputWindowHandle); 2297 2298 final Rect appOverrideBounds = mAppToken != null 2299 ? mAppToken.getResolvedOverrideBounds() : null; 2300 if (appOverrideBounds != null && !appOverrideBounds.isEmpty()) { 2301 // There may have touchable letterboxes around the activity, so in order to let the 2302 // letterboxes are able to receive touch event and slip to activity, the activity with 2303 // compatibility bounds cannot occupy full screen touchable region. 2304 if (modal) { 2305 // A modal window uses the whole compatibility bounds. 2306 flags |= FLAG_NOT_TOUCH_MODAL; 2307 mTmpRect.set(0, 0, appOverrideBounds.width(), appOverrideBounds.height()); 2308 } else { 2309 // Non-modal uses the application based frame. 2310 mTmpRect.set(mWindowFrames.mCompatFrame); 2311 } 2312 // The offset of compatibility bounds is applied to surface of {@link #AppWindowToken} 2313 // and frame, so it is unnecessary to translate twice in surface based coordinates. 2314 final int surfaceOffsetX = mAppToken.inSizeCompatMode() 2315 ? mAppToken.getBounds().left : 0; 2316 mTmpRect.offset(surfaceOffsetX - mWindowFrames.mFrame.left, -mWindowFrames.mFrame.top); 2317 region.set(mTmpRect); 2318 return flags; 2319 } 2320 2321 if (modal && mAppToken != null) { 2322 // Limit the outer touch to the activity stack region. 2323 flags |= FLAG_NOT_TOUCH_MODAL; 2324 // If the inner bounds of letterbox is available, then it will be used as the touchable 2325 // region so it won't cover the touchable letterbox and the touch events can slip to 2326 // activity from letterbox. 2327 mAppToken.getLetterboxInnerBounds(mTmpRect); 2328 if (mTmpRect.isEmpty()) { 2329 // If this is a modal window we need to dismiss it if it's not full screen and the 2330 // touch happens outside of the frame that displays the content. This means we need 2331 // to intercept touches outside of that window. The dim layer user associated with 2332 // the window (task or stack) will give us the good bounds, as they would be used to 2333 // display the dim layer. 2334 final Task task = getTask(); 2335 if (task != null) { 2336 task.getDimBounds(mTmpRect); 2337 } else { 2338 getStack().getDimBounds(mTmpRect); 2339 } 2340 } 2341 if (inFreeformWindowingMode()) { 2342 // For freeform windows we the touch region to include the whole surface for the 2343 // shadows. 2344 final DisplayMetrics displayMetrics = getDisplayContent().getDisplayMetrics(); 2345 final int delta = WindowManagerService.dipToPixel( 2346 RESIZE_HANDLE_WIDTH_IN_DP, displayMetrics); 2347 mTmpRect.inset(-delta, -delta); 2348 } 2349 region.set(mTmpRect); 2350 cropRegionToStackBoundsIfNeeded(region); 2351 subtractTouchExcludeRegionIfNeeded(region); 2352 } else if (modal && mTapExcludeRegionHolder != null) { 2353 final Region touchExcludeRegion = Region.obtain(); 2354 amendTapExcludeRegion(touchExcludeRegion); 2355 if (!touchExcludeRegion.isEmpty()) { 2356 // Remove touch modal because there are some areas that cannot be touched. 2357 flags |= FLAG_NOT_TOUCH_MODAL; 2358 // Give it a large touchable region at first because it was touch modal. The window 2359 // might be moved on the display, so the touchable region should be large enough to 2360 // ensure it covers the whole display, no matter where it is moved. 2361 getDisplayContent().getBounds(mTmpRect); 2362 final int dw = mTmpRect.width(); 2363 final int dh = mTmpRect.height(); 2364 region.set(-dw, -dh, dw + dw, dh + dh); 2365 // Subtract the area that cannot be touched. 2366 region.op(touchExcludeRegion, Region.Op.DIFFERENCE); 2367 inputWindowHandle.setTouchableRegionCrop(null); 2368 } 2369 touchExcludeRegion.recycle(); 2370 } else { 2371 // Not modal or full screen modal 2372 getTouchableRegion(region); 2373 } 2374 // Translate to surface based coordinates. 2375 region.translate(-mWindowFrames.mFrame.left, -mWindowFrames.mFrame.top); 2376 2377 return flags; 2378 } 2379 checkPolicyVisibilityChange()2380 void checkPolicyVisibilityChange() { 2381 if (isLegacyPolicyVisibility() != mLegacyPolicyVisibilityAfterAnim) { 2382 if (DEBUG_VISIBILITY) { 2383 Slog.v(TAG, "Policy visibility changing after anim in " + 2384 mWinAnimator + ": " + mLegacyPolicyVisibilityAfterAnim); 2385 } 2386 if (mLegacyPolicyVisibilityAfterAnim) { 2387 setPolicyVisibilityFlag(LEGACY_POLICY_VISIBILITY); 2388 } else { 2389 clearPolicyVisibilityFlag(LEGACY_POLICY_VISIBILITY); 2390 } 2391 if (!isVisibleByPolicy()) { 2392 mWinAnimator.hide("checkPolicyVisibilityChange"); 2393 if (isFocused()) { 2394 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, 2395 "setAnimationLocked: setting mFocusMayChange true"); 2396 mWmService.mFocusMayChange = true; 2397 } 2398 setDisplayLayoutNeeded(); 2399 // Window is no longer visible -- make sure if we were waiting 2400 // for it to be displayed before enabling the display, that 2401 // we allow the display to be enabled now. 2402 mWmService.enableScreenIfNeededLocked(); 2403 } 2404 } 2405 } 2406 setRequestedSize(int requestedWidth, int requestedHeight)2407 void setRequestedSize(int requestedWidth, int requestedHeight) { 2408 if ((mRequestedWidth != requestedWidth || mRequestedHeight != requestedHeight)) { 2409 mLayoutNeeded = true; 2410 mRequestedWidth = requestedWidth; 2411 mRequestedHeight = requestedHeight; 2412 } 2413 } 2414 prepareWindowToDisplayDuringRelayout(boolean wasVisible)2415 void prepareWindowToDisplayDuringRelayout(boolean wasVisible) { 2416 // We need to turn on screen regardless of visibility. 2417 boolean hasTurnScreenOnFlag = (mAttrs.flags & FLAG_TURN_SCREEN_ON) != 0; 2418 2419 // The screen will turn on if the following conditions are met 2420 // 1. The window has the flag FLAG_TURN_SCREEN_ON 2421 // 2. The WMS allows theater mode. 2422 // 3. No AWT or the AWT allows the screen to be turned on. This should only be true once 2423 // per resume to prevent the screen getting getting turned on for each relayout. Set 2424 // canTurnScreenOn will be set to false so the window doesn't turn the screen on again 2425 // during this resume. 2426 // 4. When the screen is not interactive. This is because when the screen is already 2427 // interactive, the value may persist until the next animation, which could potentially 2428 // be occurring while turning off the screen. This would lead to the screen incorrectly 2429 // turning back on. 2430 if (hasTurnScreenOnFlag) { 2431 boolean allowTheaterMode = mWmService.mAllowTheaterModeWakeFromLayout 2432 || Settings.Global.getInt(mWmService.mContext.getContentResolver(), 2433 Settings.Global.THEATER_MODE_ON, 0) == 0; 2434 boolean canTurnScreenOn = mAppToken == null || mAppToken.canTurnScreenOn(); 2435 2436 if (allowTheaterMode && canTurnScreenOn && !mPowerManagerWrapper.isInteractive()) { 2437 if (DEBUG_VISIBILITY || DEBUG_POWER) { 2438 Slog.v(TAG, "Relayout window turning screen on: " + this); 2439 } 2440 mPowerManagerWrapper.wakeUp(SystemClock.uptimeMillis(), 2441 PowerManager.WAKE_REASON_APPLICATION, "android.server.wm:SCREEN_ON_FLAG"); 2442 } 2443 2444 if (mAppToken != null) { 2445 mAppToken.setCanTurnScreenOn(false); 2446 } 2447 } 2448 2449 // If we were already visible, skip rest of preparation. 2450 if (wasVisible) { 2451 if (DEBUG_VISIBILITY) Slog.v(TAG, 2452 "Already visible and does not turn on screen, skip preparing: " + this); 2453 return; 2454 } 2455 2456 if ((mAttrs.softInputMode & SOFT_INPUT_MASK_ADJUST) 2457 == SOFT_INPUT_ADJUST_RESIZE) { 2458 mLayoutNeeded = true; 2459 } 2460 2461 if (isDrawnLw() && mToken.okToAnimate()) { 2462 mWinAnimator.applyEnterAnimationLocked(); 2463 } 2464 } 2465 getProcessGlobalConfiguration()2466 private Configuration getProcessGlobalConfiguration() { 2467 // For child windows we want to use the pid for the parent window in case the the child 2468 // window was added from another process. 2469 final WindowState parentWindow = getParentWindow(); 2470 final int pid = parentWindow != null ? parentWindow.mSession.mPid : mSession.mPid; 2471 final Configuration processConfig = 2472 mWmService.mAtmService.getGlobalConfigurationForPid(pid); 2473 return processConfig; 2474 } 2475 getMergedConfiguration(MergedConfiguration outConfiguration)2476 void getMergedConfiguration(MergedConfiguration outConfiguration) { 2477 final Configuration globalConfig = getProcessGlobalConfiguration(); 2478 final Configuration overrideConfig = getMergedOverrideConfiguration(); 2479 outConfiguration.setConfiguration(globalConfig, overrideConfig); 2480 } 2481 setLastReportedMergedConfiguration(MergedConfiguration config)2482 void setLastReportedMergedConfiguration(MergedConfiguration config) { 2483 mLastReportedConfiguration.setTo(config); 2484 mLastConfigReportedToClient = true; 2485 } 2486 getLastReportedMergedConfiguration(MergedConfiguration config)2487 void getLastReportedMergedConfiguration(MergedConfiguration config) { 2488 config.setTo(mLastReportedConfiguration); 2489 } 2490 getLastReportedConfiguration()2491 private Configuration getLastReportedConfiguration() { 2492 return mLastReportedConfiguration.getMergedConfiguration(); 2493 } 2494 adjustStartingWindowFlags()2495 void adjustStartingWindowFlags() { 2496 if (mAttrs.type == TYPE_BASE_APPLICATION && mAppToken != null 2497 && mAppToken.startingWindow != null) { 2498 // Special handling of starting window over the base 2499 // window of the app: propagate lock screen flags to it, 2500 // to provide the correct semantics while starting. 2501 final int mask = FLAG_SHOW_WHEN_LOCKED | FLAG_DISMISS_KEYGUARD 2502 | FLAG_ALLOW_LOCK_WHILE_SCREEN_ON; 2503 WindowManager.LayoutParams sa = mAppToken.startingWindow.mAttrs; 2504 sa.flags = (sa.flags & ~mask) | (mAttrs.flags & mask); 2505 } 2506 } 2507 setWindowScale(int requestedWidth, int requestedHeight)2508 void setWindowScale(int requestedWidth, int requestedHeight) { 2509 final boolean scaledWindow = (mAttrs.flags & FLAG_SCALED) != 0; 2510 2511 if (scaledWindow) { 2512 // requested{Width|Height} Surface's physical size 2513 // attrs.{width|height} Size on screen 2514 // TODO: We don't check if attrs != null here. Is it implicitly checked? 2515 mHScale = (mAttrs.width != requestedWidth) ? 2516 (mAttrs.width / (float)requestedWidth) : 1.0f; 2517 mVScale = (mAttrs.height != requestedHeight) ? 2518 (mAttrs.height / (float)requestedHeight) : 1.0f; 2519 } else { 2520 mHScale = mVScale = 1; 2521 } 2522 } 2523 2524 private class DeathRecipient implements IBinder.DeathRecipient { 2525 @Override binderDied()2526 public void binderDied() { 2527 try { 2528 boolean resetSplitScreenResizing = false; 2529 synchronized (mWmService.mGlobalLock) { 2530 final WindowState win = mWmService 2531 .windowForClientLocked(mSession, mClient, false); 2532 Slog.i(TAG, "WIN DEATH: " + win); 2533 if (win != null) { 2534 final DisplayContent dc = getDisplayContent(); 2535 if (win.mAppToken != null && win.mAppToken.findMainWindow() == win) { 2536 mWmService.mTaskSnapshotController.onAppDied(win.mAppToken); 2537 } 2538 win.removeIfPossible(shouldKeepVisibleDeadAppWindow()); 2539 if (win.mAttrs.type == TYPE_DOCK_DIVIDER) { 2540 // The owner of the docked divider died :( We reset the docked stack, 2541 // just in case they have the divider at an unstable position. Better 2542 // also reset drag resizing state, because the owner can't do it 2543 // anymore. 2544 final TaskStack stack = 2545 dc.getSplitScreenPrimaryStackIgnoringVisibility(); 2546 if (stack != null) { 2547 stack.resetDockedStackToMiddle(); 2548 } 2549 resetSplitScreenResizing = true; 2550 } 2551 } else if (mHasSurface) { 2552 Slog.e(TAG, "!!! LEAK !!! Window removed but surface still valid."); 2553 WindowState.this.removeIfPossible(); 2554 } 2555 } 2556 if (resetSplitScreenResizing) { 2557 try { 2558 // Note: this calls into ActivityManager, so we must *not* hold the window 2559 // manager lock while calling this. 2560 mWmService.mActivityTaskManager.setSplitScreenResizing(false); 2561 } catch (RemoteException e) { 2562 // Local call, shouldn't return RemoteException. 2563 throw e.rethrowAsRuntimeException(); 2564 } 2565 } 2566 } catch (IllegalArgumentException ex) { 2567 // This will happen if the window has already been removed. 2568 } 2569 } 2570 } 2571 2572 /** 2573 * Returns true if this window is visible and belongs to a dead app and shouldn't be removed, 2574 * because we want to preserve its location on screen to be re-activated later when the user 2575 * interacts with it. 2576 */ shouldKeepVisibleDeadAppWindow()2577 private boolean shouldKeepVisibleDeadAppWindow() { 2578 if (!isWinVisibleLw() || mAppToken == null || mAppToken.isClientHidden()) { 2579 // Not a visible app window or the app isn't dead. 2580 return false; 2581 } 2582 2583 if (mAttrs.token != mClient.asBinder()) { 2584 // The window was add by a client using another client's app token. We don't want to 2585 // keep the dead window around for this case since this is meant for 'real' apps. 2586 return false; 2587 } 2588 2589 if (mAttrs.type == TYPE_APPLICATION_STARTING) { 2590 // We don't keep starting windows since they were added by the window manager before 2591 // the app even launched. 2592 return false; 2593 } 2594 2595 return getWindowConfiguration().keepVisibleDeadAppWindowOnScreen(); 2596 } 2597 2598 @Override canReceiveKeys()2599 public boolean canReceiveKeys() { 2600 return isVisibleOrAdding() 2601 && (mViewVisibility == View.VISIBLE) && !mRemoveOnExit 2602 && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0) 2603 && (mAppToken == null || mAppToken.windowsAreFocusable()) 2604 && !cantReceiveTouchInput(); 2605 } 2606 2607 @Override canShowWhenLocked()2608 public boolean canShowWhenLocked() { 2609 final boolean showBecauseOfActivity = 2610 mAppToken != null && mAppToken.mActivityRecord.canShowWhenLocked(); 2611 final boolean showBecauseOfWindow = (getAttrs().flags & FLAG_SHOW_WHEN_LOCKED) != 0; 2612 return showBecauseOfActivity || showBecauseOfWindow; 2613 } 2614 2615 /** @return false if this window desires touch events. */ cantReceiveTouchInput()2616 boolean cantReceiveTouchInput() { 2617 return mAppToken != null && mAppToken.getTask() != null 2618 && (mAppToken.getTask().mStack.shouldIgnoreInput() || mAppToken.hiddenRequested); 2619 } 2620 2621 @Override hasDrawnLw()2622 public boolean hasDrawnLw() { 2623 return mWinAnimator.mDrawState == WindowStateAnimator.HAS_DRAWN; 2624 } 2625 2626 @Override showLw(boolean doAnimation)2627 public boolean showLw(boolean doAnimation) { 2628 return showLw(doAnimation, true); 2629 } 2630 showLw(boolean doAnimation, boolean requestAnim)2631 boolean showLw(boolean doAnimation, boolean requestAnim) { 2632 if (isLegacyPolicyVisibility() && mLegacyPolicyVisibilityAfterAnim) { 2633 // Already showing. 2634 return false; 2635 } 2636 if (isHiddenFromUserLocked()) { 2637 return false; 2638 } 2639 if (!mAppOpVisibility) { 2640 // Being hidden due to app op request. 2641 return false; 2642 } 2643 if (mPermanentlyHidden) { 2644 // Permanently hidden until the app exists as apps aren't prepared 2645 // to handle their windows being removed from under them. 2646 return false; 2647 } 2648 if (mHiddenWhileSuspended) { 2649 // Being hidden due to owner package being suspended. 2650 return false; 2651 } 2652 if (mForceHideNonSystemOverlayWindow) { 2653 // This is an alert window that is currently force hidden. 2654 return false; 2655 } 2656 if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility true: " + this); 2657 if (doAnimation) { 2658 if (DEBUG_VISIBILITY) Slog.v(TAG, "doAnimation: mPolicyVisibility=" 2659 + isLegacyPolicyVisibility() + " animating=" + isAnimating()); 2660 if (!mToken.okToAnimate()) { 2661 doAnimation = false; 2662 } else if (isLegacyPolicyVisibility() && !isAnimating()) { 2663 // Check for the case where we are currently visible and 2664 // not animating; we do not want to do animation at such a 2665 // point to become visible when we already are. 2666 doAnimation = false; 2667 } 2668 } 2669 setPolicyVisibilityFlag(LEGACY_POLICY_VISIBILITY); 2670 mLegacyPolicyVisibilityAfterAnim = true; 2671 if (doAnimation) { 2672 mWinAnimator.applyAnimationLocked(TRANSIT_ENTER, true); 2673 } 2674 if (requestAnim) { 2675 mWmService.scheduleAnimationLocked(); 2676 } 2677 if ((mAttrs.flags & FLAG_NOT_FOCUSABLE) == 0) { 2678 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false /* updateImWindows */); 2679 } 2680 return true; 2681 } 2682 2683 @Override hideLw(boolean doAnimation)2684 public boolean hideLw(boolean doAnimation) { 2685 return hideLw(doAnimation, true); 2686 } 2687 hideLw(boolean doAnimation, boolean requestAnim)2688 boolean hideLw(boolean doAnimation, boolean requestAnim) { 2689 if (doAnimation) { 2690 if (!mToken.okToAnimate()) { 2691 doAnimation = false; 2692 } 2693 } 2694 boolean current = 2695 doAnimation ? mLegacyPolicyVisibilityAfterAnim : isLegacyPolicyVisibility(); 2696 if (!current) { 2697 // Already hiding. 2698 return false; 2699 } 2700 if (doAnimation) { 2701 mWinAnimator.applyAnimationLocked(TRANSIT_EXIT, false); 2702 if (!isAnimating()) { 2703 doAnimation = false; 2704 } 2705 } 2706 mLegacyPolicyVisibilityAfterAnim = false; 2707 final boolean isFocused = isFocused(); 2708 if (!doAnimation) { 2709 if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility false: " + this); 2710 clearPolicyVisibilityFlag(LEGACY_POLICY_VISIBILITY); 2711 // Window is no longer visible -- make sure if we were waiting 2712 // for it to be displayed before enabling the display, that 2713 // we allow the display to be enabled now. 2714 mWmService.enableScreenIfNeededLocked(); 2715 if (isFocused) { 2716 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, 2717 "WindowState.hideLw: setting mFocusMayChange true"); 2718 mWmService.mFocusMayChange = true; 2719 } 2720 } 2721 if (requestAnim) { 2722 mWmService.scheduleAnimationLocked(); 2723 } 2724 if (isFocused) { 2725 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false /* updateImWindows */); 2726 } 2727 return true; 2728 } 2729 setForceHideNonSystemOverlayWindowIfNeeded(boolean forceHide)2730 void setForceHideNonSystemOverlayWindowIfNeeded(boolean forceHide) { 2731 if (mOwnerCanAddInternalSystemWindow 2732 || (!isSystemAlertWindowType(mAttrs.type) && mAttrs.type != TYPE_TOAST)) { 2733 return; 2734 } 2735 if (mForceHideNonSystemOverlayWindow == forceHide) { 2736 return; 2737 } 2738 mForceHideNonSystemOverlayWindow = forceHide; 2739 if (forceHide) { 2740 hideLw(true /* doAnimation */, true /* requestAnim */); 2741 } else { 2742 showLw(true /* doAnimation */, true /* requestAnim */); 2743 } 2744 } 2745 setHiddenWhileSuspended(boolean hide)2746 void setHiddenWhileSuspended(boolean hide) { 2747 if (mOwnerCanAddInternalSystemWindow 2748 || (!isSystemAlertWindowType(mAttrs.type) && mAttrs.type != TYPE_TOAST)) { 2749 return; 2750 } 2751 if (mHiddenWhileSuspended == hide) { 2752 return; 2753 } 2754 mHiddenWhileSuspended = hide; 2755 if (hide) { 2756 hideLw(true, true); 2757 } else { 2758 showLw(true, true); 2759 } 2760 } 2761 setAppOpVisibilityLw(boolean state)2762 private void setAppOpVisibilityLw(boolean state) { 2763 if (mAppOpVisibility != state) { 2764 mAppOpVisibility = state; 2765 if (state) { 2766 // If the policy visibility had last been to hide, then this 2767 // will incorrectly show at this point since we lost that 2768 // information. Not a big deal -- for the windows that have app 2769 // ops modifies they should only be hidden by policy due to the 2770 // lock screen, and the user won't be changing this if locked. 2771 // Plus it will quickly be fixed the next time we do a layout. 2772 showLw(true, true); 2773 } else { 2774 hideLw(true, true); 2775 } 2776 } 2777 } 2778 initAppOpsState()2779 void initAppOpsState() { 2780 if (mAppOp == OP_NONE || !mAppOpVisibility) { 2781 return; 2782 } 2783 // If the app op was MODE_DEFAULT we would have checked the permission 2784 // and add the window only if the permission was granted. Therefore, if 2785 // the mode is MODE_DEFAULT we want the op to succeed as the window is 2786 // shown. 2787 final int mode = mWmService.mAppOps.startOpNoThrow(mAppOp, 2788 getOwningUid(), getOwningPackage(), true); 2789 if (mode != MODE_ALLOWED && mode != MODE_DEFAULT) { 2790 setAppOpVisibilityLw(false); 2791 } 2792 } 2793 resetAppOpsState()2794 void resetAppOpsState() { 2795 if (mAppOp != OP_NONE && mAppOpVisibility) { 2796 mWmService.mAppOps.finishOp(mAppOp, getOwningUid(), getOwningPackage()); 2797 } 2798 } 2799 updateAppOpsState()2800 void updateAppOpsState() { 2801 if (mAppOp == OP_NONE) { 2802 return; 2803 } 2804 final int uid = getOwningUid(); 2805 final String packageName = getOwningPackage(); 2806 if (mAppOpVisibility) { 2807 // There is a race between the check and the finish calls but this is fine 2808 // as this would mean we will get another change callback and will reconcile. 2809 int mode = mWmService.mAppOps.checkOpNoThrow(mAppOp, uid, packageName); 2810 if (mode != MODE_ALLOWED && mode != MODE_DEFAULT) { 2811 mWmService.mAppOps.finishOp(mAppOp, uid, packageName); 2812 setAppOpVisibilityLw(false); 2813 } 2814 } else { 2815 final int mode = mWmService.mAppOps.startOpNoThrow(mAppOp, uid, packageName, true); 2816 if (mode == MODE_ALLOWED || mode == MODE_DEFAULT) { 2817 setAppOpVisibilityLw(true); 2818 } 2819 } 2820 } 2821 hidePermanentlyLw()2822 public void hidePermanentlyLw() { 2823 if (!mPermanentlyHidden) { 2824 mPermanentlyHidden = true; 2825 hideLw(true, true); 2826 } 2827 } 2828 pokeDrawLockLw(long timeout)2829 public void pokeDrawLockLw(long timeout) { 2830 if (isVisibleOrAdding()) { 2831 if (mDrawLock == null) { 2832 // We want the tag name to be somewhat stable so that it is easier to correlate 2833 // in wake lock statistics. So in particular, we don't want to include the 2834 // window's hash code as in toString(). 2835 final CharSequence tag = getWindowTag(); 2836 mDrawLock = mWmService.mPowerManager.newWakeLock(DRAW_WAKE_LOCK, "Window:" + tag); 2837 mDrawLock.setReferenceCounted(false); 2838 mDrawLock.setWorkSource(new WorkSource(mOwnerUid, mAttrs.packageName)); 2839 } 2840 // Each call to acquire resets the timeout. 2841 if (DEBUG_POWER) { 2842 Slog.d(TAG, "pokeDrawLock: poking draw lock on behalf of visible window owned by " 2843 + mAttrs.packageName); 2844 } 2845 mDrawLock.acquire(timeout); 2846 } else if (DEBUG_POWER) { 2847 Slog.d(TAG, "pokeDrawLock: suppressed draw lock request for invisible window " 2848 + "owned by " + mAttrs.packageName); 2849 } 2850 } 2851 2852 @Override isAlive()2853 public boolean isAlive() { 2854 return mClient.asBinder().isBinderAlive(); 2855 } 2856 isClosing()2857 boolean isClosing() { 2858 return mAnimatingExit || (mAppToken != null && mAppToken.isClosingOrEnteringPip()); 2859 } 2860 addWinAnimatorToList(ArrayList<WindowStateAnimator> animators)2861 void addWinAnimatorToList(ArrayList<WindowStateAnimator> animators) { 2862 animators.add(mWinAnimator); 2863 2864 for (int i = mChildren.size() - 1; i >= 0; --i) { 2865 final WindowState c = mChildren.get(i); 2866 c.addWinAnimatorToList(animators); 2867 } 2868 } 2869 sendAppVisibilityToClients()2870 void sendAppVisibilityToClients() { 2871 super.sendAppVisibilityToClients(); 2872 2873 final boolean clientHidden = mAppToken.isClientHidden(); 2874 if (mAttrs.type == TYPE_APPLICATION_STARTING && clientHidden) { 2875 // Don't hide the starting window. 2876 return; 2877 } 2878 2879 if (clientHidden) { 2880 // Once we are notifying the client that it's visibility has changed, we need to prevent 2881 // it from destroying child surfaces until the animation has finished. We do this by 2882 // detaching any surface control the client added from the client. 2883 for (int i = mChildren.size() - 1; i >= 0; --i) { 2884 final WindowState c = mChildren.get(i); 2885 c.mWinAnimator.detachChildren(); 2886 } 2887 2888 mWinAnimator.detachChildren(); 2889 } 2890 2891 try { 2892 if (DEBUG_VISIBILITY) Slog.v(TAG, 2893 "Setting visibility of " + this + ": " + (!clientHidden)); 2894 mClient.dispatchAppVisibility(!clientHidden); 2895 } catch (RemoteException e) { 2896 } 2897 } 2898 onStartFreezingScreen()2899 void onStartFreezingScreen() { 2900 mAppFreezing = true; 2901 for (int i = mChildren.size() - 1; i >= 0; --i) { 2902 final WindowState c = mChildren.get(i); 2903 c.onStartFreezingScreen(); 2904 } 2905 } 2906 onStopFreezingScreen()2907 boolean onStopFreezingScreen() { 2908 boolean unfrozeWindows = false; 2909 for (int i = mChildren.size() - 1; i >= 0; --i) { 2910 final WindowState c = mChildren.get(i); 2911 unfrozeWindows |= c.onStopFreezingScreen(); 2912 } 2913 2914 if (!mAppFreezing) { 2915 return unfrozeWindows; 2916 } 2917 2918 mAppFreezing = false; 2919 2920 if (mHasSurface && !getOrientationChanging() 2921 && mWmService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_TIMEOUT) { 2922 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "set mOrientationChanging of " + this); 2923 setOrientationChanging(true); 2924 mWmService.mRoot.mOrientationChangeComplete = false; 2925 } 2926 mLastFreezeDuration = 0; 2927 setDisplayLayoutNeeded(); 2928 return true; 2929 } 2930 destroySurface(boolean cleanupOnResume, boolean appStopped)2931 boolean destroySurface(boolean cleanupOnResume, boolean appStopped) { 2932 boolean destroyedSomething = false; 2933 2934 // Copying to a different list as multiple children can be removed. 2935 final ArrayList<WindowState> childWindows = new ArrayList<>(mChildren); 2936 for (int i = childWindows.size() - 1; i >= 0; --i) { 2937 final WindowState c = childWindows.get(i); 2938 destroyedSomething |= c.destroySurface(cleanupOnResume, appStopped); 2939 } 2940 2941 if (!(appStopped || mWindowRemovalAllowed || cleanupOnResume)) { 2942 return destroyedSomething; 2943 } 2944 2945 if (appStopped || mWindowRemovalAllowed) { 2946 mWinAnimator.destroyPreservedSurfaceLocked(); 2947 } 2948 2949 if (mDestroying) { 2950 if (DEBUG_ADD_REMOVE) Slog.e(TAG_WM, "win=" + this 2951 + " destroySurfaces: appStopped=" + appStopped 2952 + " win.mWindowRemovalAllowed=" + mWindowRemovalAllowed 2953 + " win.mRemoveOnExit=" + mRemoveOnExit); 2954 if (!cleanupOnResume || mRemoveOnExit) { 2955 destroySurfaceUnchecked(); 2956 } 2957 if (mRemoveOnExit) { 2958 removeImmediately(); 2959 } 2960 if (cleanupOnResume) { 2961 requestUpdateWallpaperIfNeeded(); 2962 } 2963 mDestroying = false; 2964 destroyedSomething = true; 2965 2966 // Since mDestroying will affect AppWindowToken#allDrawn, we need to perform another 2967 // traversal in case we are waiting on this window to start the transition. 2968 if (getDisplayContent().mAppTransition.isTransitionSet() 2969 && getDisplayContent().mOpeningApps.contains(mAppToken)) { 2970 mWmService.mWindowPlacerLocked.requestTraversal(); 2971 } 2972 } 2973 2974 return destroyedSomething; 2975 } 2976 2977 // Destroy or save the application surface without checking 2978 // various indicators of whether the client has released the surface. 2979 // This is in general unsafe, and most callers should use {@link #destroySurface} destroySurfaceUnchecked()2980 void destroySurfaceUnchecked() { 2981 mWinAnimator.destroySurfaceLocked(); 2982 2983 // Clear animating flags now, since the surface is now gone. (Note this is true even 2984 // if the surface is saved, to outside world the surface is still NO_SURFACE.) 2985 mAnimatingExit = false; 2986 } 2987 onSurfaceShownChanged(boolean shown)2988 void onSurfaceShownChanged(boolean shown) { 2989 if (mLastShownChangedReported == shown) { 2990 return; 2991 } 2992 mLastShownChangedReported = shown; 2993 2994 if (shown) { 2995 initExclusionRestrictions(); 2996 } else { 2997 logExclusionRestrictions(EXCLUSION_LEFT); 2998 logExclusionRestrictions(EXCLUSION_RIGHT); 2999 } 3000 } 3001 logExclusionRestrictions(int side)3002 private void logExclusionRestrictions(int side) { 3003 if (!logsGestureExclusionRestrictions(this) 3004 || SystemClock.uptimeMillis() < mLastExclusionLogUptimeMillis[side] 3005 + mWmService.mSystemGestureExclusionLogDebounceTimeoutMillis) { 3006 // Drop the log if we have just logged; this is okay, because what we would have logged 3007 // was true only for a short duration. 3008 return; 3009 } 3010 3011 final long now = SystemClock.uptimeMillis(); 3012 final long duration = now - mLastExclusionLogUptimeMillis[side]; 3013 mLastExclusionLogUptimeMillis[side] = now; 3014 3015 final int requested = mLastRequestedExclusionHeight[side]; 3016 final int granted = mLastGrantedExclusionHeight[side]; 3017 3018 StatsLog.write(StatsLog.EXCLUSION_RECT_STATE_CHANGED, 3019 mAttrs.packageName, requested, requested - granted /* rejected */, 3020 side + 1 /* Sides are 1-indexed in atoms.proto */, 3021 (getConfiguration().orientation == ORIENTATION_LANDSCAPE), 3022 isSplitScreenWindowingMode(getWindowingMode()), (int) duration); 3023 } 3024 initExclusionRestrictions()3025 private void initExclusionRestrictions() { 3026 final long now = SystemClock.uptimeMillis(); 3027 mLastExclusionLogUptimeMillis[EXCLUSION_LEFT] = now; 3028 mLastExclusionLogUptimeMillis[EXCLUSION_RIGHT] = now; 3029 } 3030 3031 @Override isDefaultDisplay()3032 public boolean isDefaultDisplay() { 3033 final DisplayContent displayContent = getDisplayContent(); 3034 if (displayContent == null) { 3035 // Only a window that was on a non-default display can be detached from it. 3036 return false; 3037 } 3038 return displayContent.isDefaultDisplay; 3039 } 3040 setShowToOwnerOnlyLocked(boolean showToOwnerOnly)3041 void setShowToOwnerOnlyLocked(boolean showToOwnerOnly) { 3042 mShowToOwnerOnly = showToOwnerOnly; 3043 } 3044 isHiddenFromUserLocked()3045 private boolean isHiddenFromUserLocked() { 3046 // Child windows are evaluated based on their parent window. 3047 final WindowState win = getTopParentWindow(); 3048 if (win.mAttrs.type < FIRST_SYSTEM_WINDOW 3049 && win.mAppToken != null && win.mAppToken.mShowForAllUsers) { 3050 3051 // All window frames that are fullscreen extend above status bar, but some don't extend 3052 // below navigation bar. Thus, check for display frame for top/left and stable frame for 3053 // bottom right. 3054 if (win.getFrameLw().left <= win.getDisplayFrameLw().left 3055 && win.getFrameLw().top <= win.getDisplayFrameLw().top 3056 && win.getFrameLw().right >= win.getStableFrameLw().right 3057 && win.getFrameLw().bottom >= win.getStableFrameLw().bottom) { 3058 // Is a fullscreen window, like the clock alarm. Show to everyone. 3059 return false; 3060 } 3061 } 3062 3063 return win.mShowToOwnerOnly 3064 && !mWmService.isCurrentProfileLocked(UserHandle.getUserId(win.mOwnerUid)); 3065 } 3066 applyInsets(Region outRegion, Rect frame, Rect inset)3067 private static void applyInsets(Region outRegion, Rect frame, Rect inset) { 3068 outRegion.set( 3069 frame.left + inset.left, frame.top + inset.top, 3070 frame.right - inset.right, frame.bottom - inset.bottom); 3071 } 3072 3073 /** Get the touchable region in global coordinates. */ getTouchableRegion(Region outRegion)3074 void getTouchableRegion(Region outRegion) { 3075 final Rect frame = mWindowFrames.mFrame; 3076 switch (mTouchableInsets) { 3077 default: 3078 case TOUCHABLE_INSETS_FRAME: 3079 outRegion.set(frame); 3080 break; 3081 case TOUCHABLE_INSETS_CONTENT: 3082 applyInsets(outRegion, frame, mGivenContentInsets); 3083 break; 3084 case TOUCHABLE_INSETS_VISIBLE: 3085 applyInsets(outRegion, frame, mGivenVisibleInsets); 3086 break; 3087 case TOUCHABLE_INSETS_REGION: { 3088 outRegion.set(mGivenTouchableRegion); 3089 outRegion.translate(frame.left, frame.top); 3090 break; 3091 } 3092 } 3093 cropRegionToStackBoundsIfNeeded(outRegion); 3094 subtractTouchExcludeRegionIfNeeded(outRegion); 3095 } 3096 3097 /** 3098 * Get the effective touchable region in global coordinates. 3099 * 3100 * In contrast to {@link #getTouchableRegion}, this takes into account 3101 * {@link WindowManager.LayoutParams#FLAG_NOT_TOUCH_MODAL touch modality.} 3102 */ getEffectiveTouchableRegion(Region outRegion)3103 void getEffectiveTouchableRegion(Region outRegion) { 3104 final boolean modal = (mAttrs.flags & (FLAG_NOT_TOUCH_MODAL | FLAG_NOT_FOCUSABLE)) == 0; 3105 final DisplayContent dc = getDisplayContent(); 3106 3107 if (modal && dc != null) { 3108 outRegion.set(dc.getBounds()); 3109 cropRegionToStackBoundsIfNeeded(outRegion); 3110 subtractTouchExcludeRegionIfNeeded(outRegion); 3111 } else { 3112 getTouchableRegion(outRegion); 3113 } 3114 } 3115 setTouchableRegionCropIfNeeded(InputWindowHandle handle)3116 private void setTouchableRegionCropIfNeeded(InputWindowHandle handle) { 3117 final Task task = getTask(); 3118 if (task == null || !task.cropWindowsToStackBounds()) { 3119 return; 3120 } 3121 3122 final TaskStack stack = task.mStack; 3123 if (stack == null) { 3124 return; 3125 } 3126 3127 handle.setTouchableRegionCrop(stack.getSurfaceControl()); 3128 } 3129 cropRegionToStackBoundsIfNeeded(Region region)3130 private void cropRegionToStackBoundsIfNeeded(Region region) { 3131 final Task task = getTask(); 3132 if (task == null || !task.cropWindowsToStackBounds()) { 3133 return; 3134 } 3135 3136 final TaskStack stack = task.mStack; 3137 if (stack == null) { 3138 return; 3139 } 3140 3141 stack.getDimBounds(mTmpRect); 3142 region.op(mTmpRect, Region.Op.INTERSECT); 3143 } 3144 3145 /** 3146 * If this window has areas that cannot be touched, we subtract those areas from its touchable 3147 * region. 3148 */ subtractTouchExcludeRegionIfNeeded(Region touchableRegion)3149 private void subtractTouchExcludeRegionIfNeeded(Region touchableRegion) { 3150 if (mTapExcludeRegionHolder == null) { 3151 return; 3152 } 3153 final Region touchExcludeRegion = Region.obtain(); 3154 amendTapExcludeRegion(touchExcludeRegion); 3155 if (!touchExcludeRegion.isEmpty()) { 3156 touchableRegion.op(touchExcludeRegion, Region.Op.DIFFERENCE); 3157 } 3158 touchExcludeRegion.recycle(); 3159 } 3160 3161 /** 3162 * Report a focus change. Must be called with no locks held, and consistently 3163 * from the same serialized thread (such as dispatched from a handler). 3164 */ reportFocusChangedSerialized(boolean focused, boolean inTouchMode)3165 void reportFocusChangedSerialized(boolean focused, boolean inTouchMode) { 3166 try { 3167 mClient.windowFocusChanged(focused, inTouchMode); 3168 } catch (RemoteException e) { 3169 } 3170 if (mFocusCallbacks != null) { 3171 final int N = mFocusCallbacks.beginBroadcast(); 3172 for (int i=0; i<N; i++) { 3173 IWindowFocusObserver obs = mFocusCallbacks.getBroadcastItem(i); 3174 try { 3175 if (focused) { 3176 obs.focusGained(mWindowId.asBinder()); 3177 } else { 3178 obs.focusLost(mWindowId.asBinder()); 3179 } 3180 } catch (RemoteException e) { 3181 } 3182 } 3183 mFocusCallbacks.finishBroadcast(); 3184 } 3185 } 3186 3187 @Override getConfiguration()3188 public Configuration getConfiguration() { 3189 if (mAppToken != null && mAppToken.mFrozenMergedConfig.size() > 0) { 3190 return mAppToken.mFrozenMergedConfig.peek(); 3191 } 3192 3193 // If the process has not registered to any display to listen to the configuration change, 3194 // we can simply return the mFullConfiguration as default. 3195 if (!registeredForDisplayConfigChanges()) { 3196 return super.getConfiguration(); 3197 } 3198 3199 // We use the process config this window is associated with as the based global config since 3200 // the process can override its config, but isn't part of the window hierarchy. 3201 mTempConfiguration.setTo(getProcessGlobalConfiguration()); 3202 mTempConfiguration.updateFrom(getMergedOverrideConfiguration()); 3203 return mTempConfiguration; 3204 } 3205 3206 /** @return {@code true} if the process registered to a display as a config listener. */ registeredForDisplayConfigChanges()3207 private boolean registeredForDisplayConfigChanges() { 3208 final WindowState parentWindow = getParentWindow(); 3209 final Session session = parentWindow != null ? parentWindow.mSession : mSession; 3210 // System process or invalid process cannot register to display config change. 3211 if (session.mPid == MY_PID || session.mPid < 0) return false; 3212 WindowProcessController app = 3213 mWmService.mAtmService.getProcessController(session.mPid, session.mUid); 3214 if (app == null || !app.registeredForDisplayConfigChanges()) return false; 3215 return true; 3216 } 3217 reportResized()3218 void reportResized() { 3219 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "wm.reportResized_" + getWindowTag()); 3220 try { 3221 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, "Reporting new frame to " + this 3222 + ": " + mWindowFrames.mCompatFrame); 3223 final MergedConfiguration mergedConfiguration = 3224 new MergedConfiguration(mWmService.mRoot.getConfiguration(), 3225 getMergedOverrideConfiguration()); 3226 3227 setLastReportedMergedConfiguration(mergedConfiguration); 3228 3229 if (DEBUG_ORIENTATION && mWinAnimator.mDrawState == DRAW_PENDING) 3230 Slog.i(TAG, "Resizing " + this + " WITH DRAW PENDING"); 3231 3232 final Rect frame = mWindowFrames.mCompatFrame; 3233 final Rect overscanInsets = mWindowFrames.mLastOverscanInsets; 3234 final Rect contentInsets = mWindowFrames.mLastContentInsets; 3235 final Rect visibleInsets = mWindowFrames.mLastVisibleInsets; 3236 final Rect stableInsets = mWindowFrames.mLastStableInsets; 3237 final Rect outsets = mWindowFrames.mLastOutsets; 3238 final boolean reportDraw = mWinAnimator.mDrawState == DRAW_PENDING; 3239 final boolean reportOrientation = mReportOrientationChanged; 3240 final int displayId = getDisplayId(); 3241 final DisplayCutout displayCutout = getWmDisplayCutout().getDisplayCutout(); 3242 if (mAttrs.type != WindowManager.LayoutParams.TYPE_APPLICATION_STARTING 3243 && mClient instanceof IWindow.Stub) { 3244 // To prevent deadlock simulate one-way call if win.mClient is a local object. 3245 mWmService.mH.post(new Runnable() { 3246 @Override 3247 public void run() { 3248 try { 3249 dispatchResized(frame, overscanInsets, contentInsets, visibleInsets, 3250 stableInsets, outsets, reportDraw, mergedConfiguration, 3251 reportOrientation, displayId, displayCutout); 3252 } catch (RemoteException e) { 3253 // Not a remote call, RemoteException won't be raised. 3254 } 3255 } 3256 }); 3257 } else { 3258 dispatchResized(frame, overscanInsets, contentInsets, visibleInsets, stableInsets, 3259 outsets, reportDraw, mergedConfiguration, reportOrientation, displayId, 3260 displayCutout); 3261 } 3262 3263 // TODO (multidisplay): Accessibility supported only for the default display and 3264 // embedded displays 3265 if (mWmService.mAccessibilityController != null && (getDisplayId() == DEFAULT_DISPLAY 3266 || getDisplayContent().getParentWindow() != null)) { 3267 mWmService.mAccessibilityController.onSomeWindowResizedOrMovedLocked(); 3268 } 3269 updateLocationInParentDisplayIfNeeded(); 3270 3271 mWindowFrames.resetInsetsChanged(); 3272 mWinAnimator.mSurfaceResized = false; 3273 mReportOrientationChanged = false; 3274 } catch (RemoteException e) { 3275 setOrientationChanging(false); 3276 mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 3277 - mWmService.mDisplayFreezeTime); 3278 // We are assuming the hosting process is dead or in a zombie state. 3279 Slog.w(TAG, "Failed to report 'resized' to the client of " + this 3280 + ", removing this window."); 3281 mWmService.mPendingRemove.add(this); 3282 mWmService.mWindowPlacerLocked.requestTraversal(); 3283 } 3284 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 3285 } 3286 updateLocationInParentDisplayIfNeeded()3287 void updateLocationInParentDisplayIfNeeded() { 3288 final int embeddedDisplayContentsSize = mEmbeddedDisplayContents.size(); 3289 // If there is any embedded display which is re-parented to this window, we need to 3290 // notify all windows in the embedded display about the location change. 3291 if (embeddedDisplayContentsSize != 0) { 3292 for (int i = embeddedDisplayContentsSize - 1; i >= 0; i--) { 3293 final DisplayContent edc = mEmbeddedDisplayContents.valueAt(i); 3294 edc.notifyLocationInParentDisplayChanged(); 3295 } 3296 } 3297 // If this window is in a embedded display which is re-parented to another window, 3298 // we may need to update its correct on-screen location. 3299 final DisplayContent dc = getDisplayContent(); 3300 if (dc.getParentWindow() == null) { 3301 return; 3302 } 3303 3304 final Point offset = dc.getLocationInParentDisplay(); 3305 if (mLastReportedDisplayOffset.equals(offset)) { 3306 return; 3307 } 3308 3309 mLastReportedDisplayOffset.set(offset.x, offset.y); 3310 try { 3311 mClient.locationInParentDisplayChanged(mLastReportedDisplayOffset); 3312 } catch (RemoteException e) { 3313 Slog.e(TAG, "Failed to update offset from DisplayContent", e); 3314 } 3315 } 3316 3317 /** 3318 * Called when the insets state changed. 3319 */ notifyInsetsChanged()3320 void notifyInsetsChanged() { 3321 try { 3322 mClient.insetsChanged( 3323 getDisplayContent().getInsetsStateController().getInsetsForDispatch(this)); 3324 } catch (RemoteException e) { 3325 Slog.w(TAG, "Failed to deliver inset state change", e); 3326 } 3327 } 3328 notifyInsetsControlChanged()3329 void notifyInsetsControlChanged() { 3330 final InsetsStateController stateController = 3331 getDisplayContent().getInsetsStateController(); 3332 try { 3333 mClient.insetsControlChanged(stateController.getInsetsForDispatch(this), 3334 stateController.getControlsForDispatch(this)); 3335 } catch (RemoteException e) { 3336 Slog.w(TAG, "Failed to deliver inset state change", e); 3337 } 3338 } 3339 getBackdropFrame(Rect frame)3340 Rect getBackdropFrame(Rect frame) { 3341 // When the task is docked, we send fullscreen sized backDropFrame as soon as resizing 3342 // start even if we haven't received the relayout window, so that the client requests 3343 // the relayout sooner. When dragging stops, backDropFrame needs to stay fullscreen 3344 // until the window to small size, otherwise the multithread renderer will shift last 3345 // one or more frame to wrong offset. So here we send fullscreen backdrop if either 3346 // isDragResizing() or isDragResizeChanged() is true. 3347 boolean resizing = isDragResizing() || isDragResizeChanged(); 3348 if (getWindowConfiguration().useWindowFrameForBackdrop() || !resizing) { 3349 // Surface position is now inherited from parent, and BackdropFrameRenderer uses 3350 // backdrop frame to position content. Thus we just keep the size of backdrop frame, and 3351 // remove the offset to avoid double offset from display origin. 3352 mTmpRect.set(frame); 3353 mTmpRect.offsetTo(0, 0); 3354 return mTmpRect; 3355 } 3356 final DisplayInfo displayInfo = getDisplayInfo(); 3357 mTmpRect.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight); 3358 return mTmpRect; 3359 } 3360 getStackId()3361 private int getStackId() { 3362 final TaskStack stack = getStack(); 3363 if (stack == null) { 3364 return INVALID_STACK_ID; 3365 } 3366 return stack.mStackId; 3367 } 3368 dispatchResized(Rect frame, Rect overscanInsets, Rect contentInsets, Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw, MergedConfiguration mergedConfiguration, boolean reportOrientation, int displayId, DisplayCutout displayCutout)3369 private void dispatchResized(Rect frame, Rect overscanInsets, Rect contentInsets, 3370 Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw, 3371 MergedConfiguration mergedConfiguration, boolean reportOrientation, int displayId, 3372 DisplayCutout displayCutout) 3373 throws RemoteException { 3374 final boolean forceRelayout = isDragResizeChanged() || reportOrientation; 3375 3376 mClient.resized(frame, overscanInsets, contentInsets, visibleInsets, stableInsets, outsets, 3377 reportDraw, mergedConfiguration, getBackdropFrame(frame), forceRelayout, 3378 getDisplayContent().getDisplayPolicy().areSystemBarsForcedShownLw(this), displayId, 3379 new DisplayCutout.ParcelableWrapper(displayCutout)); 3380 mDragResizingChangeReported = true; 3381 } 3382 registerFocusObserver(IWindowFocusObserver observer)3383 public void registerFocusObserver(IWindowFocusObserver observer) { 3384 synchronized (mWmService.mGlobalLock) { 3385 if (mFocusCallbacks == null) { 3386 mFocusCallbacks = new RemoteCallbackList<IWindowFocusObserver>(); 3387 } 3388 mFocusCallbacks.register(observer); 3389 } 3390 } 3391 unregisterFocusObserver(IWindowFocusObserver observer)3392 public void unregisterFocusObserver(IWindowFocusObserver observer) { 3393 synchronized (mWmService.mGlobalLock) { 3394 if (mFocusCallbacks != null) { 3395 mFocusCallbacks.unregister(observer); 3396 } 3397 } 3398 } 3399 isFocused()3400 boolean isFocused() { 3401 return getDisplayContent().mCurrentFocus == this; 3402 } 3403 3404 3405 /** Is this window in a container that takes up the entire screen space? */ inAppWindowThatMatchesParentBounds()3406 private boolean inAppWindowThatMatchesParentBounds() { 3407 return mAppToken == null || (mAppToken.matchParentBounds() && !inMultiWindowMode()); 3408 } 3409 3410 /** @return true when the window is in fullscreen mode, but has non-fullscreen bounds set, or 3411 * is transitioning into/out-of fullscreen. */ isLetterboxedAppWindow()3412 boolean isLetterboxedAppWindow() { 3413 return !inMultiWindowMode() && !matchesDisplayBounds() 3414 || isLetterboxedForDisplayCutoutLw(); 3415 } 3416 3417 @Override isLetterboxedForDisplayCutoutLw()3418 public boolean isLetterboxedForDisplayCutoutLw() { 3419 if (mAppToken == null) { 3420 // Only windows with an AppWindowToken are letterboxed. 3421 return false; 3422 } 3423 if (!mWindowFrames.parentFrameWasClippedByDisplayCutout()) { 3424 // Cutout didn't make a difference, no letterbox 3425 return false; 3426 } 3427 if (mAttrs.layoutInDisplayCutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS) { 3428 // Layout in cutout, no letterbox. 3429 return false; 3430 } 3431 if (!mAttrs.isFullscreen()) { 3432 // Not filling the parent frame, no letterbox 3433 return false; 3434 } 3435 // Otherwise we need a letterbox if the layout was smaller than the app window token allowed 3436 // it to be. 3437 return !frameCoversEntireAppTokenBounds(); 3438 } 3439 3440 /** 3441 * @return true if this window covers the entire bounds of its app window token 3442 * @throws NullPointerException if there is no app window token for this window 3443 */ frameCoversEntireAppTokenBounds()3444 private boolean frameCoversEntireAppTokenBounds() { 3445 mTmpRect.set(mAppToken.getBounds()); 3446 mTmpRect.intersectUnchecked(mWindowFrames.mFrame); 3447 return mAppToken.getBounds().equals(mTmpRect); 3448 } 3449 3450 @Override isLetterboxedOverlappingWith(Rect rect)3451 public boolean isLetterboxedOverlappingWith(Rect rect) { 3452 return mAppToken != null && mAppToken.isLetterboxOverlappingWith(rect); 3453 } 3454 isDragResizeChanged()3455 boolean isDragResizeChanged() { 3456 return mDragResizing != computeDragResizing(); 3457 } 3458 3459 @Override setWaitingForDrawnIfResizingChanged()3460 void setWaitingForDrawnIfResizingChanged() { 3461 if (isDragResizeChanged()) { 3462 mWmService.mWaitingForDrawn.add(this); 3463 } 3464 super.setWaitingForDrawnIfResizingChanged(); 3465 } 3466 3467 /** 3468 * @return Whether we reported a drag resize change to the application or not already. 3469 */ isDragResizingChangeReported()3470 private boolean isDragResizingChangeReported() { 3471 return mDragResizingChangeReported; 3472 } 3473 3474 /** 3475 * Resets the state whether we reported a drag resize change to the app. 3476 */ 3477 @Override resetDragResizingChangeReported()3478 void resetDragResizingChangeReported() { 3479 mDragResizingChangeReported = false; 3480 super.resetDragResizingChangeReported(); 3481 } 3482 getResizeMode()3483 int getResizeMode() { 3484 return mResizeMode; 3485 } 3486 computeDragResizing()3487 private boolean computeDragResizing() { 3488 final Task task = getTask(); 3489 if (task == null) { 3490 return false; 3491 } 3492 if (!inSplitScreenWindowingMode() && !inFreeformWindowingMode()) { 3493 return false; 3494 } 3495 if (mAttrs.width != MATCH_PARENT || mAttrs.height != MATCH_PARENT) { 3496 // Floating windows never enter drag resize mode. 3497 return false; 3498 } 3499 if (task.isDragResizing()) { 3500 return true; 3501 } 3502 3503 // If the bounds are currently frozen, it means that the layout size that the app sees 3504 // and the bounds we clip this window to might be different. In order to avoid holes, we 3505 // simulate that we are still resizing so the app fills the hole with the resizing 3506 // background. 3507 return (getDisplayContent().mDividerControllerLocked.isResizing() 3508 || mAppToken != null && !mAppToken.mFrozenBounds.isEmpty()) && 3509 !task.inFreeformWindowingMode() && !isGoneForLayoutLw(); 3510 3511 } 3512 setDragResizing()3513 void setDragResizing() { 3514 final boolean resizing = computeDragResizing(); 3515 if (resizing == mDragResizing) { 3516 return; 3517 } 3518 mDragResizing = resizing; 3519 final Task task = getTask(); 3520 if (task != null && task.isDragResizing()) { 3521 mResizeMode = task.getDragResizeMode(); 3522 } else { 3523 mResizeMode = mDragResizing && getDisplayContent().mDividerControllerLocked.isResizing() 3524 ? DRAG_RESIZE_MODE_DOCKED_DIVIDER 3525 : DRAG_RESIZE_MODE_FREEFORM; 3526 } 3527 } 3528 isDragResizing()3529 boolean isDragResizing() { 3530 return mDragResizing; 3531 } 3532 isDockedResizing()3533 boolean isDockedResizing() { 3534 return (mDragResizing && getResizeMode() == DRAG_RESIZE_MODE_DOCKED_DIVIDER) 3535 || (isChildWindow() && getParentWindow().isDockedResizing()); 3536 } 3537 3538 @CallSuper 3539 @Override writeToProto(ProtoOutputStream proto, long fieldId, @WindowTraceLogLevel int logLevel)3540 public void writeToProto(ProtoOutputStream proto, long fieldId, 3541 @WindowTraceLogLevel int logLevel) { 3542 boolean isVisible = isVisible(); 3543 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible) { 3544 return; 3545 } 3546 3547 final long token = proto.start(fieldId); 3548 super.writeToProto(proto, WINDOW_CONTAINER, logLevel); 3549 writeIdentifierToProto(proto, IDENTIFIER); 3550 proto.write(DISPLAY_ID, getDisplayId()); 3551 proto.write(STACK_ID, getStackId()); 3552 mAttrs.writeToProto(proto, ATTRIBUTES); 3553 mGivenContentInsets.writeToProto(proto, GIVEN_CONTENT_INSETS); 3554 mWindowFrames.writeToProto(proto, WINDOW_FRAMES); 3555 mAttrs.surfaceInsets.writeToProto(proto, SURFACE_INSETS); 3556 mSurfacePosition.writeToProto(proto, SURFACE_POSITION); 3557 mWinAnimator.writeToProto(proto, ANIMATOR); 3558 proto.write(ANIMATING_EXIT, mAnimatingExit); 3559 for (int i = 0; i < mChildren.size(); i++) { 3560 mChildren.get(i).writeToProto(proto, CHILD_WINDOWS, logLevel); 3561 } 3562 proto.write(REQUESTED_WIDTH, mRequestedWidth); 3563 proto.write(REQUESTED_HEIGHT, mRequestedHeight); 3564 proto.write(VIEW_VISIBILITY, mViewVisibility); 3565 proto.write(SYSTEM_UI_VISIBILITY, mSystemUiVisibility); 3566 proto.write(HAS_SURFACE, mHasSurface); 3567 proto.write(IS_READY_FOR_DISPLAY, isReadyForDisplay()); 3568 proto.write(REMOVE_ON_EXIT, mRemoveOnExit); 3569 proto.write(DESTROYING, mDestroying); 3570 proto.write(REMOVED, mRemoved); 3571 proto.write(IS_ON_SCREEN, isOnScreen()); 3572 proto.write(IS_VISIBLE, isVisible); 3573 proto.write(PENDING_SEAMLESS_ROTATION, mPendingSeamlessRotate != null); 3574 proto.write(FINISHED_SEAMLESS_ROTATION_FRAME, mFinishSeamlessRotateFrameNumber); 3575 proto.write(FORCE_SEAMLESS_ROTATION, mForceSeamlesslyRotate); 3576 proto.end(token); 3577 } 3578 3579 @Override writeIdentifierToProto(ProtoOutputStream proto, long fieldId)3580 public void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) { 3581 final long token = proto.start(fieldId); 3582 proto.write(HASH_CODE, System.identityHashCode(this)); 3583 proto.write(USER_ID, UserHandle.getUserId(mOwnerUid)); 3584 final CharSequence title = getWindowTag(); 3585 if (title != null) { 3586 proto.write(TITLE, title.toString()); 3587 } 3588 proto.end(token); 3589 } 3590 3591 @Override dump(PrintWriter pw, String prefix, boolean dumpAll)3592 void dump(PrintWriter pw, String prefix, boolean dumpAll) { 3593 final TaskStack stack = getStack(); 3594 pw.print(prefix + "mDisplayId=" + getDisplayId()); 3595 if (stack != null) { 3596 pw.print(" stackId=" + stack.mStackId); 3597 } 3598 pw.println(" mSession=" + mSession 3599 + " mClient=" + mClient.asBinder()); 3600 pw.println(prefix + "mOwnerUid=" + mOwnerUid 3601 + " mShowToOwnerOnly=" + mShowToOwnerOnly 3602 + " package=" + mAttrs.packageName 3603 + " appop=" + AppOpsManager.opToName(mAppOp)); 3604 pw.println(prefix + "mAttrs=" + mAttrs.toString(prefix)); 3605 pw.println(prefix + "Requested w=" + mRequestedWidth 3606 + " h=" + mRequestedHeight 3607 + " mLayoutSeq=" + mLayoutSeq); 3608 if (mRequestedWidth != mLastRequestedWidth || mRequestedHeight != mLastRequestedHeight) { 3609 pw.println(prefix + "LastRequested w=" + mLastRequestedWidth 3610 + " h=" + mLastRequestedHeight); 3611 } 3612 if (mIsChildWindow || mLayoutAttached) { 3613 pw.println(prefix + "mParentWindow=" + getParentWindow() 3614 + " mLayoutAttached=" + mLayoutAttached); 3615 } 3616 if (mIsImWindow || mIsWallpaper || mIsFloatingLayer) { 3617 pw.println(prefix + "mIsImWindow=" + mIsImWindow 3618 + " mIsWallpaper=" + mIsWallpaper 3619 + " mIsFloatingLayer=" + mIsFloatingLayer 3620 + " mWallpaperVisible=" + mWallpaperVisible); 3621 } 3622 if (dumpAll) { 3623 pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer); 3624 pw.print(" mSubLayer="); pw.print(mSubLayer); 3625 } 3626 if (dumpAll) { 3627 pw.println(prefix + "mToken=" + mToken); 3628 if (mAppToken != null) { 3629 pw.println(prefix + "mAppToken=" + mAppToken); 3630 pw.print(prefix + "mAppDied=" + mAppDied); 3631 pw.print(prefix + "drawnStateEvaluated=" + getDrawnStateEvaluated()); 3632 pw.println(prefix + "mightAffectAllDrawn=" + mightAffectAllDrawn()); 3633 } 3634 pw.println(prefix + "mViewVisibility=0x" + Integer.toHexString(mViewVisibility) 3635 + " mHaveFrame=" + mHaveFrame 3636 + " mObscured=" + mObscured); 3637 pw.println(prefix + "mSeq=" + mSeq 3638 + " mSystemUiVisibility=0x" + Integer.toHexString(mSystemUiVisibility)); 3639 } 3640 if (!isVisibleByPolicy() || !mLegacyPolicyVisibilityAfterAnim || !mAppOpVisibility 3641 || isParentWindowHidden() || mPermanentlyHidden || mForceHideNonSystemOverlayWindow 3642 || mHiddenWhileSuspended) { 3643 pw.println(prefix + "mPolicyVisibility=" + isVisibleByPolicy() 3644 + " mLegacyPolicyVisibilityAfterAnim=" + mLegacyPolicyVisibilityAfterAnim 3645 + " mAppOpVisibility=" + mAppOpVisibility 3646 + " parentHidden=" + isParentWindowHidden() 3647 + " mPermanentlyHidden=" + mPermanentlyHidden 3648 + " mHiddenWhileSuspended=" + mHiddenWhileSuspended 3649 + " mForceHideNonSystemOverlayWindow=" + mForceHideNonSystemOverlayWindow); 3650 } 3651 if (!mRelayoutCalled || mLayoutNeeded) { 3652 pw.println(prefix + "mRelayoutCalled=" + mRelayoutCalled 3653 + " mLayoutNeeded=" + mLayoutNeeded); 3654 } 3655 if (dumpAll) { 3656 pw.println(prefix + "mGivenContentInsets=" + mGivenContentInsets.toShortString(sTmpSB) 3657 + " mGivenVisibleInsets=" + mGivenVisibleInsets.toShortString(sTmpSB)); 3658 if (mTouchableInsets != 0 || mGivenInsetsPending) { 3659 pw.println(prefix + "mTouchableInsets=" + mTouchableInsets 3660 + " mGivenInsetsPending=" + mGivenInsetsPending); 3661 Region region = new Region(); 3662 getTouchableRegion(region); 3663 pw.println(prefix + "touchable region=" + region); 3664 } 3665 pw.println(prefix + "mFullConfiguration=" + getConfiguration()); 3666 pw.println(prefix + "mLastReportedConfiguration=" + getLastReportedConfiguration()); 3667 } 3668 pw.println(prefix + "mHasSurface=" + mHasSurface 3669 + " isReadyForDisplay()=" + isReadyForDisplay() 3670 + " mWindowRemovalAllowed=" + mWindowRemovalAllowed); 3671 if (inSizeCompatMode()) { 3672 pw.println(prefix + "mCompatFrame=" + mWindowFrames.mCompatFrame.toShortString(sTmpSB)); 3673 } 3674 if (dumpAll) { 3675 mWindowFrames.dump(pw, prefix); 3676 pw.println(prefix + " surface=" + mAttrs.surfaceInsets.toShortString(sTmpSB)); 3677 } 3678 super.dump(pw, prefix, dumpAll); 3679 pw.println(prefix + mWinAnimator + ":"); 3680 mWinAnimator.dump(pw, prefix + " ", dumpAll); 3681 if (mAnimatingExit || mRemoveOnExit || mDestroying || mRemoved) { 3682 pw.println(prefix + "mAnimatingExit=" + mAnimatingExit 3683 + " mRemoveOnExit=" + mRemoveOnExit 3684 + " mDestroying=" + mDestroying 3685 + " mRemoved=" + mRemoved); 3686 } 3687 if (getOrientationChanging() || mAppFreezing || mReportOrientationChanged) { 3688 pw.println(prefix + "mOrientationChanging=" + mOrientationChanging 3689 + " configOrientationChanging=" 3690 + (getLastReportedConfiguration().orientation != getConfiguration().orientation) 3691 + " mAppFreezing=" + mAppFreezing 3692 + " mReportOrientationChanged=" + mReportOrientationChanged); 3693 } 3694 if (mLastFreezeDuration != 0) { 3695 pw.print(prefix + "mLastFreezeDuration="); 3696 TimeUtils.formatDuration(mLastFreezeDuration, pw); 3697 pw.println(); 3698 } 3699 pw.print(prefix + "mForceSeamlesslyRotate=" + mForceSeamlesslyRotate 3700 + " seamlesslyRotate: pending="); 3701 if (mPendingSeamlessRotate != null) { 3702 mPendingSeamlessRotate.dump(pw); 3703 } else { 3704 pw.print("null"); 3705 } 3706 pw.println(" finishedFrameNumber=" + mFinishSeamlessRotateFrameNumber); 3707 3708 if (mHScale != 1 || mVScale != 1) { 3709 pw.println(prefix + "mHScale=" + mHScale 3710 + " mVScale=" + mVScale); 3711 } 3712 if (mWallpaperX != -1 || mWallpaperY != -1) { 3713 pw.println(prefix + "mWallpaperX=" + mWallpaperX 3714 + " mWallpaperY=" + mWallpaperY); 3715 } 3716 if (mWallpaperXStep != -1 || mWallpaperYStep != -1) { 3717 pw.println(prefix + "mWallpaperXStep=" + mWallpaperXStep 3718 + " mWallpaperYStep=" + mWallpaperYStep); 3719 } 3720 if (mWallpaperDisplayOffsetX != Integer.MIN_VALUE 3721 || mWallpaperDisplayOffsetY != Integer.MIN_VALUE) { 3722 pw.println(prefix + "mWallpaperDisplayOffsetX=" + mWallpaperDisplayOffsetX 3723 + " mWallpaperDisplayOffsetY=" + mWallpaperDisplayOffsetY); 3724 } 3725 if (mDrawLock != null) { 3726 pw.println(prefix + "mDrawLock=" + mDrawLock); 3727 } 3728 if (isDragResizing()) { 3729 pw.println(prefix + "isDragResizing=" + isDragResizing()); 3730 } 3731 if (computeDragResizing()) { 3732 pw.println(prefix + "computeDragResizing=" + computeDragResizing()); 3733 } 3734 pw.println(prefix + "isOnScreen=" + isOnScreen()); 3735 pw.println(prefix + "isVisible=" + isVisible()); 3736 pw.println(prefix + "mEmbeddedDisplayContents=" + mEmbeddedDisplayContents); 3737 } 3738 3739 @Override getName()3740 String getName() { 3741 return Integer.toHexString(System.identityHashCode(this)) 3742 + " " + getWindowTag(); 3743 } 3744 getWindowTag()3745 CharSequence getWindowTag() { 3746 CharSequence tag = mAttrs.getTitle(); 3747 if (tag == null || tag.length() <= 0) { 3748 tag = mAttrs.packageName; 3749 } 3750 return tag; 3751 } 3752 3753 @Override toString()3754 public String toString() { 3755 final CharSequence title = getWindowTag(); 3756 if (mStringNameCache == null || mLastTitle != title || mWasExiting != mAnimatingExit) { 3757 mLastTitle = title; 3758 mWasExiting = mAnimatingExit; 3759 mStringNameCache = "Window{" + Integer.toHexString(System.identityHashCode(this)) 3760 + " u" + UserHandle.getUserId(mOwnerUid) 3761 + " " + mLastTitle + (mAnimatingExit ? " EXITING}" : "}"); 3762 } 3763 return mStringNameCache; 3764 } 3765 transformClipRectFromScreenToSurfaceSpace(Rect clipRect)3766 void transformClipRectFromScreenToSurfaceSpace(Rect clipRect) { 3767 if (mHScale == 1 && mVScale == 1) { 3768 return; 3769 } 3770 if (mHScale >= 0) { 3771 clipRect.left = (int) (clipRect.left / mHScale); 3772 clipRect.right = (int) Math.ceil(clipRect.right / mHScale); 3773 } 3774 if (mVScale >= 0) { 3775 clipRect.top = (int) (clipRect.top / mVScale); 3776 clipRect.bottom = (int) Math.ceil(clipRect.bottom / mVScale); 3777 } 3778 } 3779 applyGravityAndUpdateFrame(Rect containingFrame, Rect displayFrame)3780 private void applyGravityAndUpdateFrame(Rect containingFrame, Rect displayFrame) { 3781 final int pw = containingFrame.width(); 3782 final int ph = containingFrame.height(); 3783 final Task task = getTask(); 3784 final boolean inNonFullscreenContainer = !inAppWindowThatMatchesParentBounds(); 3785 final boolean noLimits = (mAttrs.flags & FLAG_LAYOUT_NO_LIMITS) != 0; 3786 3787 // We need to fit it to the display if either 3788 // a) The window is in a fullscreen container, or we don't have a task (we assume fullscreen 3789 // for the taskless windows) 3790 // b) If it's a secondary app window, we also need to fit it to the display unless 3791 // FLAG_LAYOUT_NO_LIMITS is set. This is so we place Popups, dialogs, and similar windows on 3792 // screen, but SurfaceViews want to be always at a specific location so we don't fit it to 3793 // the display. 3794 final boolean fitToDisplay = (task == null || !inNonFullscreenContainer) 3795 || ((mAttrs.type != TYPE_BASE_APPLICATION) && !noLimits); 3796 float x, y; 3797 int w,h; 3798 3799 final boolean inSizeCompatMode = inSizeCompatMode(); 3800 if ((mAttrs.flags & FLAG_SCALED) != 0) { 3801 if (mAttrs.width < 0) { 3802 w = pw; 3803 } else if (inSizeCompatMode) { 3804 w = (int)(mAttrs.width * mGlobalScale + .5f); 3805 } else { 3806 w = mAttrs.width; 3807 } 3808 if (mAttrs.height < 0) { 3809 h = ph; 3810 } else if (inSizeCompatMode) { 3811 h = (int)(mAttrs.height * mGlobalScale + .5f); 3812 } else { 3813 h = mAttrs.height; 3814 } 3815 } else { 3816 if (mAttrs.width == MATCH_PARENT) { 3817 w = pw; 3818 } else if (inSizeCompatMode) { 3819 w = (int)(mRequestedWidth * mGlobalScale + .5f); 3820 } else { 3821 w = mRequestedWidth; 3822 } 3823 if (mAttrs.height == MATCH_PARENT) { 3824 h = ph; 3825 } else if (inSizeCompatMode) { 3826 h = (int)(mRequestedHeight * mGlobalScale + .5f); 3827 } else { 3828 h = mRequestedHeight; 3829 } 3830 } 3831 3832 if (inSizeCompatMode) { 3833 x = mAttrs.x * mGlobalScale; 3834 y = mAttrs.y * mGlobalScale; 3835 } else { 3836 x = mAttrs.x; 3837 y = mAttrs.y; 3838 } 3839 3840 if (inNonFullscreenContainer && !layoutInParentFrame()) { 3841 // Make sure window fits in containing frame since it is in a non-fullscreen task as 3842 // required by {@link Gravity#apply} call. 3843 w = Math.min(w, pw); 3844 h = Math.min(h, ph); 3845 } 3846 3847 // Set mFrame 3848 Gravity.apply(mAttrs.gravity, w, h, containingFrame, 3849 (int) (x + mAttrs.horizontalMargin * pw), 3850 (int) (y + mAttrs.verticalMargin * ph), mWindowFrames.mFrame); 3851 3852 // Now make sure the window fits in the overall display frame. 3853 if (fitToDisplay) { 3854 Gravity.applyDisplay(mAttrs.gravity, displayFrame, mWindowFrames.mFrame); 3855 } 3856 3857 // We need to make sure we update the CompatFrame as it is used for 3858 // cropping decisions, etc, on systems where we lack a decor layer. 3859 mWindowFrames.mCompatFrame.set(mWindowFrames.mFrame); 3860 if (inSizeCompatMode) { 3861 // See comparable block in computeFrameLw. 3862 mWindowFrames.mCompatFrame.scale(mInvGlobalScale); 3863 } 3864 } 3865 isChildWindow()3866 boolean isChildWindow() { 3867 return mIsChildWindow; 3868 } 3869 layoutInParentFrame()3870 boolean layoutInParentFrame() { 3871 return mIsChildWindow 3872 && (mAttrs.privateFlags & PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME) != 0; 3873 } 3874 3875 /** 3876 * Returns true if any window added by an application process that if of type 3877 * {@link android.view.WindowManager.LayoutParams#TYPE_TOAST} or that requires that requires 3878 * {@link android.app.AppOpsManager#OP_SYSTEM_ALERT_WINDOW} permission should be hidden when 3879 * this window is visible. 3880 */ hideNonSystemOverlayWindowsWhenVisible()3881 boolean hideNonSystemOverlayWindowsWhenVisible() { 3882 return (mAttrs.privateFlags & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0 3883 && mSession.mCanHideNonSystemOverlayWindows; 3884 } 3885 3886 /** Returns the parent window if this is a child of another window, else null. */ getParentWindow()3887 WindowState getParentWindow() { 3888 // NOTE: We are not calling getParent() directly as the WindowState might be a child of a 3889 // WindowContainer that isn't a WindowState. 3890 return (mIsChildWindow) ? ((WindowState) super.getParent()) : null; 3891 } 3892 3893 /** Returns the topmost parent window if this is a child of another window, else this. */ getTopParentWindow()3894 WindowState getTopParentWindow() { 3895 WindowState current = this; 3896 WindowState topParent = current; 3897 while (current != null && current.mIsChildWindow) { 3898 current = current.getParentWindow(); 3899 // Parent window can be null if the child is detached from it's parent already, but 3900 // someone still has a reference to access it. So, we return the top parent value we 3901 // already have instead of null. 3902 if (current != null) { 3903 topParent = current; 3904 } 3905 } 3906 return topParent; 3907 } 3908 isParentWindowHidden()3909 boolean isParentWindowHidden() { 3910 final WindowState parent = getParentWindow(); 3911 return parent != null && parent.mHidden; 3912 } 3913 isParentWindowGoneForLayout()3914 private boolean isParentWindowGoneForLayout() { 3915 final WindowState parent = getParentWindow(); 3916 return parent != null && parent.isGoneForLayoutLw(); 3917 } 3918 setWillReplaceWindow(boolean animate)3919 void setWillReplaceWindow(boolean animate) { 3920 for (int i = mChildren.size() - 1; i >= 0; i--) { 3921 final WindowState c = mChildren.get(i); 3922 c.setWillReplaceWindow(animate); 3923 } 3924 3925 if ((mAttrs.privateFlags & PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH) != 0 3926 || mAttrs.type == TYPE_APPLICATION_STARTING) { 3927 // We don't set replacing on starting windows since they are added by window manager and 3928 // not the client so won't be replaced by the client. 3929 return; 3930 } 3931 3932 mWillReplaceWindow = true; 3933 mReplacementWindow = null; 3934 mAnimateReplacingWindow = animate; 3935 } 3936 clearWillReplaceWindow()3937 void clearWillReplaceWindow() { 3938 mWillReplaceWindow = false; 3939 mReplacementWindow = null; 3940 mAnimateReplacingWindow = false; 3941 3942 for (int i = mChildren.size() - 1; i >= 0; i--) { 3943 final WindowState c = mChildren.get(i); 3944 c.clearWillReplaceWindow(); 3945 } 3946 } 3947 waitingForReplacement()3948 boolean waitingForReplacement() { 3949 if (mWillReplaceWindow) { 3950 return true; 3951 } 3952 3953 for (int i = mChildren.size() - 1; i >= 0; i--) { 3954 final WindowState c = mChildren.get(i); 3955 if (c.waitingForReplacement()) { 3956 return true; 3957 } 3958 } 3959 return false; 3960 } 3961 requestUpdateWallpaperIfNeeded()3962 void requestUpdateWallpaperIfNeeded() { 3963 final DisplayContent dc = getDisplayContent(); 3964 if (dc != null && (mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) { 3965 dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 3966 dc.setLayoutNeeded(); 3967 mWmService.mWindowPlacerLocked.requestTraversal(); 3968 } 3969 3970 for (int i = mChildren.size() - 1; i >= 0; i--) { 3971 final WindowState c = mChildren.get(i); 3972 c.requestUpdateWallpaperIfNeeded(); 3973 } 3974 } 3975 translateToWindowX(float x)3976 float translateToWindowX(float x) { 3977 float winX = x - mWindowFrames.mFrame.left; 3978 if (inSizeCompatMode()) { 3979 winX *= mGlobalScale; 3980 } 3981 return winX; 3982 } 3983 translateToWindowY(float y)3984 float translateToWindowY(float y) { 3985 float winY = y - mWindowFrames.mFrame.top; 3986 if (inSizeCompatMode()) { 3987 winY *= mGlobalScale; 3988 } 3989 return winY; 3990 } 3991 3992 // During activity relaunch due to resize, we sometimes use window replacement 3993 // for only child windows (as the main window is handled by window preservation) 3994 // and the big surface. 3995 // 3996 // Though windows of TYPE_APPLICATION or TYPE_DRAWN_APPLICATION (as opposed to 3997 // TYPE_BASE_APPLICATION) are not children in the sense of an attached window, 3998 // we also want to replace them at such phases, as they won't be covered by window 3999 // preservation, and in general we expect them to return following relaunch. shouldBeReplacedWithChildren()4000 boolean shouldBeReplacedWithChildren() { 4001 return mIsChildWindow || mAttrs.type == TYPE_APPLICATION 4002 || mAttrs.type == TYPE_DRAWN_APPLICATION; 4003 } 4004 setWillReplaceChildWindows()4005 void setWillReplaceChildWindows() { 4006 if (shouldBeReplacedWithChildren()) { 4007 setWillReplaceWindow(false /* animate */); 4008 } 4009 for (int i = mChildren.size() - 1; i >= 0; i--) { 4010 final WindowState c = mChildren.get(i); 4011 c.setWillReplaceChildWindows(); 4012 } 4013 } 4014 getReplacingWindow()4015 WindowState getReplacingWindow() { 4016 if (mAnimatingExit && mWillReplaceWindow && mAnimateReplacingWindow) { 4017 return this; 4018 } 4019 for (int i = mChildren.size() - 1; i >= 0; i--) { 4020 final WindowState c = mChildren.get(i); 4021 final WindowState replacing = c.getReplacingWindow(); 4022 if (replacing != null) { 4023 return replacing; 4024 } 4025 } 4026 return null; 4027 } 4028 4029 @Override getRotationAnimationHint()4030 public int getRotationAnimationHint() { 4031 if (mAppToken != null) { 4032 return mAppToken.mRotationAnimationHint; 4033 } else { 4034 return -1; 4035 } 4036 } 4037 4038 @Override isInputMethodWindow()4039 public boolean isInputMethodWindow() { 4040 return mIsImWindow; 4041 } 4042 4043 // This must be called while inside a transaction. performShowLocked()4044 boolean performShowLocked() { 4045 if (isHiddenFromUserLocked()) { 4046 if (DEBUG_VISIBILITY) Slog.w(TAG, "hiding " + this + ", belonging to " + mOwnerUid); 4047 clearPolicyVisibilityFlag(VISIBLE_FOR_USER); 4048 return false; 4049 } 4050 4051 logPerformShow("performShow on "); 4052 4053 final int drawState = mWinAnimator.mDrawState; 4054 if ((drawState == HAS_DRAWN || drawState == READY_TO_SHOW) 4055 && mAttrs.type != TYPE_APPLICATION_STARTING && mAppToken != null) { 4056 mAppToken.onFirstWindowDrawn(this, mWinAnimator); 4057 } 4058 4059 if (mWinAnimator.mDrawState != READY_TO_SHOW || !isReadyForDisplay()) { 4060 return false; 4061 } 4062 4063 logPerformShow("Showing "); 4064 4065 mWmService.enableScreenIfNeededLocked(); 4066 mWinAnimator.applyEnterAnimationLocked(); 4067 4068 // Force the show in the next prepareSurfaceLocked() call. 4069 mWinAnimator.mLastAlpha = -1; 4070 if (DEBUG_ANIM) Slog.v(TAG, 4071 "performShowLocked: mDrawState=HAS_DRAWN in " + this); 4072 mWinAnimator.mDrawState = HAS_DRAWN; 4073 mWmService.scheduleAnimationLocked(); 4074 4075 if (mHidden) { 4076 mHidden = false; 4077 final DisplayContent displayContent = getDisplayContent(); 4078 4079 for (int i = mChildren.size() - 1; i >= 0; --i) { 4080 final WindowState c = mChildren.get(i); 4081 if (c.mWinAnimator.mSurfaceController != null) { 4082 c.performShowLocked(); 4083 // It hadn't been shown, which means layout not performed on it, so now we 4084 // want to make sure to do a layout. If called from within the transaction 4085 // loop, this will cause it to restart with a new layout. 4086 if (displayContent != null) { 4087 displayContent.setLayoutNeeded(); 4088 } 4089 } 4090 } 4091 } 4092 4093 if (mAttrs.type == TYPE_INPUT_METHOD) { 4094 getDisplayContent().mDividerControllerLocked.resetImeHideRequested(); 4095 } 4096 4097 return true; 4098 } 4099 logPerformShow(String prefix)4100 private void logPerformShow(String prefix) { 4101 if (DEBUG_VISIBILITY 4102 || (DEBUG_STARTING_WINDOW_VERBOSE && mAttrs.type == TYPE_APPLICATION_STARTING)) { 4103 Slog.v(TAG, prefix + this 4104 + ": mDrawState=" + mWinAnimator.drawStateToString() 4105 + " readyForDisplay=" + isReadyForDisplay() 4106 + " starting=" + (mAttrs.type == TYPE_APPLICATION_STARTING) 4107 + " during animation: policyVis=" + isVisibleByPolicy() 4108 + " parentHidden=" + isParentWindowHidden() 4109 + " tok.hiddenRequested=" 4110 + (mAppToken != null && mAppToken.hiddenRequested) 4111 + " tok.hidden=" + (mAppToken != null && mAppToken.isHidden()) 4112 + " animating=" + isAnimating() 4113 + " tok animating=" 4114 + (mAppToken != null && mAppToken.isSelfAnimating()) 4115 + " Callers=" + Debug.getCallers(4)); 4116 } 4117 } 4118 getWindowInfo()4119 WindowInfo getWindowInfo() { 4120 WindowInfo windowInfo = WindowInfo.obtain(); 4121 windowInfo.type = mAttrs.type; 4122 windowInfo.layer = mLayer; 4123 windowInfo.token = mClient.asBinder(); 4124 if (mAppToken != null) { 4125 windowInfo.activityToken = mAppToken.appToken.asBinder(); 4126 } 4127 windowInfo.title = mAttrs.accessibilityTitle; 4128 // Panel windows have no public way to set the a11y title directly. Use the 4129 // regular title as a fallback. 4130 final boolean isPanelWindow = (mAttrs.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW) 4131 && (mAttrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW); 4132 // Accessibility overlays should have titles that work for accessibility, and can't set 4133 // the a11y title themselves. 4134 final boolean isAccessibilityOverlay = 4135 windowInfo.type == WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY; 4136 if (TextUtils.isEmpty(windowInfo.title) && (isPanelWindow || isAccessibilityOverlay)) { 4137 final CharSequence title = mAttrs.getTitle(); 4138 windowInfo.title = TextUtils.isEmpty(title) ? null : title; 4139 } 4140 windowInfo.accessibilityIdOfAnchor = mAttrs.accessibilityIdOfAnchor; 4141 windowInfo.focused = isFocused(); 4142 Task task = getTask(); 4143 windowInfo.inPictureInPicture = (task != null) && task.inPinnedWindowingMode(); 4144 windowInfo.hasFlagWatchOutsideTouch = 4145 (mAttrs.flags & WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH) != 0; 4146 4147 if (mIsChildWindow) { 4148 windowInfo.parentToken = getParentWindow().mClient.asBinder(); 4149 } 4150 4151 final int childCount = mChildren.size(); 4152 if (childCount > 0) { 4153 if (windowInfo.childTokens == null) { 4154 windowInfo.childTokens = new ArrayList(childCount); 4155 } 4156 for (int j = 0; j < childCount; j++) { 4157 final WindowState child = mChildren.get(j); 4158 windowInfo.childTokens.add(child.mClient.asBinder()); 4159 } 4160 } 4161 return windowInfo; 4162 } 4163 4164 @Override forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)4165 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) { 4166 if (mChildren.isEmpty()) { 4167 // The window has no children so we just return it. 4168 return applyInOrderWithImeWindows(callback, traverseTopToBottom); 4169 } 4170 4171 if (traverseTopToBottom) { 4172 return forAllWindowTopToBottom(callback); 4173 } else { 4174 return forAllWindowBottomToTop(callback); 4175 } 4176 } 4177 forAllWindowBottomToTop(ToBooleanFunction<WindowState> callback)4178 private boolean forAllWindowBottomToTop(ToBooleanFunction<WindowState> callback) { 4179 // We want to consume the negative sublayer children first because they need to appear 4180 // below the parent, then this window (the parent), and then the positive sublayer children 4181 // because they need to appear above the parent. 4182 int i = 0; 4183 final int count = mChildren.size(); 4184 WindowState child = mChildren.get(i); 4185 4186 while (i < count && child.mSubLayer < 0) { 4187 if (child.applyInOrderWithImeWindows(callback, false /* traverseTopToBottom */)) { 4188 return true; 4189 } 4190 i++; 4191 if (i >= count) { 4192 break; 4193 } 4194 child = mChildren.get(i); 4195 } 4196 4197 if (applyInOrderWithImeWindows(callback, false /* traverseTopToBottom */)) { 4198 return true; 4199 } 4200 4201 while (i < count) { 4202 if (child.applyInOrderWithImeWindows(callback, false /* traverseTopToBottom */)) { 4203 return true; 4204 } 4205 i++; 4206 if (i >= count) { 4207 break; 4208 } 4209 child = mChildren.get(i); 4210 } 4211 4212 return false; 4213 } 4214 forAllWindowTopToBottom(ToBooleanFunction<WindowState> callback)4215 private boolean forAllWindowTopToBottom(ToBooleanFunction<WindowState> callback) { 4216 // We want to consume the positive sublayer children first because they need to appear 4217 // above the parent, then this window (the parent), and then the negative sublayer children 4218 // because they need to appear above the parent. 4219 int i = mChildren.size() - 1; 4220 WindowState child = mChildren.get(i); 4221 4222 while (i >= 0 && child.mSubLayer >= 0) { 4223 if (child.applyInOrderWithImeWindows(callback, true /* traverseTopToBottom */)) { 4224 return true; 4225 } 4226 --i; 4227 if (i < 0) { 4228 break; 4229 } 4230 child = mChildren.get(i); 4231 } 4232 4233 if (applyInOrderWithImeWindows(callback, true /* traverseTopToBottom */)) { 4234 return true; 4235 } 4236 4237 while (i >= 0) { 4238 if (child.applyInOrderWithImeWindows(callback, true /* traverseTopToBottom */)) { 4239 return true; 4240 } 4241 --i; 4242 if (i < 0) { 4243 break; 4244 } 4245 child = mChildren.get(i); 4246 } 4247 4248 return false; 4249 } 4250 applyImeWindowsIfNeeded(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)4251 private boolean applyImeWindowsIfNeeded(ToBooleanFunction<WindowState> callback, 4252 boolean traverseTopToBottom) { 4253 // If this window is the current IME target, so we need to process the IME windows 4254 // directly above it. The exception is if we are in split screen 4255 // in which case we process the IME at the DisplayContent level to 4256 // ensure it is above the docked divider. 4257 if (isInputMethodTarget() && !inSplitScreenWindowingMode()) { 4258 if (getDisplayContent().forAllImeWindows(callback, traverseTopToBottom)) { 4259 return true; 4260 } 4261 } 4262 return false; 4263 } 4264 applyInOrderWithImeWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)4265 private boolean applyInOrderWithImeWindows(ToBooleanFunction<WindowState> callback, 4266 boolean traverseTopToBottom) { 4267 if (traverseTopToBottom) { 4268 if (applyImeWindowsIfNeeded(callback, traverseTopToBottom) 4269 || callback.apply(this)) { 4270 return true; 4271 } 4272 } else { 4273 if (callback.apply(this) 4274 || applyImeWindowsIfNeeded(callback, traverseTopToBottom)) { 4275 return true; 4276 } 4277 } 4278 return false; 4279 } 4280 getWindow(Predicate<WindowState> callback)4281 WindowState getWindow(Predicate<WindowState> callback) { 4282 if (mChildren.isEmpty()) { 4283 return callback.test(this) ? this : null; 4284 } 4285 4286 // We want to consume the positive sublayer children first because they need to appear 4287 // above the parent, then this window (the parent), and then the negative sublayer children 4288 // because they need to appear above the parent. 4289 int i = mChildren.size() - 1; 4290 WindowState child = mChildren.get(i); 4291 4292 while (i >= 0 && child.mSubLayer >= 0) { 4293 if (callback.test(child)) { 4294 return child; 4295 } 4296 --i; 4297 if (i < 0) { 4298 break; 4299 } 4300 child = mChildren.get(i); 4301 } 4302 4303 if (callback.test(this)) { 4304 return this; 4305 } 4306 4307 while (i >= 0) { 4308 if (callback.test(child)) { 4309 return child; 4310 } 4311 --i; 4312 if (i < 0) { 4313 break; 4314 } 4315 child = mChildren.get(i); 4316 } 4317 4318 return null; 4319 } 4320 4321 /** 4322 * @return True if we our one of our ancestors has {@link #mAnimatingExit} set to true, false 4323 * otherwise. 4324 */ 4325 @VisibleForTesting isSelfOrAncestorWindowAnimatingExit()4326 boolean isSelfOrAncestorWindowAnimatingExit() { 4327 WindowState window = this; 4328 do { 4329 if (window.mAnimatingExit) { 4330 return true; 4331 } 4332 window = window.getParentWindow(); 4333 } while (window != null); 4334 return false; 4335 } 4336 onExitAnimationDone()4337 void onExitAnimationDone() { 4338 if (DEBUG_ANIM) Slog.v(TAG, "onExitAnimationDone in " + this 4339 + ": exiting=" + mAnimatingExit + " remove=" + mRemoveOnExit 4340 + " selfAnimating=" + isSelfAnimating()); 4341 4342 if (!mChildren.isEmpty()) { 4343 // Copying to a different list as multiple children can be removed. 4344 final ArrayList<WindowState> childWindows = new ArrayList<>(mChildren); 4345 for (int i = childWindows.size() - 1; i >= 0; i--) { 4346 childWindows.get(i).onExitAnimationDone(); 4347 } 4348 } 4349 4350 if (mWinAnimator.mEnteringAnimation) { 4351 mWinAnimator.mEnteringAnimation = false; 4352 mWmService.requestTraversal(); 4353 // System windows don't have an activity and an app token as a result, but need a way 4354 // to be informed about their entrance animation end. 4355 if (mAppToken == null) { 4356 try { 4357 mClient.dispatchWindowShown(); 4358 } catch (RemoteException e) { 4359 } 4360 } 4361 } 4362 4363 if (isSelfAnimating()) { 4364 return; 4365 } 4366 4367 // TODO (multidisplay): Accessibility supported only for the default display and 4368 // embedded displays 4369 if (mWmService.mAccessibilityController != null && (getDisplayId() == DEFAULT_DISPLAY 4370 || getDisplayContent().getParentWindow() != null)) { 4371 mWmService.mAccessibilityController.onSomeWindowResizedOrMovedLocked(); 4372 } 4373 4374 if (!isSelfOrAncestorWindowAnimatingExit()) { 4375 return; 4376 } 4377 4378 if (localLOGV || DEBUG_ADD_REMOVE) Slog.v(TAG, 4379 "Exit animation finished in " + this + ": remove=" + mRemoveOnExit); 4380 4381 mDestroying = true; 4382 4383 final boolean hasSurface = mWinAnimator.hasSurface(); 4384 4385 // Use pendingTransaction here so hide is done the same transaction as the other 4386 // animations when exiting 4387 mWinAnimator.hide(getPendingTransaction(), "onExitAnimationDone"); 4388 4389 // If we have an app token, we ask it to destroy the surface for us, so that it can take 4390 // care to ensure the activity has actually stopped and the surface is not still in use. 4391 // Otherwise we add the service to mDestroySurface and allow it to be processed in our next 4392 // transaction. 4393 if (mAppToken != null) { 4394 mAppToken.destroySurfaces(); 4395 } else { 4396 if (hasSurface) { 4397 mWmService.mDestroySurface.add(this); 4398 } 4399 if (mRemoveOnExit) { 4400 mWmService.mPendingRemove.add(this); 4401 mRemoveOnExit = false; 4402 } 4403 } 4404 mAnimatingExit = false; 4405 getDisplayContent().mWallpaperController.hideWallpapers(this); 4406 } 4407 clearAnimatingFlags()4408 boolean clearAnimatingFlags() { 4409 boolean didSomething = false; 4410 // We don't want to clear it out for windows that get replaced, because the 4411 // animation depends on the flag to remove the replaced window. 4412 // 4413 // We also don't clear the mAnimatingExit flag for windows which have the 4414 // mRemoveOnExit flag. This indicates an explicit remove request has been issued 4415 // by the client. We should let animation proceed and not clear this flag or 4416 // they won't eventually be removed by WindowStateAnimator#finishExit. 4417 if (!mWillReplaceWindow && !mRemoveOnExit) { 4418 // Clear mAnimating flag together with mAnimatingExit. When animation 4419 // changes from exiting to entering, we need to clear this flag until the 4420 // new animation gets applied, so that isAnimationStarting() becomes true 4421 // until then. 4422 // Otherwise applySurfaceChangesTransaction will fail to skip surface 4423 // placement for this window during this period, one or more frame will 4424 // show up with wrong position or scale. 4425 if (mAnimatingExit) { 4426 mAnimatingExit = false; 4427 didSomething = true; 4428 } 4429 if (mDestroying) { 4430 mDestroying = false; 4431 mWmService.mDestroySurface.remove(this); 4432 didSomething = true; 4433 } 4434 } 4435 4436 for (int i = mChildren.size() - 1; i >= 0; --i) { 4437 didSomething |= (mChildren.get(i)).clearAnimatingFlags(); 4438 } 4439 4440 return didSomething; 4441 } 4442 isRtl()4443 public boolean isRtl() { 4444 return getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL; 4445 } 4446 hideWallpaperWindow(boolean wasDeferred, String reason)4447 void hideWallpaperWindow(boolean wasDeferred, String reason) { 4448 for (int j = mChildren.size() - 1; j >= 0; --j) { 4449 final WindowState c = mChildren.get(j); 4450 c.hideWallpaperWindow(wasDeferred, reason); 4451 } 4452 if (!mWinAnimator.mLastHidden || wasDeferred) { 4453 mWinAnimator.hide(reason); 4454 getDisplayContent().mWallpaperController.mDeferredHideWallpaper = null; 4455 dispatchWallpaperVisibility(false); 4456 final DisplayContent displayContent = getDisplayContent(); 4457 if (displayContent != null) { 4458 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 4459 if (DEBUG_LAYOUT_REPEATS) { 4460 mWmService.mWindowPlacerLocked.debugLayoutRepeats("hideWallpaperWindow " + this, 4461 displayContent.pendingLayoutChanges); 4462 } 4463 } 4464 } 4465 } 4466 4467 /** 4468 * Check wallpaper window for visibility change and notify window if so. 4469 * @param visible Current visibility. 4470 */ dispatchWallpaperVisibility(final boolean visible)4471 void dispatchWallpaperVisibility(final boolean visible) { 4472 final boolean hideAllowed = 4473 getDisplayContent().mWallpaperController.mDeferredHideWallpaper == null; 4474 4475 // Only send notification if the visibility actually changed and we are not trying to hide 4476 // the wallpaper when we are deferring hiding of the wallpaper. 4477 if (mWallpaperVisible != visible && (hideAllowed || visible)) { 4478 mWallpaperVisible = visible; 4479 try { 4480 if (DEBUG_VISIBILITY || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 4481 "Updating vis of wallpaper " + this 4482 + ": " + visible + " from:\n" + Debug.getCallers(4, " ")); 4483 mClient.dispatchAppVisibility(visible); 4484 } catch (RemoteException e) { 4485 } 4486 } 4487 } 4488 hasVisibleNotDrawnWallpaper()4489 boolean hasVisibleNotDrawnWallpaper() { 4490 if (mWallpaperVisible && !isDrawnLw()) { 4491 return true; 4492 } 4493 for (int j = mChildren.size() - 1; j >= 0; --j) { 4494 final WindowState c = mChildren.get(j); 4495 if (c.hasVisibleNotDrawnWallpaper()) { 4496 return true; 4497 } 4498 } 4499 return false; 4500 } 4501 updateReportedVisibility(UpdateReportedVisibilityResults results)4502 void updateReportedVisibility(UpdateReportedVisibilityResults results) { 4503 for (int i = mChildren.size() - 1; i >= 0; --i) { 4504 final WindowState c = mChildren.get(i); 4505 c.updateReportedVisibility(results); 4506 } 4507 4508 if (mAppFreezing || mViewVisibility != View.VISIBLE 4509 || mAttrs.type == TYPE_APPLICATION_STARTING 4510 || mDestroying) { 4511 return; 4512 } 4513 if (DEBUG_VISIBILITY) { 4514 Slog.v(TAG, "Win " + this + ": isDrawn=" + isDrawnLw() 4515 + ", animating=" + isAnimating()); 4516 if (!isDrawnLw()) { 4517 Slog.v(TAG, "Not displayed: s=" + mWinAnimator.mSurfaceController 4518 + " pv=" + isVisibleByPolicy() 4519 + " mDrawState=" + mWinAnimator.mDrawState 4520 + " ph=" + isParentWindowHidden() 4521 + " th=" + (mAppToken != null ? mAppToken.hiddenRequested : false) 4522 + " a=" + isAnimating()); 4523 } 4524 } 4525 4526 results.numInteresting++; 4527 if (isDrawnLw()) { 4528 results.numDrawn++; 4529 if (!isAnimating()) { 4530 results.numVisible++; 4531 } 4532 results.nowGone = false; 4533 } else if (isAnimating()) { 4534 results.nowGone = false; 4535 } 4536 } 4537 skipDecorCrop()4538 private boolean skipDecorCrop() { 4539 // The decor frame is used to specify the region not covered by the system 4540 // decorations (nav bar, status bar). In case this is empty, for example with 4541 // FLAG_TRANSLUCENT_NAVIGATION, we don't need to do any cropping. 4542 if (mWindowFrames.mDecorFrame.isEmpty()) { 4543 return true; 4544 } 4545 4546 // But if we have a frame, and are an application window, then we must be cropped. 4547 if (mAppToken != null) { 4548 return false; 4549 } 4550 4551 // For non application windows, we may be allowed to extend over the decor bars 4552 // depending on our type and permissions assosciated with our token. 4553 return mToken.canLayerAboveSystemBars(); 4554 } 4555 4556 /** 4557 * Calculate the window crop according to system decor policy. In general this is 4558 * the system decor rect (see #calculateSystemDecorRect), but we also have some 4559 * special cases. This rectangle is in screen space. 4560 */ calculatePolicyCrop(Rect policyCrop)4561 void calculatePolicyCrop(Rect policyCrop) { 4562 final DisplayContent displayContent = getDisplayContent(); 4563 4564 if (!displayContent.isDefaultDisplay && !displayContent.supportsSystemDecorations()) { 4565 // On a different display there is no system decor. Crop the window 4566 // by the screen boundaries. 4567 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 4568 policyCrop.set(0, 0, mWindowFrames.mCompatFrame.width(), 4569 mWindowFrames.mCompatFrame.height()); 4570 policyCrop.intersect(-mWindowFrames.mCompatFrame.left, -mWindowFrames.mCompatFrame.top, 4571 displayInfo.logicalWidth - mWindowFrames.mCompatFrame.left, 4572 displayInfo.logicalHeight - mWindowFrames.mCompatFrame.top); 4573 } else if (skipDecorCrop()) { 4574 // Windows without policy decor aren't cropped. 4575 policyCrop.set(0, 0, mWindowFrames.mCompatFrame.width(), 4576 mWindowFrames.mCompatFrame.height()); 4577 } else { 4578 // Crop to the system decor specified by policy. 4579 calculateSystemDecorRect(policyCrop); 4580 } 4581 } 4582 4583 /** 4584 * The system decor rect is the region of the window which is not covered 4585 * by system decorations. 4586 */ calculateSystemDecorRect(Rect systemDecorRect)4587 private void calculateSystemDecorRect(Rect systemDecorRect) { 4588 final Rect decorRect = mWindowFrames.mDecorFrame; 4589 final int width = mWindowFrames.mFrame.width(); 4590 final int height = mWindowFrames.mFrame.height(); 4591 4592 final int left = mWindowFrames.mFrame.left; 4593 final int top = mWindowFrames.mFrame.top; 4594 4595 // Initialize the decor rect to the entire frame. 4596 if (isDockedResizing()) { 4597 // If we are resizing with the divider, the task bounds might be smaller than the 4598 // stack bounds. The system decor is used to clip to the task bounds, which we don't 4599 // want in this case in order to avoid holes. 4600 // 4601 // We take care to not shrink the width, for surfaces which are larger than 4602 // the display region. Of course this area will not eventually be visible 4603 // but if we truncate the width now, we will calculate incorrectly 4604 // when adjusting to the stack bounds. 4605 final DisplayInfo displayInfo = getDisplayContent().getDisplayInfo(); 4606 systemDecorRect.set(0, 0, 4607 Math.max(width, displayInfo.logicalWidth), 4608 Math.max(height, displayInfo.logicalHeight)); 4609 } else { 4610 systemDecorRect.set(0, 0, width, height); 4611 } 4612 4613 // If a freeform window is animating from a position where it would be cutoff, it would be 4614 // cutoff during the animation. We don't want that, so for the duration of the animation 4615 // we ignore the decor cropping and depend on layering to position windows correctly. 4616 4617 // We also ignore cropping when the window is currently being drag resized in split screen 4618 // to prevent issues with the crop for screenshot. 4619 final boolean cropToDecor = 4620 !(inFreeformWindowingMode() && isAnimatingLw()) && !isDockedResizing(); 4621 if (cropToDecor) { 4622 // Intersect with the decor rect, offsetted by window position. 4623 systemDecorRect.intersect(decorRect.left - left, decorRect.top - top, 4624 decorRect.right - left, decorRect.bottom - top); 4625 } 4626 4627 // If size compatibility is being applied to the window, the 4628 // surface is scaled relative to the screen. Also apply this 4629 // scaling to the crop rect. We aren't using the standard rect 4630 // scale function because we want to round things to make the crop 4631 // always round to a larger rect to ensure we don't crop too 4632 // much and hide part of the window that should be seen. 4633 if (mInvGlobalScale != 1.0f && inSizeCompatMode()) { 4634 final float scale = mInvGlobalScale; 4635 systemDecorRect.left = (int) (systemDecorRect.left * scale - 0.5f); 4636 systemDecorRect.top = (int) (systemDecorRect.top * scale - 0.5f); 4637 systemDecorRect.right = (int) ((systemDecorRect.right + 1) * scale - 0.5f); 4638 systemDecorRect.bottom = (int) ((systemDecorRect.bottom + 1) * scale - 0.5f); 4639 } 4640 4641 } 4642 4643 /** 4644 * Expand the given rectangle by this windows surface insets. This 4645 * takes you from the 'window size' to the 'surface size'. 4646 * The surface insets are positive in each direction, so we inset by 4647 * the inverse. 4648 */ expandForSurfaceInsets(Rect r)4649 void expandForSurfaceInsets(Rect r) { 4650 r.inset(-mAttrs.surfaceInsets.left, 4651 -mAttrs.surfaceInsets.top, 4652 -mAttrs.surfaceInsets.right, 4653 -mAttrs.surfaceInsets.bottom); 4654 } 4655 surfaceInsetsChanging()4656 boolean surfaceInsetsChanging() { 4657 return !mLastSurfaceInsets.equals(mAttrs.surfaceInsets); 4658 } 4659 relayoutVisibleWindow(int result, int attrChanges)4660 int relayoutVisibleWindow(int result, int attrChanges) { 4661 final boolean wasVisible = isVisibleLw(); 4662 4663 result |= (!wasVisible || !isDrawnLw()) ? RELAYOUT_RES_FIRST_TIME : 0; 4664 4665 if (mAnimatingExit) { 4666 Slog.d(TAG, "relayoutVisibleWindow: " + this + " mAnimatingExit=true, mRemoveOnExit=" 4667 + mRemoveOnExit + ", mDestroying=" + mDestroying); 4668 4669 // Cancel the existing exit animation for the next enter animation. 4670 if (isSelfAnimating()) { 4671 cancelAnimation(); 4672 destroySurfaceUnchecked(); 4673 } 4674 mAnimatingExit = false; 4675 } 4676 if (mDestroying) { 4677 mDestroying = false; 4678 mWmService.mDestroySurface.remove(this); 4679 } 4680 if (!wasVisible) { 4681 mWinAnimator.mEnterAnimationPending = true; 4682 } 4683 4684 mLastVisibleLayoutRotation = getDisplayContent().getRotation(); 4685 4686 mWinAnimator.mEnteringAnimation = true; 4687 4688 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "prepareToDisplay"); 4689 try { 4690 prepareWindowToDisplayDuringRelayout(wasVisible); 4691 } finally { 4692 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 4693 } 4694 4695 if ((attrChanges & FORMAT_CHANGED) != 0) { 4696 // If the format can't be changed in place, preserve the old surface until the app draws 4697 // on the new one. This prevents blinking when we change elevation of freeform and 4698 // pinned windows. 4699 if (!mWinAnimator.tryChangeFormatInPlaceLocked()) { 4700 mWinAnimator.preserveSurfaceLocked(); 4701 result |= RELAYOUT_RES_SURFACE_CHANGED 4702 | RELAYOUT_RES_FIRST_TIME; 4703 } 4704 } 4705 4706 // When we change the Surface size, in scenarios which may require changing 4707 // the surface position in sync with the resize, we use a preserved surface 4708 // so we can freeze it while waiting for the client to report draw on the newly 4709 // sized surface. At the moment this logic is only in place for switching 4710 // in and out of the big surface for split screen resize. 4711 if (isDragResizeChanged()) { 4712 setDragResizing(); 4713 // We can only change top level windows to the full-screen surface when 4714 // resizing (as we only have one full-screen surface). So there is no need 4715 // to preserve and destroy windows which are attached to another, they 4716 // will keep their surface and its size may change over time. 4717 if (mHasSurface && !isChildWindow()) { 4718 mWinAnimator.preserveSurfaceLocked(); 4719 result |= RELAYOUT_RES_SURFACE_CHANGED | 4720 RELAYOUT_RES_FIRST_TIME; 4721 } 4722 } 4723 final boolean freeformResizing = isDragResizing() 4724 && getResizeMode() == DRAG_RESIZE_MODE_FREEFORM; 4725 final boolean dockedResizing = isDragResizing() 4726 && getResizeMode() == DRAG_RESIZE_MODE_DOCKED_DIVIDER; 4727 result |= freeformResizing ? RELAYOUT_RES_DRAG_RESIZING_FREEFORM : 0; 4728 result |= dockedResizing ? RELAYOUT_RES_DRAG_RESIZING_DOCKED : 0; 4729 return result; 4730 } 4731 4732 /** 4733 * @return True if this window has been laid out at least once; false otherwise. 4734 */ isLaidOut()4735 boolean isLaidOut() { 4736 return mLayoutSeq != -1; 4737 } 4738 4739 /** 4740 * Add the DisplayContent of the embedded display which is re-parented to this window to 4741 * the list of embedded displays. 4742 * 4743 * @param dc DisplayContent of the re-parented embedded display. 4744 * @return {@code true} if the giving DisplayContent is added, {@code false} otherwise. 4745 */ addEmbeddedDisplayContent(DisplayContent dc)4746 boolean addEmbeddedDisplayContent(DisplayContent dc) { 4747 return mEmbeddedDisplayContents.add(dc); 4748 } 4749 4750 /** 4751 * Remove the DisplayContent of the embedded display which is re-parented to this window from 4752 * the list of embedded displays. 4753 * 4754 * @param dc DisplayContent of the re-parented embedded display. 4755 * @return {@code true} if the giving DisplayContent is removed, {@code false} otherwise. 4756 */ removeEmbeddedDisplayContent(DisplayContent dc)4757 boolean removeEmbeddedDisplayContent(DisplayContent dc) { 4758 return mEmbeddedDisplayContents.remove(dc); 4759 } 4760 4761 /** 4762 * Updates the last inset values to the current ones. 4763 */ updateLastInsetValues()4764 void updateLastInsetValues() { 4765 mWindowFrames.updateLastInsetValues(); 4766 } 4767 startAnimation(Animation anim)4768 void startAnimation(Animation anim) { 4769 4770 // If we are an inset provider, all our animations are driven by the inset client. 4771 if (mInsetProvider != null && mInsetProvider.isControllable()) { 4772 return; 4773 } 4774 4775 final DisplayInfo displayInfo = getDisplayContent().getDisplayInfo(); 4776 anim.initialize(mWindowFrames.mFrame.width(), mWindowFrames.mFrame.height(), 4777 displayInfo.appWidth, displayInfo.appHeight); 4778 anim.restrictDuration(MAX_ANIMATION_DURATION); 4779 anim.scaleCurrentDuration(mWmService.getWindowAnimationScaleLocked()); 4780 final AnimationAdapter adapter = new LocalAnimationAdapter( 4781 new WindowAnimationSpec(anim, mSurfacePosition, false /* canSkipFirstFrame */, 4782 0 /* windowCornerRadius */), 4783 mWmService.mSurfaceAnimationRunner); 4784 startAnimation(getPendingTransaction(), adapter); 4785 commitPendingTransaction(); 4786 } 4787 startMoveAnimation(int left, int top)4788 private void startMoveAnimation(int left, int top) { 4789 4790 // If we are an inset provider, all our animations are driven by the inset client. 4791 if (mInsetProvider != null && mInsetProvider.isControllable()) { 4792 return; 4793 } 4794 4795 if (DEBUG_ANIM) Slog.v(TAG, "Setting move animation on " + this); 4796 final Point oldPosition = new Point(); 4797 final Point newPosition = new Point(); 4798 transformFrameToSurfacePosition(mWindowFrames.mLastFrame.left, mWindowFrames.mLastFrame.top, 4799 oldPosition); 4800 transformFrameToSurfacePosition(left, top, newPosition); 4801 final AnimationAdapter adapter = new LocalAnimationAdapter( 4802 new MoveAnimationSpec(oldPosition.x, oldPosition.y, newPosition.x, newPosition.y), 4803 mWmService.mSurfaceAnimationRunner); 4804 startAnimation(getPendingTransaction(), adapter); 4805 } 4806 startAnimation(Transaction t, AnimationAdapter adapter)4807 private void startAnimation(Transaction t, AnimationAdapter adapter) { 4808 startAnimation(t, adapter, mWinAnimator.mLastHidden); 4809 } 4810 4811 @Override onAnimationFinished()4812 protected void onAnimationFinished() { 4813 super.onAnimationFinished(); 4814 mWinAnimator.onAnimationFinished(); 4815 } 4816 4817 /** 4818 * Retrieves the current transformation matrix of the window, relative to the display. 4819 * 4820 * @param float9 A temporary array of 9 floats. 4821 * @param outMatrix Matrix to fill in the transformation. 4822 */ getTransformationMatrix(float[] float9, Matrix outMatrix)4823 void getTransformationMatrix(float[] float9, Matrix outMatrix) { 4824 float9[Matrix.MSCALE_X] = mWinAnimator.mDsDx; 4825 float9[Matrix.MSKEW_Y] = mWinAnimator.mDtDx; 4826 float9[Matrix.MSKEW_X] = mWinAnimator.mDtDy; 4827 float9[Matrix.MSCALE_Y] = mWinAnimator.mDsDy; 4828 int x = mSurfacePosition.x; 4829 int y = mSurfacePosition.y; 4830 4831 // We might be on a display which has been re-parented to a view in another window, so here 4832 // computes the global location of our display. 4833 DisplayContent dc = getDisplayContent(); 4834 while (dc != null && dc.getParentWindow() != null) { 4835 final WindowState displayParent = dc.getParentWindow(); 4836 x += displayParent.mWindowFrames.mFrame.left - displayParent.mAttrs.surfaceInsets.left 4837 + (dc.getLocationInParentWindow().x * displayParent.mGlobalScale + 0.5f); 4838 y += displayParent.mWindowFrames.mFrame.top - displayParent.mAttrs.surfaceInsets.top 4839 + (dc.getLocationInParentWindow().y * displayParent.mGlobalScale + 0.5f); 4840 dc = displayParent.getDisplayContent(); 4841 } 4842 4843 // If changed, also adjust transformFrameToSurfacePosition 4844 final WindowContainer parent = getParent(); 4845 if (isChildWindow()) { 4846 final WindowState parentWindow = getParentWindow(); 4847 x += parentWindow.mWindowFrames.mFrame.left - parentWindow.mAttrs.surfaceInsets.left; 4848 y += parentWindow.mWindowFrames.mFrame.top - parentWindow.mAttrs.surfaceInsets.top; 4849 } else if (parent != null) { 4850 final Rect parentBounds = parent.getBounds(); 4851 x += parentBounds.left; 4852 y += parentBounds.top; 4853 } 4854 float9[Matrix.MTRANS_X] = x; 4855 float9[Matrix.MTRANS_Y] = y; 4856 float9[Matrix.MPERSP_0] = 0; 4857 float9[Matrix.MPERSP_1] = 0; 4858 float9[Matrix.MPERSP_2] = 1; 4859 outMatrix.setValues(float9); 4860 } 4861 4862 // TODO: Hack to work around the number of states AppWindowToken needs to access without having 4863 // access to its windows children. Need to investigate re-writing 4864 // {@link AppWindowToken#updateReportedVisibilityLocked} so this can be removed. 4865 static final class UpdateReportedVisibilityResults { 4866 int numInteresting; 4867 int numVisible; 4868 int numDrawn; 4869 boolean nowGone = true; 4870 reset()4871 void reset() { 4872 numInteresting = 0; 4873 numVisible = 0; 4874 numDrawn = 0; 4875 nowGone = true; 4876 } 4877 } 4878 4879 private static final class WindowId extends IWindowId.Stub { 4880 private final WeakReference<WindowState> mOuter; 4881 WindowId(WindowState outer)4882 private WindowId(WindowState outer) { 4883 4884 // Use a weak reference for the outer class. This is important to prevent the following 4885 // leak: Since we send this class to the client process, binder will keep it alive as 4886 // long as the client keeps it alive. Now, if the window is removed, we need to clear 4887 // out our reference so even though this class is kept alive we don't leak WindowState, 4888 // which can keep a whole lot of classes alive. 4889 mOuter = new WeakReference<>(outer); 4890 } 4891 4892 @Override registerFocusObserver(IWindowFocusObserver observer)4893 public void registerFocusObserver(IWindowFocusObserver observer) { 4894 final WindowState outer = mOuter.get(); 4895 if (outer != null) { 4896 outer.registerFocusObserver(observer); 4897 } 4898 } 4899 @Override unregisterFocusObserver(IWindowFocusObserver observer)4900 public void unregisterFocusObserver(IWindowFocusObserver observer) { 4901 final WindowState outer = mOuter.get(); 4902 if (outer != null) { 4903 outer.unregisterFocusObserver(observer); 4904 } 4905 } 4906 @Override isFocused()4907 public boolean isFocused() { 4908 final WindowState outer = mOuter.get(); 4909 if (outer != null) { 4910 synchronized (outer.mWmService.mGlobalLock) { 4911 return outer.isFocused(); 4912 } 4913 } 4914 return false; 4915 } 4916 } 4917 4918 4919 @Override shouldMagnify()4920 boolean shouldMagnify() { 4921 if (mAttrs.type == TYPE_INPUT_METHOD || 4922 mAttrs.type == TYPE_INPUT_METHOD_DIALOG || 4923 mAttrs.type == TYPE_MAGNIFICATION_OVERLAY || 4924 mAttrs.type == TYPE_NAVIGATION_BAR || 4925 // It's tempting to wonder: Have we forgotten the rounded corners overlay? 4926 // worry not: it's a fake TYPE_NAVIGATION_BAR_PANEL 4927 mAttrs.type == TYPE_NAVIGATION_BAR_PANEL) { 4928 return false; 4929 } 4930 return true; 4931 } 4932 4933 @Override getSession()4934 SurfaceSession getSession() { 4935 if (mSession.mSurfaceSession != null) { 4936 return mSession.mSurfaceSession; 4937 } else { 4938 return getParent().getSession(); 4939 } 4940 } 4941 4942 @Override needsZBoost()4943 boolean needsZBoost() { 4944 final WindowState inputMethodTarget = getDisplayContent().mInputMethodTarget; 4945 if (mIsImWindow && inputMethodTarget != null) { 4946 final AppWindowToken appToken = inputMethodTarget.mAppToken; 4947 if (appToken != null) { 4948 return appToken.needsZBoost(); 4949 } 4950 } 4951 return mWillReplaceWindow; 4952 } 4953 applyDims(Dimmer dimmer)4954 private void applyDims(Dimmer dimmer) { 4955 if (!mAnimatingExit && mAppDied) { 4956 mIsDimming = true; 4957 dimmer.dimAbove(getPendingTransaction(), this, DEFAULT_DIM_AMOUNT_DEAD_WINDOW); 4958 } else if ((mAttrs.flags & FLAG_DIM_BEHIND) != 0 && isVisibleNow() && !mHidden) { 4959 // Only show a dim behind when the following is satisfied: 4960 // 1. The window has the flag FLAG_DIM_BEHIND 4961 // 2. The WindowToken is not hidden so dims aren't shown when the window is exiting. 4962 // 3. The WS is considered visible according to the isVisible() method 4963 // 4. The WS is not hidden. 4964 mIsDimming = true; 4965 dimmer.dimBelow(getPendingTransaction(), this, mAttrs.dimAmount); 4966 } 4967 } 4968 4969 @Override prepareSurfaces()4970 void prepareSurfaces() { 4971 final Dimmer dimmer = getDimmer(); 4972 mIsDimming = false; 4973 if (dimmer != null) { 4974 applyDims(dimmer); 4975 } 4976 updateSurfacePosition(); 4977 4978 mWinAnimator.prepareSurfaceLocked(true); 4979 super.prepareSurfaces(); 4980 } 4981 4982 @Override onAnimationLeashCreated(Transaction t, SurfaceControl leash)4983 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) { 4984 super.onAnimationLeashCreated(t, leash); 4985 4986 // Leash is now responsible for position, so set our position to 0. 4987 t.setPosition(mSurfaceControl, 0, 0); 4988 mLastSurfacePosition.set(0, 0); 4989 } 4990 4991 @Override onAnimationLeashLost(Transaction t)4992 public void onAnimationLeashLost(Transaction t) { 4993 super.onAnimationLeashLost(t); 4994 updateSurfacePosition(t); 4995 } 4996 4997 @Override updateSurfacePosition()4998 void updateSurfacePosition() { 4999 updateSurfacePosition(getPendingTransaction()); 5000 } 5001 5002 @VisibleForTesting updateSurfacePosition(Transaction t)5003 void updateSurfacePosition(Transaction t) { 5004 if (mSurfaceControl == null) { 5005 return; 5006 } 5007 5008 transformFrameToSurfacePosition(mWindowFrames.mFrame.left, mWindowFrames.mFrame.top, 5009 mSurfacePosition); 5010 5011 // Freeze position while we're unrotated, so the surface remains at the position it was 5012 // prior to the rotation. 5013 if (!mSurfaceAnimator.hasLeash() && mPendingSeamlessRotate == null 5014 && !mLastSurfacePosition.equals(mSurfacePosition)) { 5015 t.setPosition(mSurfaceControl, mSurfacePosition.x, mSurfacePosition.y); 5016 mLastSurfacePosition.set(mSurfacePosition.x, mSurfacePosition.y); 5017 if (surfaceInsetsChanging() && mWinAnimator.hasSurface()) { 5018 mLastSurfaceInsets.set(mAttrs.surfaceInsets); 5019 t.deferTransactionUntil(mSurfaceControl, 5020 mWinAnimator.mSurfaceController.mSurfaceControl.getHandle(), 5021 getFrameNumber()); 5022 } 5023 } 5024 } 5025 transformFrameToSurfacePosition(int left, int top, Point outPoint)5026 private void transformFrameToSurfacePosition(int left, int top, Point outPoint) { 5027 outPoint.set(left, top); 5028 5029 // If changed, also adjust getTransformationMatrix 5030 final WindowContainer parentWindowContainer = getParent(); 5031 if (isChildWindow()) { 5032 // TODO: This probably falls apart at some point and we should 5033 // actually compute relative coordinates. 5034 5035 // Since the parent was outset by its surface insets, we need to undo the outsetting 5036 // with insetting by the same amount. 5037 final WindowState parent = getParentWindow(); 5038 transformSurfaceInsetsPosition(mTmpPoint, parent.mAttrs.surfaceInsets); 5039 outPoint.offset(-parent.mWindowFrames.mFrame.left + mTmpPoint.x, 5040 -parent.mWindowFrames.mFrame.top + mTmpPoint.y); 5041 } else if (parentWindowContainer != null) { 5042 final Rect parentBounds = parentWindowContainer.getDisplayedBounds(); 5043 outPoint.offset(-parentBounds.left, -parentBounds.top); 5044 } 5045 5046 TaskStack stack = getStack(); 5047 5048 // If we have stack outsets, that means the top-left 5049 // will be outset, and we need to inset ourselves 5050 // to account for it. If we actually have shadows we will 5051 // then un-inset ourselves by the surfaceInsets. 5052 if (stack != null) { 5053 final int outset = stack.getStackOutset(); 5054 outPoint.offset(outset, outset); 5055 } 5056 5057 // Expand for surface insets. See WindowState.expandForSurfaceInsets. 5058 transformSurfaceInsetsPosition(mTmpPoint, mAttrs.surfaceInsets); 5059 outPoint.offset(-mTmpPoint.x, -mTmpPoint.y); 5060 } 5061 5062 /** 5063 * The surface insets from layout parameter are in application coordinate. If the window is 5064 * scaled, the insets also need to be scaled for surface position in global coordinate. 5065 */ transformSurfaceInsetsPosition(Point outPos, Rect surfaceInsets)5066 private void transformSurfaceInsetsPosition(Point outPos, Rect surfaceInsets) { 5067 if (!inSizeCompatMode()) { 5068 outPos.x = surfaceInsets.left; 5069 outPos.y = surfaceInsets.top; 5070 return; 5071 } 5072 outPos.x = (int) (surfaceInsets.left * mGlobalScale + 0.5f); 5073 outPos.y = (int) (surfaceInsets.top * mGlobalScale + 0.5f); 5074 } 5075 needsRelativeLayeringToIme()5076 boolean needsRelativeLayeringToIme() { 5077 // We only use the relative layering mode in split screen, as part of elevating the IME 5078 // and windows above it's target above the docked divider. 5079 if (!inSplitScreenWindowingMode()) { 5080 return false; 5081 } 5082 5083 if (isChildWindow()) { 5084 // If we are a child of the input method target we need this promotion. 5085 if (getParentWindow().isInputMethodTarget()) { 5086 return true; 5087 } 5088 } else if (mAppToken != null) { 5089 // Likewise if we share a token with the Input method target and are ordered 5090 // above it but not necessarily a child (e.g. a Dialog) then we also need 5091 // this promotion. 5092 final WindowState imeTarget = getDisplayContent().mInputMethodTarget; 5093 boolean inTokenWithAndAboveImeTarget = imeTarget != null && imeTarget != this 5094 && imeTarget.mToken == mToken && imeTarget.compareTo(this) <= 0; 5095 return inTokenWithAndAboveImeTarget; 5096 } 5097 return false; 5098 } 5099 5100 @Override assignLayer(Transaction t, int layer)5101 void assignLayer(Transaction t, int layer) { 5102 // See comment in assignRelativeLayerForImeTargetChild 5103 if (needsRelativeLayeringToIme()) { 5104 getDisplayContent().assignRelativeLayerForImeTargetChild(t, this); 5105 return; 5106 } 5107 super.assignLayer(t, layer); 5108 } 5109 5110 @Override isDimming()5111 public boolean isDimming() { 5112 return mIsDimming; 5113 } 5114 5115 // TODO(b/70040778): We should aim to eliminate the last user of TYPE_APPLICATION_MEDIA 5116 // then we can drop all negative layering on the windowing side and simply inherit 5117 // the default implementation here. assignChildLayers(Transaction t)5118 public void assignChildLayers(Transaction t) { 5119 // The surface of the main window might be preserved. So the child window on top of the main 5120 // window should be also on top of the preserved surface. 5121 int layer = PRESERVED_SURFACE_LAYER + 1; 5122 for (int i = 0; i < mChildren.size(); i++) { 5123 final WindowState w = mChildren.get(i); 5124 5125 // APPLICATION_MEDIA_OVERLAY needs to go above APPLICATION_MEDIA 5126 // while they both need to go below the main window. However the 5127 // relative layering of multiple APPLICATION_MEDIA/OVERLAY has never 5128 // been defined and so we can use static layers and leave it that way. 5129 if (w.mAttrs.type == TYPE_APPLICATION_MEDIA) { 5130 w.assignLayer(t, -2); 5131 } else if (w.mAttrs.type == TYPE_APPLICATION_MEDIA_OVERLAY) { 5132 w.assignLayer(t, -1); 5133 } else { 5134 w.assignLayer(t, layer); 5135 } 5136 w.assignChildLayers(t); 5137 layer++; 5138 } 5139 } 5140 5141 /** 5142 * Update a tap exclude region identified by provided id. The requested area will be clipped to 5143 * the window bounds. 5144 */ updateTapExcludeRegion(int regionId, Region region)5145 void updateTapExcludeRegion(int regionId, Region region) { 5146 final DisplayContent currentDisplay = getDisplayContent(); 5147 if (currentDisplay == null) { 5148 throw new IllegalStateException("Trying to update window not attached to any display."); 5149 } 5150 5151 if (mTapExcludeRegionHolder == null) { 5152 mTapExcludeRegionHolder = new TapExcludeRegionHolder(); 5153 5154 // Make sure that this window is registered as one that provides a tap exclude region 5155 // for its containing display. 5156 currentDisplay.mTapExcludeProvidingWindows.add(this); 5157 } 5158 5159 mTapExcludeRegionHolder.updateRegion(regionId, region); 5160 // Trigger touch exclude region update on current display. 5161 currentDisplay.updateTouchExcludeRegion(); 5162 // Trigger touchable region update for this window. 5163 currentDisplay.getInputMonitor().updateInputWindowsLw(true /* force */); 5164 } 5165 5166 /** 5167 * Union the region with current tap exclude region that this window provides. 5168 * 5169 * @param region The region to be amended. It is on the screen coordinates. 5170 */ amendTapExcludeRegion(Region region)5171 void amendTapExcludeRegion(Region region) { 5172 final Region tempRegion = Region.obtain(); 5173 mTmpRect.set(mWindowFrames.mFrame); 5174 mTmpRect.offsetTo(0, 0); 5175 mTapExcludeRegionHolder.amendRegion(tempRegion, mTmpRect); 5176 // The region held by the holder is on the window coordinates. We need to translate it to 5177 // the screen coordinates. 5178 tempRegion.translate(mWindowFrames.mFrame.left, mWindowFrames.mFrame.top); 5179 region.op(tempRegion, Region.Op.UNION); 5180 tempRegion.recycle(); 5181 } 5182 hasTapExcludeRegion()5183 boolean hasTapExcludeRegion() { 5184 return mTapExcludeRegionHolder != null && !mTapExcludeRegionHolder.isEmpty(); 5185 } 5186 5187 @Override isInputMethodTarget()5188 public boolean isInputMethodTarget() { 5189 return getDisplayContent().mInputMethodTarget == this; 5190 } 5191 getFrameNumber()5192 long getFrameNumber() { 5193 return mFrameNumber; 5194 } 5195 setFrameNumber(long frameNumber)5196 void setFrameNumber(long frameNumber) { 5197 mFrameNumber = frameNumber; 5198 } 5199 getMaxVisibleBounds(Rect out)5200 public void getMaxVisibleBounds(Rect out) { 5201 if (out.isEmpty()) { 5202 out.set(mWindowFrames.mVisibleFrame); 5203 return; 5204 } 5205 5206 if (mWindowFrames.mVisibleFrame.left < out.left) { 5207 out.left = mWindowFrames.mVisibleFrame.left; 5208 } 5209 if (mWindowFrames.mVisibleFrame.top < out.top) { 5210 out.top = mWindowFrames.mVisibleFrame.top; 5211 } 5212 if (mWindowFrames.mVisibleFrame.right > out.right) { 5213 out.right = mWindowFrames.mVisibleFrame.right; 5214 } 5215 if (mWindowFrames.mVisibleFrame.bottom > out.bottom) { 5216 out.bottom = mWindowFrames.mVisibleFrame.bottom; 5217 } 5218 } 5219 5220 /** 5221 * Copy the inset values over so they can be sent back to the client when a relayout occurs. 5222 */ getInsetsForRelayout(Rect outOverscanInsets, Rect outContentInsets, Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets)5223 void getInsetsForRelayout(Rect outOverscanInsets, Rect outContentInsets, Rect outVisibleInsets, 5224 Rect outStableInsets, Rect outOutsets) { 5225 outOverscanInsets.set(mWindowFrames.mOverscanInsets); 5226 outContentInsets.set(mWindowFrames.mContentInsets); 5227 outVisibleInsets.set(mWindowFrames.mVisibleInsets); 5228 outStableInsets.set(mWindowFrames.mStableInsets); 5229 outOutsets.set(mWindowFrames.mOutsets); 5230 5231 mLastRelayoutContentInsets.set(mWindowFrames.mContentInsets); 5232 } 5233 getContentInsets(Rect outContentInsets)5234 void getContentInsets(Rect outContentInsets) { 5235 outContentInsets.set(mWindowFrames.mContentInsets); 5236 } 5237 getContentInsets()5238 Rect getContentInsets() { 5239 return mWindowFrames.mContentInsets; 5240 } 5241 getStableInsets(Rect outStableInsets)5242 void getStableInsets(Rect outStableInsets) { 5243 outStableInsets.set(mWindowFrames.mStableInsets); 5244 } 5245 getStableInsets()5246 Rect getStableInsets() { 5247 return mWindowFrames.mStableInsets; 5248 } 5249 resetLastContentInsets()5250 void resetLastContentInsets() { 5251 mWindowFrames.resetLastContentInsets(); 5252 } 5253 getVisibleInsets()5254 Rect getVisibleInsets() { 5255 return mWindowFrames.mVisibleInsets; 5256 } 5257 5258 @Override getWindowFrames()5259 public WindowFrames getWindowFrames() { 5260 return mWindowFrames; 5261 } 5262 resetContentChanged()5263 void resetContentChanged() { 5264 mWindowFrames.setContentChanged(false); 5265 } 5266 setInsetProvider(InsetsSourceProvider insetProvider)5267 void setInsetProvider(InsetsSourceProvider insetProvider) { 5268 mInsetProvider = insetProvider; 5269 } 5270 getInsetProvider()5271 InsetsSourceProvider getInsetProvider() { 5272 return mInsetProvider; 5273 } 5274 5275 private final class MoveAnimationSpec implements AnimationSpec { 5276 5277 private final long mDuration; 5278 private Interpolator mInterpolator; 5279 private Point mFrom = new Point(); 5280 private Point mTo = new Point(); 5281 MoveAnimationSpec(int fromX, int fromY, int toX, int toY)5282 private MoveAnimationSpec(int fromX, int fromY, int toX, int toY) { 5283 final Animation anim = AnimationUtils.loadAnimation(mContext, 5284 com.android.internal.R.anim.window_move_from_decor); 5285 mDuration = (long) 5286 (anim.computeDurationHint() * mWmService.getWindowAnimationScaleLocked()); 5287 mInterpolator = anim.getInterpolator(); 5288 mFrom.set(fromX, fromY); 5289 mTo.set(toX, toY); 5290 } 5291 5292 @Override getDuration()5293 public long getDuration() { 5294 return mDuration; 5295 } 5296 5297 @Override apply(Transaction t, SurfaceControl leash, long currentPlayTime)5298 public void apply(Transaction t, SurfaceControl leash, long currentPlayTime) { 5299 final float fraction = (float) currentPlayTime / getDuration(); 5300 final float v = mInterpolator.getInterpolation(fraction); 5301 t.setPosition(leash, mFrom.x + (mTo.x - mFrom.x) * v, 5302 mFrom.y + (mTo.y - mFrom.y) * v); 5303 } 5304 5305 @Override dump(PrintWriter pw, String prefix)5306 public void dump(PrintWriter pw, String prefix) { 5307 pw.println(prefix + "from=" + mFrom 5308 + " to=" + mTo 5309 + " duration=" + mDuration); 5310 } 5311 5312 @Override writeToProtoInner(ProtoOutputStream proto)5313 public void writeToProtoInner(ProtoOutputStream proto) { 5314 final long token = proto.start(MOVE); 5315 mFrom.writeToProto(proto, FROM); 5316 mTo.writeToProto(proto, TO); 5317 proto.write(DURATION_MS, mDuration); 5318 proto.end(token); 5319 } 5320 } 5321 } 5322