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