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