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 dont 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 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 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 */ 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 */ 712 void setDrawnStateEvaluated(boolean evaluated) { 713 mDrawnStateEvaluated = evaluated; 714 } 715 716 @Override 717 void onParentSet() { 718 super.onParentSet(); 719 setDrawnStateEvaluated(false /*evaluated*/); 720 } 721 722 @Override 723 public int getOwningUid() { 724 return mOwnerUid; 725 } 726 727 @Override 728 public String getOwningPackage() { 729 return mAttrs.packageName; 730 } 731 732 @Override 733 public boolean canAddInternalSystemWindow() { 734 return mOwnerCanAddInternalSystemWindow; 735 } 736 737 @Override 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 */ 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 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 1035 public Rect getFrameLw() { 1036 return mFrame; 1037 } 1038 1039 @Override 1040 public Point getShownPositionLw() { 1041 return mShownPosition; 1042 } 1043 1044 @Override 1045 public Rect getDisplayFrameLw() { 1046 return mDisplayFrame; 1047 } 1048 1049 @Override 1050 public Rect getOverscanFrameLw() { 1051 return mOverscanFrame; 1052 } 1053 1054 @Override 1055 public Rect getContentFrameLw() { 1056 return mContentFrame; 1057 } 1058 1059 @Override 1060 public Rect getVisibleFrameLw() { 1061 return mVisibleFrame; 1062 } 1063 1064 Rect getStableFrameLw() { 1065 return mStableFrame; 1066 } 1067 1068 @Override 1069 public boolean getGivenInsetsPendingLw() { 1070 return mGivenInsetsPending; 1071 } 1072 1073 @Override 1074 public Rect getGivenContentInsetsLw() { 1075 return mGivenContentInsets; 1076 } 1077 1078 @Override 1079 public Rect getGivenVisibleInsetsLw() { 1080 return mGivenVisibleInsets; 1081 } 1082 1083 @Override 1084 public WindowManager.LayoutParams getAttrs() { 1085 return mAttrs; 1086 } 1087 1088 @Override 1089 public boolean getNeedsMenuLw(WindowManagerPolicy.WindowState bottom) { 1090 return getDisplayContent().getNeedsMenu(this, bottom); 1091 } 1092 1093 @Override 1094 public int getSystemUiVisibility() { 1095 return mSystemUiVisibility; 1096 } 1097 1098 @Override 1099 public int getSurfaceLayer() { 1100 return mLayer; 1101 } 1102 1103 @Override 1104 public int getBaseType() { 1105 return getTopParentWindow().mAttrs.type; 1106 } 1107 1108 @Override 1109 public IApplicationToken getAppToken() { 1110 return mAppToken != null ? mAppToken.appToken : null; 1111 } 1112 1113 @Override 1114 public boolean isVoiceInteraction() { 1115 return mAppToken != null && mAppToken.mVoiceInteraction; 1116 } 1117 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 */ 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 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 1249 void setOrientationChanging(boolean changing) { 1250 mOrientationChanging = changing; 1251 mOrientationChangeTimedOut = false; 1252 } 1253 1254 void orientationChangeTimedOut() { 1255 mOrientationChangeTimedOut = true; 1256 } 1257 1258 DisplayContent getDisplayContent() { 1259 return mToken.getDisplayContent(); 1260 } 1261 1262 DisplayInfo getDisplayInfo() { 1263 final DisplayContent displayContent = getDisplayContent(); 1264 return displayContent != null ? displayContent.getDisplayInfo() : null; 1265 } 1266 1267 @Override 1268 public int getDisplayId() { 1269 final DisplayContent displayContent = getDisplayContent(); 1270 if (displayContent == null) { 1271 return -1; 1272 } 1273 return displayContent.getDisplayId(); 1274 } 1275 1276 Task getTask() { 1277 return mAppToken != null ? mAppToken.getTask() : null; 1278 } 1279 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 */ 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 1325 public long getInputDispatchingTimeoutNanos() { 1326 return mAppToken != null 1327 ? mAppToken.mInputDispatchingTimeoutNanos 1328 : WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; 1329 } 1330 1331 @Override 1332 public boolean hasAppShownWindows() { 1333 return mAppToken != null && (mAppToken.firstWindowDrawn || mAppToken.startingDisplayed); 1334 } 1335 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 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 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 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 */ 1375 boolean wouldBeVisibleIfPolicyIgnored() { 1376 return mHasSurface && !isParentWindowHidden() 1377 && !mAnimatingExit && !mDestroying && (!mIsWallpaper || mWallpaperVisible); 1378 } 1379 1380 @Override 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? 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 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 1527 public boolean isAnimatingLw() { 1528 return mWinAnimator.mAnimation != null 1529 || (mAppToken != null && mAppToken.mAppAnimator.animation != null); 1530 } 1531 1532 @Override 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 */ 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 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 */ 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 1580 void onMovedByResize() { 1581 if (DEBUG_RESIZE) Slog.d(TAG, "onMovedByResize: Moving " + this); 1582 mMovedByResize = true; 1583 super.onMovedByResize(); 1584 } 1585 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 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 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 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 */ 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 */ 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 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 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. */ 1771 boolean isConfigChanged() { 1772 return !getLastReportedConfiguration().equals(getConfiguration()); 1773 } 1774 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 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 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 1846 void removeIfPossible() { 1847 super.removeIfPossible(); 1848 removeIfPossible(false /*keepVisibleDeadWindow*/); 1849 } 1850 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 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 2000 void setHasSurface(boolean hasSurface) { 2001 mHasSurface = hasSurface; 2002 } 2003 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 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 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 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 { 2085 DeadWindowEventReceiver(InputChannel inputChannel) { 2086 super(inputChannel, mService.mH.getLooper()); 2087 } 2088 @Override 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 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 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 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 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. */ 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 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 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 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. 2224 boolean inPinnedWorkspace() { 2225 final Task task = getTask(); 2226 return task != null && task.inPinnedWorkspace(); 2227 } 2228 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 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 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 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 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 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 2333 void getMergedConfiguration(MergedConfiguration outConfiguration) { 2334 final Configuration globalConfig = mService.mRoot.getConfiguration(); 2335 final Configuration overrideConfig = getMergedOverrideConfiguration(); 2336 outConfiguration.setConfiguration(globalConfig, overrideConfig); 2337 } 2338 2339 void setLastReportedMergedConfiguration(MergedConfiguration config) { 2340 mLastReportedConfiguration.setTo(config); 2341 } 2342 2343 void getLastReportedMergedConfiguration(MergedConfiguration config) { 2344 config.setTo(mLastReportedConfiguration); 2345 } 2346 2347 private Configuration getLastReportedConfiguration() { 2348 return mLastReportedConfiguration.getMergedConfiguration(); 2349 } 2350 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 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 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 */ 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. */ 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. */ 2452 boolean canReceiveTouchInput() { 2453 return mAppToken != null && mAppToken.getTask() != null 2454 && mAppToken.getTask().mStack.shouldIgnoreInput(); 2455 } 2456 2457 @Override 2458 public boolean hasDrawnLw() { 2459 return mWinAnimator.mDrawState == WindowStateAnimator.HAS_DRAWN; 2460 } 2461 2462 @Override 2463 public boolean showLw(boolean doAnimation) { 2464 return showLw(doAnimation, true); 2465 } 2466 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 2516 public boolean hideLw(boolean doAnimation) { 2517 return hideLw(doAnimation, true); 2518 } 2519 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 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 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 2593 public void hidePermanentlyLw() { 2594 if (!mPermanentlyHidden) { 2595 mPermanentlyHidden = true; 2596 hideLw(true, true); 2597 } 2598 } 2599 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 2625 public boolean isAlive() { 2626 return mClient.asBinder().isBinderAlive(); 2627 } 2628 2629 boolean isClosing() { 2630 return mAnimatingExit || (mService.mClosingApps.contains(mAppToken)); 2631 } 2632 2633 boolean isAnimatingWithSavedSurface() { 2634 return mAnimatingWithSavedSurface; 2635 } 2636 2637 @Override 2638 boolean isAnimating() { 2639 if (mWinAnimator.isAnimationSet() || mAnimatingExit) { 2640 return true; 2641 } 2642 return super.isAnimating(); 2643 } 2644 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 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 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 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 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 2725 public void setVisibleBeforeClientHidden() { 2726 mWasVisibleBeforeClientHidden |= 2727 (mViewVisibility == View.VISIBLE || mAnimatingWithSavedSurface); 2728 2729 super.setVisibleBeforeClientHidden(); 2730 } 2731 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 2740 public boolean wasVisibleBeforeClientHidden() { 2741 return mWasVisibleBeforeClientHidden; 2742 } 2743 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 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 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 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} 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 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.*/ 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. */ 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 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 2983 boolean hasSavedSurface() { 2984 return mSurfaceSaved; 2985 } 2986 2987 void clearHasSavedSurface() { 2988 mSurfaceSaved = false; 2989 mAnimatingWithSavedSurface = false; 2990 if (mWasVisibleBeforeClientHidden) { 2991 mAppToken.destroySavedSurfaces(); 2992 } 2993 } 2994 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 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 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 3025 void setShowToOwnerOnlyLocked(boolean showToOwnerOnly) { 3026 mShowToOwnerOnly = showToOwnerOnly; 3027 } 3028 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 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 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 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 */ 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 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 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 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 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 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 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 3246 public void unregisterFocusObserver(IWindowFocusObserver observer) { 3247 synchronized(mService.mWindowMap) { 3248 if (mFocusCallbacks != null) { 3249 mFocusCallbacks.unregister(observer); 3250 } 3251 } 3252 } 3253 3254 public boolean isFocused() { 3255 synchronized(mService.mWindowMap) { 3256 return mService.mCurrentFocus == this; 3257 } 3258 } 3259 3260 boolean inFreeformWorkspace() { 3261 final Task task = getTask(); 3262 return task != null && task.inFreeformWorkspace(); 3263 } 3264 3265 @Override 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? */ 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. */ 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. */ 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 3302 boolean isDragResizeChanged() { 3303 return mDragResizing != computeDragResizing(); 3304 } 3305 3306 @Override 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 */ 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 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 */ 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 */ 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 */ 3352 private boolean isResizedWhileNotDragResizingReported() { 3353 return mResizedWhileNotDragResizingReported; 3354 } 3355 3356 int getResizeMode() { 3357 return mResizeMode; 3358 } 3359 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 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 3402 boolean isDragResizing() { 3403 return mDragResizing; 3404 } 3405 3406 boolean isDockedResizing() { 3407 return (mDragResizing && getResizeMode() == DRAG_RESIZE_MODE_DOCKED_DIVIDER) 3408 || (isChildWindow() && getParentWindow().isDockedResizing()); 3409 } 3410 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 3609 String getName() { 3610 return Integer.toHexString(System.identityHashCode(this)) 3611 + " " + getWindowTag(); 3612 } 3613 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 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 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 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 3731 boolean isChildWindow() { 3732 return mIsChildWindow; 3733 } 3734 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 */ 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. */ 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. */ 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 3774 boolean isParentWindowHidden() { 3775 final WindowState parent = getParentWindow(); 3776 return parent != null && parent.mHidden; 3777 } 3778 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 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 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 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 3836 float translateToWindowX(float x) { 3837 float winX = x - mFrame.left; 3838 if (mEnforceSizeCompat) { 3839 winX *= mGlobalScale; 3840 } 3841 return winX; 3842 } 3843 3844 float translateToWindowY(float y) { 3845 float winY = y - mFrame.top; 3846 if (mEnforceSizeCompat) { 3847 winY *= mGlobalScale; 3848 } 3849 return winY; 3850 } 3851 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. 3869 boolean shouldBeReplacedWithChildren() { 3870 return mIsChildWindow || mAttrs.type == TYPE_APPLICATION 3871 || mAttrs.type == TYPE_DRAWN_APPLICATION; 3872 } 3873 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 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 3899 public int getRotationAnimationHint() { 3900 if (mAppToken != null) { 3901 return mAppToken.mRotationAnimationHint; 3902 } else { 3903 return -1; 3904 } 3905 } 3906 3907 @Override 3908 public boolean isInputMethodWindow() { 3909 return mIsImWindow; 3910 } 3911 3912 // This must be called while inside a transaction. 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 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 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 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 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 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 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 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 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 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 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 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 4310 public boolean isRtl() { 4311 return getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL; 4312 } 4313 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 */ 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 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 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 */ 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 */ 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 */ 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 4499 boolean surfaceInsetsChanging() { 4500 return !mLastSurfaceInsets.equals(mAttrs.surfaceInsets); 4501 } 4502 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 */ 4579 boolean isLaidOut() { 4580 return mLayoutSeq != -1; 4581 } 4582 4583 /** 4584 * Updates the last inset values to the current ones. 4585 */ 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 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 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 4625 public void registerFocusObserver(IWindowFocusObserver observer) { 4626 final WindowState outer = mOuter.get(); 4627 if (outer != null) { 4628 outer.registerFocusObserver(observer); 4629 } 4630 } 4631 @Override 4632 public void unregisterFocusObserver(IWindowFocusObserver observer) { 4633 final WindowState outer = mOuter.get(); 4634 if (outer != null) { 4635 outer.unregisterFocusObserver(observer); 4636 } 4637 } 4638 @Override 4639 public boolean isFocused() { 4640 final WindowState outer = mOuter.get(); 4641 return outer != null && outer.isFocused(); 4642 } 4643 } 4644 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