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