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