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 android.app.ActivityManager; 20 import android.app.AppOpsManager; 21 import android.content.Context; 22 import android.content.res.Configuration; 23 import android.graphics.Matrix; 24 import android.graphics.PixelFormat; 25 import android.graphics.Point; 26 import android.graphics.Rect; 27 import android.graphics.Region; 28 import android.os.IBinder; 29 import android.os.PowerManager; 30 import android.os.RemoteCallbackList; 31 import android.os.RemoteException; 32 import android.os.SystemClock; 33 import android.os.Trace; 34 import android.os.UserHandle; 35 import android.os.WorkSource; 36 import android.util.DisplayMetrics; 37 import android.util.Slog; 38 import android.util.TimeUtils; 39 import android.view.Display; 40 import android.view.DisplayInfo; 41 import android.view.Gravity; 42 import android.view.IApplicationToken; 43 import android.view.IWindow; 44 import android.view.IWindowFocusObserver; 45 import android.view.IWindowId; 46 import android.view.InputChannel; 47 import android.view.InputEvent; 48 import android.view.InputEventReceiver; 49 import android.view.View; 50 import android.view.ViewTreeObserver; 51 import android.view.WindowManager; 52 import android.view.WindowManagerPolicy; 53 54 import com.android.server.input.InputWindowHandle; 55 56 import java.io.PrintWriter; 57 import java.util.ArrayList; 58 59 import static android.app.ActivityManager.StackId; 60 import static android.app.ActivityManager.StackId.DOCKED_STACK_ID; 61 import static android.app.ActivityManager.StackId.INVALID_STACK_ID; 62 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; 63 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT; 64 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME; 65 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION; 66 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE; 67 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; 68 import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON; 69 import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND; 70 import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD; 71 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS; 72 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 73 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; 74 import static android.view.WindowManager.LayoutParams.FLAG_SCALED; 75 import static android.view.WindowManager.LayoutParams.FLAG_SECURE; 76 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; 77 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; 78 import static android.view.WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON; 79 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW; 80 import static android.view.WindowManager.LayoutParams.MATCH_PARENT; 81 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW; 82 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; 83 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME; 84 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH; 85 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; 86 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST; 87 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; 88 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; 89 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; 90 import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION; 91 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; 92 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; 93 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; 94 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; 95 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 96 import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER; 97 import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM; 98 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE; 99 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM; 100 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS; 101 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_CONFIGURATION; 102 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT; 103 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT; 104 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION; 105 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_POWER; 106 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RESIZE; 107 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; 108 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; 109 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 110 111 class WindowList extends ArrayList<WindowState> { 112 WindowList() {} 113 WindowList(WindowList windowList) { 114 super(windowList); 115 } 116 } 117 118 /** 119 * A window in the window manager. 120 */ 121 final class WindowState implements WindowManagerPolicy.WindowState { 122 static final String TAG = TAG_WITH_CLASS_NAME ? "WindowState" : TAG_WM; 123 124 // The minimal size of a window within the usable area of the freeform stack. 125 // TODO(multi-window): fix the min sizes when we have mininum width/height support, 126 // use hard-coded min sizes for now. 127 static final int MINIMUM_VISIBLE_WIDTH_IN_DP = 48; 128 static final int MINIMUM_VISIBLE_HEIGHT_IN_DP = 32; 129 130 // The thickness of a window resize handle outside the window bounds on the free form workspace 131 // to capture touch events in that area. 132 static final int RESIZE_HANDLE_WIDTH_IN_DP = 30; 133 134 static final boolean DEBUG_DISABLE_SAVING_SURFACES = false; 135 136 final WindowManagerService mService; 137 final WindowManagerPolicy mPolicy; 138 final Context mContext; 139 final Session mSession; 140 final IWindow mClient; 141 final int mAppOp; 142 // UserId and appId of the owner. Don't display windows of non-current user. 143 final int mOwnerUid; 144 final IWindowId mWindowId; 145 WindowToken mToken; 146 WindowToken mRootToken; 147 AppWindowToken mAppToken; 148 AppWindowToken mTargetAppToken; 149 150 // mAttrs.flags is tested in animation without being locked. If the bits tested are ever 151 // modified they will need to be locked. 152 final WindowManager.LayoutParams mAttrs = new WindowManager.LayoutParams(); 153 final DeathRecipient mDeathRecipient; 154 final WindowState mAttachedWindow; 155 final WindowList mChildWindows = new WindowList(); 156 final int mBaseLayer; 157 final int mSubLayer; 158 final boolean mLayoutAttached; 159 final boolean mIsImWindow; 160 final boolean mIsWallpaper; 161 final boolean mIsFloatingLayer; 162 int mSeq; 163 boolean mEnforceSizeCompat; 164 int mViewVisibility; 165 int mSystemUiVisibility; 166 boolean mPolicyVisibility = true; 167 boolean mPolicyVisibilityAfterAnim = true; 168 boolean mAppOpVisibility = true; 169 boolean mPermanentlyHidden; // the window should never be shown again 170 boolean mAppFreezing; 171 boolean mAttachedHidden; // is our parent window hidden? 172 boolean mWallpaperVisible; // for wallpaper, what was last vis report? 173 boolean mDragResizing; 174 boolean mDragResizingChangeReported; 175 int mResizeMode; 176 177 RemoteCallbackList<IWindowFocusObserver> mFocusCallbacks; 178 179 /** 180 * The window size that was requested by the application. These are in 181 * the application's coordinate space (without compatibility scale applied). 182 */ 183 int mRequestedWidth; 184 int mRequestedHeight; 185 int mLastRequestedWidth; 186 int mLastRequestedHeight; 187 188 int mLayer; 189 boolean mHaveFrame; 190 boolean mObscured; 191 boolean mTurnOnScreen; 192 193 int mLayoutSeq = -1; 194 195 private final Configuration mTmpConfig = new Configuration(); 196 // Represents the changes from our override configuration applied 197 // to the global configuration. This is the only form of configuration 198 // which is suitable for delivery to the client. 199 private Configuration mMergedConfiguration = new Configuration(); 200 // Sticky answer to isConfigChanged(), remains true until new Configuration is assigned. 201 // Used only on {@link #TYPE_KEYGUARD}. 202 private boolean mConfigHasChanged; 203 204 /** 205 * Actual position of the surface shown on-screen (may be modified by animation). These are 206 * in the screen's coordinate space (WITH the compatibility scale applied). 207 */ 208 final Point mShownPosition = new Point(); 209 210 /** 211 * Insets that determine the actually visible area. These are in the application's 212 * coordinate space (without compatibility scale applied). 213 */ 214 final Rect mVisibleInsets = new Rect(); 215 final Rect mLastVisibleInsets = new Rect(); 216 boolean mVisibleInsetsChanged; 217 218 /** 219 * Insets that are covered by system windows (such as the status bar) and 220 * transient docking windows (such as the IME). These are in the application's 221 * coordinate space (without compatibility scale applied). 222 */ 223 final Rect mContentInsets = new Rect(); 224 final Rect mLastContentInsets = new Rect(); 225 boolean mContentInsetsChanged; 226 227 /** 228 * Insets that determine the area covered by the display overscan region. These are in the 229 * application's coordinate space (without compatibility scale applied). 230 */ 231 final Rect mOverscanInsets = new Rect(); 232 final Rect mLastOverscanInsets = new Rect(); 233 boolean mOverscanInsetsChanged; 234 235 /** 236 * Insets that determine the area covered by the stable system windows. These are in the 237 * application's coordinate space (without compatibility scale applied). 238 */ 239 final Rect mStableInsets = new Rect(); 240 final Rect mLastStableInsets = new Rect(); 241 boolean mStableInsetsChanged; 242 243 /** 244 * Outsets determine the area outside of the surface where we want to pretend that it's possible 245 * to draw anyway. 246 */ 247 final Rect mOutsets = new Rect(); 248 final Rect mLastOutsets = new Rect(); 249 boolean mOutsetsChanged = false; 250 251 /** 252 * Set to true if we are waiting for this window to receive its 253 * given internal insets before laying out other windows based on it. 254 */ 255 boolean mGivenInsetsPending; 256 257 /** 258 * These are the content insets that were given during layout for 259 * this window, to be applied to windows behind it. 260 */ 261 final Rect mGivenContentInsets = new Rect(); 262 263 /** 264 * These are the visible insets that were given during layout for 265 * this window, to be applied to windows behind it. 266 */ 267 final Rect mGivenVisibleInsets = new Rect(); 268 269 /** 270 * This is the given touchable area relative to the window frame, or null if none. 271 */ 272 final Region mGivenTouchableRegion = new Region(); 273 274 /** 275 * Flag indicating whether the touchable region should be adjusted by 276 * the visible insets; if false the area outside the visible insets is 277 * NOT touchable, so we must use those to adjust the frame during hit 278 * tests. 279 */ 280 int mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME; 281 282 // Current transformation being applied. 283 float mGlobalScale=1; 284 float mInvGlobalScale=1; 285 float mHScale=1, mVScale=1; 286 float mLastHScale=1, mLastVScale=1; 287 final Matrix mTmpMatrix = new Matrix(); 288 289 // "Real" frame that the application sees, in display coordinate space. 290 final Rect mFrame = new Rect(); 291 final Rect mLastFrame = new Rect(); 292 boolean mFrameSizeChanged = false; 293 // Frame that is scaled to the application's coordinate space when in 294 // screen size compatibility mode. 295 final Rect mCompatFrame = new Rect(); 296 297 final Rect mContainingFrame = new Rect(); 298 299 final Rect mParentFrame = new Rect(); 300 301 // The entire screen area of the {@link TaskStack} this window is in. Usually equal to the 302 // screen area of the device. 303 final Rect mDisplayFrame = new Rect(); 304 305 // The region of the display frame that the display type supports displaying content on. This 306 // is mostly a special case for TV where some displays dont have the entire display usable. 307 // {@link WindowManager.LayoutParams#FLAG_LAYOUT_IN_OVERSCAN} flag can be used to allow 308 // window display contents to extend into the overscan region. 309 final Rect mOverscanFrame = new Rect(); 310 311 // The display frame minus the stable insets. This value is always constant regardless of if 312 // the status bar or navigation bar is visible. 313 final Rect mStableFrame = new Rect(); 314 315 // The area not occupied by the status and navigation bars. So, if both status and navigation 316 // bars are visible, the decor frame is equal to the stable frame. 317 final Rect mDecorFrame = new Rect(); 318 319 // Equal to the decor frame if the IME (e.g. keyboard) is not present. Equal to the decor frame 320 // minus the area occupied by the IME if the IME is present. 321 final Rect mContentFrame = new Rect(); 322 323 // Legacy stuff. Generally equal to the content frame expect when the IME for older apps 324 // displays hint text. 325 final Rect mVisibleFrame = new Rect(); 326 327 // Frame that includes dead area outside of the surface but where we want to pretend that it's 328 // possible to draw. 329 final Rect mOutsetFrame = new Rect(); 330 331 /** 332 * Usually empty. Set to the task's tempInsetFrame. See 333 *{@link android.app.IActivityManager#resizeDockedStack}. 334 */ 335 final Rect mInsetFrame = new Rect(); 336 337 private static final Rect sTmpRect = new Rect(); 338 339 boolean mContentChanged; 340 341 // If a window showing a wallpaper: the requested offset for the 342 // wallpaper; if a wallpaper window: the currently applied offset. 343 float mWallpaperX = -1; 344 float mWallpaperY = -1; 345 346 // If a window showing a wallpaper: what fraction of the offset 347 // range corresponds to a full virtual screen. 348 float mWallpaperXStep = -1; 349 float mWallpaperYStep = -1; 350 351 // If a window showing a wallpaper: a raw pixel offset to forcibly apply 352 // to its window; if a wallpaper window: not used. 353 int mWallpaperDisplayOffsetX = Integer.MIN_VALUE; 354 int mWallpaperDisplayOffsetY = Integer.MIN_VALUE; 355 356 // Wallpaper windows: pixels offset based on above variables. 357 int mXOffset; 358 int mYOffset; 359 360 /** 361 * This is set after IWindowSession.relayout() has been called at 362 * least once for the window. It allows us to detect the situation 363 * where we don't yet have a surface, but should have one soon, so 364 * we can give the window focus before waiting for the relayout. 365 */ 366 boolean mRelayoutCalled; 367 368 boolean mInRelayout; 369 370 /** 371 * If the application has called relayout() with changes that can 372 * impact its window's size, we need to perform a layout pass on it 373 * even if it is not currently visible for layout. This is set 374 * when in that case until the layout is done. 375 */ 376 boolean mLayoutNeeded; 377 378 /** Currently running an exit animation? */ 379 boolean mAnimatingExit; 380 381 /** Currently on the mDestroySurface list? */ 382 boolean mDestroying; 383 384 /** Completely remove from window manager after exit animation? */ 385 boolean mRemoveOnExit; 386 387 /** 388 * Whether the app died while it was visible, if true we might need 389 * to continue to show it until it's restarted. 390 */ 391 boolean mAppDied; 392 393 /** 394 * Set when the orientation is changing and this window has not yet 395 * been updated for the new orientation. 396 */ 397 boolean mOrientationChanging; 398 399 /** 400 * The orientation during the last visible call to relayout. If our 401 * current orientation is different, the window can't be ready 402 * to be shown. 403 */ 404 int mLastVisibleLayoutRotation = -1; 405 406 /** 407 * How long we last kept the screen frozen. 408 */ 409 int mLastFreezeDuration; 410 411 /** Is this window now (or just being) removed? */ 412 boolean mRemoved; 413 414 /** 415 * It is save to remove the window and destroy the surface because the client requested removal 416 * or some other higher level component said so (e.g. activity manager). 417 * TODO: We should either have different booleans for the removal reason or use a bit-field. 418 */ 419 boolean mWindowRemovalAllowed; 420 421 /** 422 * Temp for keeping track of windows that have been removed when 423 * rebuilding window list. 424 */ 425 boolean mRebuilding; 426 427 // Input channel and input window handle used by the input dispatcher. 428 final InputWindowHandle mInputWindowHandle; 429 InputChannel mInputChannel; 430 InputChannel mClientChannel; 431 432 // Used to improve performance of toString() 433 String mStringNameCache; 434 CharSequence mLastTitle; 435 boolean mWasExiting; 436 437 final WindowStateAnimator mWinAnimator; 438 439 boolean mHasSurface = false; 440 441 boolean mNotOnAppsDisplay = false; 442 DisplayContent mDisplayContent; 443 444 /** When true this window can be displayed on screens owther than mOwnerUid's */ 445 private boolean mShowToOwnerOnly; 446 447 // Whether the window has a saved surface from last pause, which can be 448 // used to start an entering animation earlier. 449 private boolean mSurfaceSaved = false; 450 451 // Whether we're performing an entering animation with a saved surface. This flag is 452 // true during the time we're showing a window with a previously saved surface. It's 453 // cleared when surface is destroyed, saved, or re-drawn by the app. 454 private boolean mAnimatingWithSavedSurface; 455 456 // Whether the window was visible when we set the app to invisible last time. WM uses 457 // this as a hint to restore the surface (if available) for early animation next time 458 // the app is brought visible. 459 boolean mWasVisibleBeforeClientHidden; 460 461 // This window will be replaced due to relaunch. This allows window manager 462 // to differentiate between simple removal of a window and replacement. In the latter case it 463 // will preserve the old window until the new one is drawn. 464 boolean mWillReplaceWindow = false; 465 // If true, the replaced window was already requested to be removed. 466 boolean mReplacingRemoveRequested = false; 467 // Whether the replacement of the window should trigger app transition animation. 468 boolean mAnimateReplacingWindow = false; 469 // If not null, the window that will be used to replace the old one. This is being set when 470 // the window is added and unset when this window reports its first draw. 471 WindowState mReplacingWindow = null; 472 // For the new window in the replacement transition, if we have 473 // requested to replace without animation, then we should 474 // make sure we also don't apply an enter animation for 475 // the new window. 476 boolean mSkipEnterAnimationForSeamlessReplacement = false; 477 // Whether this window is being moved via the resize API 478 boolean mMovedByResize; 479 480 /** 481 * Wake lock for drawing. 482 * Even though it's slightly more expensive to do so, we will use a separate wake lock 483 * for each app that is requesting to draw while dozing so that we can accurately track 484 * who is preventing the system from suspending. 485 * This lock is only acquired on first use. 486 */ 487 PowerManager.WakeLock mDrawLock; 488 489 final private Rect mTmpRect = new Rect(); 490 491 /** 492 * See {@link #notifyMovedInStack}. 493 */ 494 private boolean mJustMovedInStack; 495 496 /** 497 * Whether the window was resized by us while it was gone for layout. 498 */ 499 boolean mResizedWhileGone = false; 500 501 /** @see #isResizedWhileNotDragResizing(). */ 502 private boolean mResizedWhileNotDragResizing; 503 504 /** @see #isResizedWhileNotDragResizingReported(). */ 505 private boolean mResizedWhileNotDragResizingReported; 506 507 /** 508 * During seamless rotation we have two phases, first the old window contents 509 * are rotated to look as if they didn't move in the new coordinate system. Then we 510 * have to freeze updates to this layer (to preserve the transformation) until 511 * the resize actually occurs. This is true from when the transformation is set 512 * and false until the transaction to resize is sent. 513 */ 514 boolean mSeamlesslyRotated = false; 515 516 WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token, 517 WindowState attachedWindow, int appOp, int seq, WindowManager.LayoutParams a, 518 int viewVisibility, final DisplayContent displayContent) { 519 mService = service; 520 mSession = s; 521 mClient = c; 522 mAppOp = appOp; 523 mToken = token; 524 mOwnerUid = s.mUid; 525 mWindowId = new IWindowId.Stub() { 526 @Override 527 public void registerFocusObserver(IWindowFocusObserver observer) { 528 WindowState.this.registerFocusObserver(observer); 529 } 530 @Override 531 public void unregisterFocusObserver(IWindowFocusObserver observer) { 532 WindowState.this.unregisterFocusObserver(observer); 533 } 534 @Override 535 public boolean isFocused() { 536 return WindowState.this.isFocused(); 537 } 538 }; 539 mAttrs.copyFrom(a); 540 mViewVisibility = viewVisibility; 541 mDisplayContent = displayContent; 542 mPolicy = mService.mPolicy; 543 mContext = mService.mContext; 544 DeathRecipient deathRecipient = new DeathRecipient(); 545 mSeq = seq; 546 mEnforceSizeCompat = (mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0; 547 if (WindowManagerService.localLOGV) Slog.v( 548 TAG, "Window " + this + " client=" + c.asBinder() 549 + " token=" + token + " (" + mAttrs.token + ")" + " params=" + a); 550 try { 551 c.asBinder().linkToDeath(deathRecipient, 0); 552 } catch (RemoteException e) { 553 mDeathRecipient = null; 554 mAttachedWindow = null; 555 mLayoutAttached = false; 556 mIsImWindow = false; 557 mIsWallpaper = false; 558 mIsFloatingLayer = false; 559 mBaseLayer = 0; 560 mSubLayer = 0; 561 mInputWindowHandle = null; 562 mWinAnimator = null; 563 return; 564 } 565 mDeathRecipient = deathRecipient; 566 567 if ((mAttrs.type >= FIRST_SUB_WINDOW && 568 mAttrs.type <= LAST_SUB_WINDOW)) { 569 // The multiplier here is to reserve space for multiple 570 // windows in the same type layer. 571 mBaseLayer = mPolicy.windowTypeToLayerLw( 572 attachedWindow.mAttrs.type) * WindowManagerService.TYPE_LAYER_MULTIPLIER 573 + WindowManagerService.TYPE_LAYER_OFFSET; 574 mSubLayer = mPolicy.subWindowTypeToLayerLw(a.type); 575 mAttachedWindow = attachedWindow; 576 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + this + " to " + mAttachedWindow); 577 578 final WindowList childWindows = mAttachedWindow.mChildWindows; 579 final int numChildWindows = childWindows.size(); 580 if (numChildWindows == 0) { 581 childWindows.add(this); 582 } else { 583 boolean added = false; 584 for (int i = 0; i < numChildWindows; i++) { 585 final int childSubLayer = childWindows.get(i).mSubLayer; 586 if (mSubLayer < childSubLayer 587 || (mSubLayer == childSubLayer && childSubLayer < 0)) { 588 // We insert the child window into the list ordered by the sub-layer. For 589 // same sub-layers, the negative one should go below others; the positive 590 // one should go above others. 591 childWindows.add(i, this); 592 added = true; 593 break; 594 } 595 } 596 if (!added) { 597 childWindows.add(this); 598 } 599 } 600 601 mLayoutAttached = mAttrs.type != 602 WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; 603 mIsImWindow = attachedWindow.mAttrs.type == TYPE_INPUT_METHOD 604 || attachedWindow.mAttrs.type == TYPE_INPUT_METHOD_DIALOG; 605 mIsWallpaper = attachedWindow.mAttrs.type == TYPE_WALLPAPER; 606 mIsFloatingLayer = mIsImWindow || mIsWallpaper; 607 } else { 608 // The multiplier here is to reserve space for multiple 609 // windows in the same type layer. 610 mBaseLayer = mPolicy.windowTypeToLayerLw(a.type) 611 * WindowManagerService.TYPE_LAYER_MULTIPLIER 612 + WindowManagerService.TYPE_LAYER_OFFSET; 613 mSubLayer = 0; 614 mAttachedWindow = null; 615 mLayoutAttached = false; 616 mIsImWindow = mAttrs.type == TYPE_INPUT_METHOD 617 || mAttrs.type == TYPE_INPUT_METHOD_DIALOG; 618 mIsWallpaper = mAttrs.type == TYPE_WALLPAPER; 619 mIsFloatingLayer = mIsImWindow || mIsWallpaper; 620 } 621 622 WindowState appWin = this; 623 while (appWin.isChildWindow()) { 624 appWin = appWin.mAttachedWindow; 625 } 626 WindowToken appToken = appWin.mToken; 627 while (appToken.appWindowToken == null) { 628 WindowToken parent = mService.mTokenMap.get(appToken.token); 629 if (parent == null || appToken == parent) { 630 break; 631 } 632 appToken = parent; 633 } 634 mRootToken = appToken; 635 mAppToken = appToken.appWindowToken; 636 if (mAppToken != null) { 637 final DisplayContent appDisplay = getDisplayContent(); 638 mNotOnAppsDisplay = displayContent != appDisplay; 639 640 if (mAppToken.showForAllUsers) { 641 // Windows for apps that can show for all users should also show when the 642 // device is locked. 643 mAttrs.flags |= FLAG_SHOW_WHEN_LOCKED; 644 } 645 } 646 647 mWinAnimator = new WindowStateAnimator(this); 648 mWinAnimator.mAlpha = a.alpha; 649 650 mRequestedWidth = 0; 651 mRequestedHeight = 0; 652 mLastRequestedWidth = 0; 653 mLastRequestedHeight = 0; 654 mXOffset = 0; 655 mYOffset = 0; 656 mLayer = 0; 657 mInputWindowHandle = new InputWindowHandle( 658 mAppToken != null ? mAppToken.mInputApplicationHandle : null, this, 659 displayContent.getDisplayId()); 660 } 661 662 void attach() { 663 if (WindowManagerService.localLOGV) Slog.v( 664 TAG, "Attaching " + this + " token=" + mToken 665 + ", list=" + mToken.windows); 666 mSession.windowAddedLocked(); 667 } 668 669 @Override 670 public int getOwningUid() { 671 return mOwnerUid; 672 } 673 674 @Override 675 public String getOwningPackage() { 676 return mAttrs.packageName; 677 } 678 679 /** 680 * Subtracts the insets calculated by intersecting {@param layoutFrame} with {@param insetFrame} 681 * from {@param frame}. In other words, it applies the insets that would result if 682 * {@param frame} would be shifted to {@param layoutFrame} and then applying the insets from 683 * {@param insetFrame}. Also it respects {@param displayFrame} in case window has minimum 684 * width/height applied and insets should be overridden. 685 */ 686 private void subtractInsets(Rect frame, Rect layoutFrame, Rect insetFrame, Rect displayFrame) { 687 final int left = Math.max(0, insetFrame.left - Math.max(layoutFrame.left, displayFrame.left)); 688 final int top = Math.max(0, insetFrame.top - Math.max(layoutFrame.top, displayFrame.top)); 689 final int right = Math.max(0, Math.min(layoutFrame.right, displayFrame.right) - insetFrame.right); 690 final int bottom = Math.max(0, Math.min(layoutFrame.bottom, displayFrame.bottom) - insetFrame.bottom); 691 frame.inset(left, top, right, bottom); 692 } 693 694 @Override 695 public void computeFrameLw(Rect pf, Rect df, Rect of, Rect cf, Rect vf, Rect dcf, Rect sf, 696 Rect osf) { 697 if (mWillReplaceWindow && (mAnimatingExit || !mReplacingRemoveRequested)) { 698 // This window is being replaced and either already got information that it's being 699 // removed or we are still waiting for some information. Because of this we don't 700 // want to apply any more changes to it, so it remains in this state until new window 701 // appears. 702 return; 703 } 704 mHaveFrame = true; 705 706 final Task task = getTask(); 707 final boolean fullscreenTask = !isInMultiWindowMode(); 708 final boolean windowsAreFloating = task != null && task.isFloating(); 709 710 // If the task has temp inset bounds set, we have to make sure all its windows uses 711 // the temp inset frame. Otherwise different display frames get applied to the main 712 // window and the child window, making them misaligned. 713 if (fullscreenTask) { 714 mInsetFrame.setEmpty(); 715 } else { 716 task.getTempInsetBounds(mInsetFrame); 717 } 718 719 // Denotes the actual frame used to calculate the insets and to perform the layout. When 720 // resizing in docked mode, we'd like to freeze the layout, so we also need to freeze the 721 // insets temporarily. By the notion of a task having a different layout frame, we can 722 // achieve that while still moving the task around. 723 final Rect layoutContainingFrame; 724 final Rect layoutDisplayFrame; 725 726 // The offset from the layout containing frame to the actual containing frame. 727 final int layoutXDiff; 728 final int layoutYDiff; 729 if (fullscreenTask || layoutInParentFrame()) { 730 // We use the parent frame as the containing frame for fullscreen and child windows 731 mContainingFrame.set(pf); 732 mDisplayFrame.set(df); 733 layoutDisplayFrame = df; 734 layoutContainingFrame = pf; 735 layoutXDiff = 0; 736 layoutYDiff = 0; 737 } else { 738 task.getBounds(mContainingFrame); 739 if (mAppToken != null && !mAppToken.mFrozenBounds.isEmpty()) { 740 741 // If the bounds are frozen, we still want to translate the window freely and only 742 // freeze the size. 743 Rect frozen = mAppToken.mFrozenBounds.peek(); 744 mContainingFrame.right = mContainingFrame.left + frozen.width(); 745 mContainingFrame.bottom = mContainingFrame.top + frozen.height(); 746 } 747 final WindowState imeWin = mService.mInputMethodWindow; 748 // IME is up and obscuring this window. Adjust the window position so it is visible. 749 if (imeWin != null && imeWin.isVisibleNow() && mService.mInputMethodTarget == this) { 750 if (windowsAreFloating && mContainingFrame.bottom > cf.bottom) { 751 // In freeform we want to move the top up directly. 752 // TODO: Investigate why this is cf not pf. 753 mContainingFrame.top -= mContainingFrame.bottom - cf.bottom; 754 } else if (mContainingFrame.bottom > pf.bottom) { 755 // But in docked we want to behave like fullscreen 756 // and behave as if the task were given smaller bounds 757 // for the purposes of layout. 758 mContainingFrame.bottom = pf.bottom; 759 } 760 } 761 762 if (windowsAreFloating) { 763 // In floating modes (e.g. freeform, pinned) we have only to set the rectangle 764 // if it wasn't set already. No need to intersect it with the (visible) 765 // "content frame" since it is allowed to be outside the visible desktop. 766 if (mContainingFrame.isEmpty()) { 767 mContainingFrame.set(cf); 768 } 769 } 770 mDisplayFrame.set(mContainingFrame); 771 layoutXDiff = !mInsetFrame.isEmpty() ? mInsetFrame.left - mContainingFrame.left : 0; 772 layoutYDiff = !mInsetFrame.isEmpty() ? mInsetFrame.top - mContainingFrame.top : 0; 773 layoutContainingFrame = !mInsetFrame.isEmpty() ? mInsetFrame : mContainingFrame; 774 mTmpRect.set(0, 0, mDisplayContent.getDisplayInfo().logicalWidth, 775 mDisplayContent.getDisplayInfo().logicalHeight); 776 subtractInsets(mDisplayFrame, layoutContainingFrame, df, mTmpRect); 777 if (!layoutInParentFrame()) { 778 subtractInsets(mContainingFrame, layoutContainingFrame, pf, mTmpRect); 779 subtractInsets(mInsetFrame, layoutContainingFrame, pf, mTmpRect); 780 } 781 layoutDisplayFrame = df; 782 layoutDisplayFrame.intersect(layoutContainingFrame); 783 } 784 785 final int pw = mContainingFrame.width(); 786 final int ph = mContainingFrame.height(); 787 788 if (!mParentFrame.equals(pf)) { 789 //Slog.i(TAG_WM, "Window " + this + " content frame from " + mParentFrame 790 // + " to " + pf); 791 mParentFrame.set(pf); 792 mContentChanged = true; 793 } 794 if (mRequestedWidth != mLastRequestedWidth || mRequestedHeight != mLastRequestedHeight) { 795 mLastRequestedWidth = mRequestedWidth; 796 mLastRequestedHeight = mRequestedHeight; 797 mContentChanged = true; 798 } 799 800 mOverscanFrame.set(of); 801 mContentFrame.set(cf); 802 mVisibleFrame.set(vf); 803 mDecorFrame.set(dcf); 804 mStableFrame.set(sf); 805 final boolean hasOutsets = osf != null; 806 if (hasOutsets) { 807 mOutsetFrame.set(osf); 808 } 809 810 final int fw = mFrame.width(); 811 final int fh = mFrame.height(); 812 813 applyGravityAndUpdateFrame(layoutContainingFrame, layoutDisplayFrame); 814 815 // Calculate the outsets before the content frame gets shrinked to the window frame. 816 if (hasOutsets) { 817 mOutsets.set(Math.max(mContentFrame.left - mOutsetFrame.left, 0), 818 Math.max(mContentFrame.top - mOutsetFrame.top, 0), 819 Math.max(mOutsetFrame.right - mContentFrame.right, 0), 820 Math.max(mOutsetFrame.bottom - mContentFrame.bottom, 0)); 821 } else { 822 mOutsets.set(0, 0, 0, 0); 823 } 824 825 // Make sure the content and visible frames are inside of the 826 // final window frame. 827 if (windowsAreFloating && !mFrame.isEmpty()) { 828 // Keep the frame out of the blocked system area, limit it in size to the content area 829 // and make sure that there is always a minimum visible so that the user can drag it 830 // into a usable area.. 831 final int height = Math.min(mFrame.height(), mContentFrame.height()); 832 final int width = Math.min(mContentFrame.width(), mFrame.width()); 833 final DisplayMetrics displayMetrics = getDisplayContent().getDisplayMetrics(); 834 final int minVisibleHeight = Math.min(height, WindowManagerService.dipToPixel( 835 MINIMUM_VISIBLE_HEIGHT_IN_DP, displayMetrics)); 836 final int minVisibleWidth = Math.min(width, WindowManagerService.dipToPixel( 837 MINIMUM_VISIBLE_WIDTH_IN_DP, displayMetrics)); 838 final int top = Math.max(mContentFrame.top, 839 Math.min(mFrame.top, mContentFrame.bottom - minVisibleHeight)); 840 final int left = Math.max(mContentFrame.left + minVisibleWidth - width, 841 Math.min(mFrame.left, mContentFrame.right - minVisibleWidth)); 842 mFrame.set(left, top, left + width, top + height); 843 mContentFrame.set(mFrame); 844 mVisibleFrame.set(mContentFrame); 845 mStableFrame.set(mContentFrame); 846 } else if (mAttrs.type == TYPE_DOCK_DIVIDER) { 847 mDisplayContent.getDockedDividerController().positionDockedStackedDivider(mFrame); 848 mContentFrame.set(mFrame); 849 if (!mFrame.equals(mLastFrame)) { 850 mMovedByResize = true; 851 } 852 } else { 853 mContentFrame.set(Math.max(mContentFrame.left, mFrame.left), 854 Math.max(mContentFrame.top, mFrame.top), 855 Math.min(mContentFrame.right, mFrame.right), 856 Math.min(mContentFrame.bottom, mFrame.bottom)); 857 858 mVisibleFrame.set(Math.max(mVisibleFrame.left, mFrame.left), 859 Math.max(mVisibleFrame.top, mFrame.top), 860 Math.min(mVisibleFrame.right, mFrame.right), 861 Math.min(mVisibleFrame.bottom, mFrame.bottom)); 862 863 mStableFrame.set(Math.max(mStableFrame.left, mFrame.left), 864 Math.max(mStableFrame.top, mFrame.top), 865 Math.min(mStableFrame.right, mFrame.right), 866 Math.min(mStableFrame.bottom, mFrame.bottom)); 867 } 868 869 if (fullscreenTask && !windowsAreFloating) { 870 // Windows that are not fullscreen can be positioned outside of the display frame, 871 // but that is not a reason to provide them with overscan insets. 872 mOverscanInsets.set(Math.max(mOverscanFrame.left - layoutContainingFrame.left, 0), 873 Math.max(mOverscanFrame.top - layoutContainingFrame.top, 0), 874 Math.max(layoutContainingFrame.right - mOverscanFrame.right, 0), 875 Math.max(layoutContainingFrame.bottom - mOverscanFrame.bottom, 0)); 876 } 877 878 if (mAttrs.type == TYPE_DOCK_DIVIDER) { 879 // For the docked divider, we calculate the stable insets like a full-screen window 880 // so it can use it to calculate the snap positions. 881 mStableInsets.set(Math.max(mStableFrame.left - mDisplayFrame.left, 0), 882 Math.max(mStableFrame.top - mDisplayFrame.top, 0), 883 Math.max(mDisplayFrame.right - mStableFrame.right, 0), 884 Math.max(mDisplayFrame.bottom - mStableFrame.bottom, 0)); 885 886 // The divider doesn't care about insets in any case, so set it to empty so we don't 887 // trigger a relayout when moving it. 888 mContentInsets.setEmpty(); 889 mVisibleInsets.setEmpty(); 890 } else { 891 getDisplayContent().getLogicalDisplayRect(mTmpRect); 892 // Override right and/or bottom insets in case if the frame doesn't fit the screen in 893 // non-fullscreen mode. 894 boolean overrideRightInset = !fullscreenTask && mFrame.right > mTmpRect.right; 895 boolean overrideBottomInset = !fullscreenTask && mFrame.bottom > mTmpRect.bottom; 896 mContentInsets.set(mContentFrame.left - mFrame.left, 897 mContentFrame.top - mFrame.top, 898 overrideRightInset ? mTmpRect.right - mContentFrame.right 899 : mFrame.right - mContentFrame.right, 900 overrideBottomInset ? mTmpRect.bottom - mContentFrame.bottom 901 : mFrame.bottom - mContentFrame.bottom); 902 903 mVisibleInsets.set(mVisibleFrame.left - mFrame.left, 904 mVisibleFrame.top - mFrame.top, 905 overrideRightInset ? mTmpRect.right - mVisibleFrame.right 906 : mFrame.right - mVisibleFrame.right, 907 overrideBottomInset ? mTmpRect.bottom - mVisibleFrame.bottom 908 : mFrame.bottom - mVisibleFrame.bottom); 909 910 mStableInsets.set(Math.max(mStableFrame.left - mFrame.left, 0), 911 Math.max(mStableFrame.top - mFrame.top, 0), 912 overrideRightInset ? Math.max(mTmpRect.right - mStableFrame.right, 0) 913 : Math.max(mFrame.right - mStableFrame.right, 0), 914 overrideBottomInset ? Math.max(mTmpRect.bottom - mStableFrame.bottom, 0) 915 : Math.max(mFrame.bottom - mStableFrame.bottom, 0)); 916 } 917 918 // Offset the actual frame by the amount layout frame is off. 919 mFrame.offset(-layoutXDiff, -layoutYDiff); 920 mCompatFrame.offset(-layoutXDiff, -layoutYDiff); 921 mContentFrame.offset(-layoutXDiff, -layoutYDiff); 922 mVisibleFrame.offset(-layoutXDiff, -layoutYDiff); 923 mStableFrame.offset(-layoutXDiff, -layoutYDiff); 924 925 mCompatFrame.set(mFrame); 926 if (mEnforceSizeCompat) { 927 // If there is a size compatibility scale being applied to the 928 // window, we need to apply this to its insets so that they are 929 // reported to the app in its coordinate space. 930 mOverscanInsets.scale(mInvGlobalScale); 931 mContentInsets.scale(mInvGlobalScale); 932 mVisibleInsets.scale(mInvGlobalScale); 933 mStableInsets.scale(mInvGlobalScale); 934 mOutsets.scale(mInvGlobalScale); 935 936 // Also the scaled frame that we report to the app needs to be 937 // adjusted to be in its coordinate space. 938 mCompatFrame.scale(mInvGlobalScale); 939 } 940 941 if (mIsWallpaper && (fw != mFrame.width() || fh != mFrame.height())) { 942 final DisplayContent displayContent = getDisplayContent(); 943 if (displayContent != null) { 944 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 945 mService.mWallpaperControllerLocked.updateWallpaperOffset( 946 this, displayInfo.logicalWidth, displayInfo.logicalHeight, false); 947 } 948 } 949 950 if (DEBUG_LAYOUT || WindowManagerService.localLOGV) Slog.v(TAG, 951 "Resolving (mRequestedWidth=" 952 + mRequestedWidth + ", mRequestedheight=" 953 + mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph 954 + "): frame=" + mFrame.toShortString() 955 + " ci=" + mContentInsets.toShortString() 956 + " vi=" + mVisibleInsets.toShortString() 957 + " si=" + mStableInsets.toShortString() 958 + " of=" + mOutsets.toShortString()); 959 } 960 961 @Override 962 public Rect getFrameLw() { 963 return mFrame; 964 } 965 966 @Override 967 public Point getShownPositionLw() { 968 return mShownPosition; 969 } 970 971 @Override 972 public Rect getDisplayFrameLw() { 973 return mDisplayFrame; 974 } 975 976 @Override 977 public Rect getOverscanFrameLw() { 978 return mOverscanFrame; 979 } 980 981 @Override 982 public Rect getContentFrameLw() { 983 return mContentFrame; 984 } 985 986 @Override 987 public Rect getVisibleFrameLw() { 988 return mVisibleFrame; 989 } 990 991 @Override 992 public boolean getGivenInsetsPendingLw() { 993 return mGivenInsetsPending; 994 } 995 996 @Override 997 public Rect getGivenContentInsetsLw() { 998 return mGivenContentInsets; 999 } 1000 1001 @Override 1002 public Rect getGivenVisibleInsetsLw() { 1003 return mGivenVisibleInsets; 1004 } 1005 1006 @Override 1007 public WindowManager.LayoutParams getAttrs() { 1008 return mAttrs; 1009 } 1010 1011 @Override 1012 public boolean getNeedsMenuLw(WindowManagerPolicy.WindowState bottom) { 1013 int index = -1; 1014 WindowState ws = this; 1015 WindowList windows = getWindowList(); 1016 while (true) { 1017 if (ws.mAttrs.needsMenuKey != WindowManager.LayoutParams.NEEDS_MENU_UNSET) { 1018 return ws.mAttrs.needsMenuKey == WindowManager.LayoutParams.NEEDS_MENU_SET_TRUE; 1019 } 1020 // If we reached the bottom of the range of windows we are considering, 1021 // assume no menu is needed. 1022 if (ws == bottom) { 1023 return false; 1024 } 1025 // The current window hasn't specified whether menu key is needed; 1026 // look behind it. 1027 // First, we may need to determine the starting position. 1028 if (index < 0) { 1029 index = windows.indexOf(ws); 1030 } 1031 index--; 1032 if (index < 0) { 1033 return false; 1034 } 1035 ws = windows.get(index); 1036 } 1037 } 1038 1039 @Override 1040 public int getSystemUiVisibility() { 1041 return mSystemUiVisibility; 1042 } 1043 1044 @Override 1045 public int getSurfaceLayer() { 1046 return mLayer; 1047 } 1048 1049 @Override 1050 public int getBaseType() { 1051 WindowState win = this; 1052 while (win.isChildWindow()) { 1053 win = win.mAttachedWindow; 1054 } 1055 return win.mAttrs.type; 1056 } 1057 1058 @Override 1059 public IApplicationToken getAppToken() { 1060 return mAppToken != null ? mAppToken.appToken : null; 1061 } 1062 1063 @Override 1064 public boolean isVoiceInteraction() { 1065 return mAppToken != null && mAppToken.voiceInteraction; 1066 } 1067 1068 boolean setReportResizeHints() { 1069 mOverscanInsetsChanged |= !mLastOverscanInsets.equals(mOverscanInsets); 1070 mContentInsetsChanged |= !mLastContentInsets.equals(mContentInsets); 1071 mVisibleInsetsChanged |= !mLastVisibleInsets.equals(mVisibleInsets); 1072 mStableInsetsChanged |= !mLastStableInsets.equals(mStableInsets); 1073 mOutsetsChanged |= !mLastOutsets.equals(mOutsets); 1074 mFrameSizeChanged |= (mLastFrame.width() != mFrame.width()) || 1075 (mLastFrame.height() != mFrame.height()); 1076 return mOverscanInsetsChanged || mContentInsetsChanged || mVisibleInsetsChanged 1077 || mOutsetsChanged || mFrameSizeChanged; 1078 } 1079 1080 public DisplayContent getDisplayContent() { 1081 if (mAppToken == null || mNotOnAppsDisplay) { 1082 return mDisplayContent; 1083 } 1084 final TaskStack stack = getStack(); 1085 return stack == null ? mDisplayContent : stack.getDisplayContent(); 1086 } 1087 1088 public DisplayInfo getDisplayInfo() { 1089 final DisplayContent displayContent = getDisplayContent(); 1090 return displayContent != null ? displayContent.getDisplayInfo() : null; 1091 } 1092 1093 public int getDisplayId() { 1094 final DisplayContent displayContent = getDisplayContent(); 1095 if (displayContent == null) { 1096 return -1; 1097 } 1098 return displayContent.getDisplayId(); 1099 } 1100 1101 Task getTask() { 1102 return mAppToken != null ? mAppToken.mTask : null; 1103 } 1104 1105 TaskStack getStack() { 1106 Task task = getTask(); 1107 if (task != null) { 1108 if (task.mStack != null) { 1109 return task.mStack; 1110 } 1111 } 1112 // Some system windows (e.g. "Power off" dialog) don't have a task, but we would still 1113 // associate them with some stack to enable dimming. 1114 return mAttrs.type >= WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW 1115 && mDisplayContent != null ? mDisplayContent.getHomeStack() : null; 1116 } 1117 1118 /** 1119 * Retrieves the visible bounds of the window. 1120 * @param bounds The rect which gets the bounds. 1121 */ 1122 void getVisibleBounds(Rect bounds) { 1123 final Task task = getTask(); 1124 boolean intersectWithStackBounds = task != null && task.cropWindowsToStackBounds(); 1125 bounds.setEmpty(); 1126 mTmpRect.setEmpty(); 1127 if (intersectWithStackBounds) { 1128 final TaskStack stack = task.mStack; 1129 if (stack != null) { 1130 stack.getDimBounds(mTmpRect); 1131 } else { 1132 intersectWithStackBounds = false; 1133 } 1134 } 1135 1136 bounds.set(mVisibleFrame); 1137 if (intersectWithStackBounds) { 1138 bounds.intersect(mTmpRect); 1139 } 1140 1141 if (bounds.isEmpty()) { 1142 bounds.set(mFrame); 1143 if (intersectWithStackBounds) { 1144 bounds.intersect(mTmpRect); 1145 } 1146 return; 1147 } 1148 } 1149 1150 public long getInputDispatchingTimeoutNanos() { 1151 return mAppToken != null 1152 ? mAppToken.inputDispatchingTimeoutNanos 1153 : WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; 1154 } 1155 1156 @Override 1157 public boolean hasAppShownWindows() { 1158 return mAppToken != null && (mAppToken.firstWindowDrawn || mAppToken.startingDisplayed); 1159 } 1160 1161 boolean isIdentityMatrix(float dsdx, float dtdx, float dsdy, float dtdy) { 1162 if (dsdx < .99999f || dsdx > 1.00001f) return false; 1163 if (dtdy < .99999f || dtdy > 1.00001f) return false; 1164 if (dtdx < -.000001f || dtdx > .000001f) return false; 1165 if (dsdy < -.000001f || dsdy > .000001f) return false; 1166 return true; 1167 } 1168 1169 void prelayout() { 1170 if (mEnforceSizeCompat) { 1171 mGlobalScale = mService.mCompatibleScreenScale; 1172 mInvGlobalScale = 1/mGlobalScale; 1173 } else { 1174 mGlobalScale = mInvGlobalScale = 1; 1175 } 1176 } 1177 1178 /** 1179 * Does the minimal check for visibility. Callers generally want to use one of the public 1180 * methods as they perform additional checks on the app token. 1181 * TODO: See if there are other places we can use this check below instead of duplicating... 1182 */ 1183 private boolean isVisibleUnchecked() { 1184 return mHasSurface && mPolicyVisibility && !mAttachedHidden 1185 && !mAnimatingExit && !mDestroying && (!mIsWallpaper || mWallpaperVisible); 1186 } 1187 1188 /** 1189 * Is this window visible? It is not visible if there is no surface, or we are in the process 1190 * of running an exit animation that will remove the surface, or its app token has been hidden. 1191 */ 1192 @Override 1193 public boolean isVisibleLw() { 1194 return (mAppToken == null || !mAppToken.hiddenRequested) && isVisibleUnchecked(); 1195 } 1196 1197 /** 1198 * Like {@link #isVisibleLw}, but also counts a window that is currently "hidden" behind the 1199 * keyguard as visible. This allows us to apply things like window flags that impact the 1200 * keyguard. XXX I am starting to think we need to have ANOTHER visibility flag for this 1201 * "hidden behind keyguard" state rather than overloading mPolicyVisibility. Ungh. 1202 */ 1203 @Override 1204 public boolean isVisibleOrBehindKeyguardLw() { 1205 if (mRootToken.waitingToShow && mService.mAppTransition.isTransitionSet()) { 1206 return false; 1207 } 1208 final AppWindowToken atoken = mAppToken; 1209 final boolean animating = atoken != null && atoken.mAppAnimator.animation != null; 1210 return mHasSurface && !mDestroying && !mAnimatingExit 1211 && (atoken == null ? mPolicyVisibility : !atoken.hiddenRequested) 1212 && ((!mAttachedHidden && mViewVisibility == View.VISIBLE && !mRootToken.hidden) 1213 || mWinAnimator.mAnimation != null || animating); 1214 } 1215 1216 /** 1217 * Is this window visible, ignoring its app token? It is not visible if there is no surface, 1218 * or we are in the process of running an exit animation that will remove the surface. 1219 */ 1220 public boolean isWinVisibleLw() { 1221 return (mAppToken == null || !mAppToken.hiddenRequested || mAppToken.mAppAnimator.animating) 1222 && isVisibleUnchecked(); 1223 } 1224 1225 /** 1226 * The same as isVisible(), but follows the current hidden state of the associated app token, 1227 * not the pending requested hidden state. 1228 */ 1229 boolean isVisibleNow() { 1230 return (!mRootToken.hidden || mAttrs.type == TYPE_APPLICATION_STARTING) 1231 && isVisibleUnchecked(); 1232 } 1233 1234 /** 1235 * Can this window possibly be a drag/drop target? The test here is 1236 * a combination of the above "visible now" with the check that the 1237 * Input Manager uses when discarding windows from input consideration. 1238 */ 1239 boolean isPotentialDragTarget() { 1240 return isVisibleNow() && !mRemoved 1241 && mInputChannel != null && mInputWindowHandle != null; 1242 } 1243 1244 /** 1245 * Same as isVisible(), but we also count it as visible between the 1246 * call to IWindowSession.add() and the first relayout(). 1247 */ 1248 boolean isVisibleOrAdding() { 1249 final AppWindowToken atoken = mAppToken; 1250 return (mHasSurface || (!mRelayoutCalled && mViewVisibility == View.VISIBLE)) 1251 && mPolicyVisibility && !mAttachedHidden 1252 && (atoken == null || !atoken.hiddenRequested) 1253 && !mAnimatingExit && !mDestroying; 1254 } 1255 1256 /** 1257 * Is this window currently on-screen? It is on-screen either if it 1258 * is visible or it is currently running an animation before no longer 1259 * being visible. 1260 */ 1261 boolean isOnScreen() { 1262 return mPolicyVisibility && isOnScreenIgnoringKeyguard(); 1263 } 1264 1265 /** 1266 * Like isOnScreen(), but ignores any force hiding of the window due 1267 * to the keyguard. 1268 */ 1269 boolean isOnScreenIgnoringKeyguard() { 1270 if (!mHasSurface || mDestroying) { 1271 return false; 1272 } 1273 final AppWindowToken atoken = mAppToken; 1274 if (atoken != null) { 1275 return ((!mAttachedHidden && !atoken.hiddenRequested) 1276 || mWinAnimator.mAnimation != null || atoken.mAppAnimator.animation != null); 1277 } 1278 return !mAttachedHidden || mWinAnimator.mAnimation != null; 1279 } 1280 1281 /** 1282 * Whether this window's drawn state might affect the drawn states of the app token. 1283 * 1284 * @param visibleOnly Whether we should consider only the windows that's currently 1285 * visible in layout. If true, windows that has not relayout to VISIBLE 1286 * would always return false. 1287 * 1288 * @return true if the window should be considered while evaluating allDrawn flags. 1289 */ 1290 boolean mightAffectAllDrawn(boolean visibleOnly) { 1291 final boolean isViewVisible = (mAppToken == null || !mAppToken.clientHidden) 1292 && (mViewVisibility == View.VISIBLE) && !mWindowRemovalAllowed; 1293 return (isOnScreenIgnoringKeyguard() && (!visibleOnly || isViewVisible) 1294 || mWinAnimator.mAttrType == TYPE_BASE_APPLICATION 1295 || mWinAnimator.mAttrType == TYPE_DRAWN_APPLICATION) 1296 && !mAnimatingExit && !mDestroying; 1297 } 1298 1299 /** 1300 * Whether this window is "interesting" when evaluating allDrawn. If it's interesting, 1301 * it must be drawn before allDrawn can become true. 1302 */ 1303 boolean isInteresting() { 1304 return mAppToken != null && !mAppDied 1305 && (!mAppToken.mAppAnimator.freezingScreen || !mAppFreezing); 1306 } 1307 1308 /** 1309 * Like isOnScreen(), but we don't return true if the window is part 1310 * of a transition that has not yet been started. 1311 */ 1312 boolean isReadyForDisplay() { 1313 if (mRootToken.waitingToShow && mService.mAppTransition.isTransitionSet()) { 1314 return false; 1315 } 1316 return mHasSurface && mPolicyVisibility && !mDestroying 1317 && ((!mAttachedHidden && mViewVisibility == View.VISIBLE && !mRootToken.hidden) 1318 || mWinAnimator.mAnimation != null 1319 || ((mAppToken != null) && (mAppToken.mAppAnimator.animation != null))); 1320 } 1321 1322 /** 1323 * Like isReadyForDisplay(), but ignores any force hiding of the window due 1324 * to the keyguard. 1325 */ 1326 boolean isReadyForDisplayIgnoringKeyguard() { 1327 if (mRootToken.waitingToShow && mService.mAppTransition.isTransitionSet()) { 1328 return false; 1329 } 1330 final AppWindowToken atoken = mAppToken; 1331 if (atoken == null && !mPolicyVisibility) { 1332 // If this is not an app window, and the policy has asked to force 1333 // hide, then we really do want to hide. 1334 return false; 1335 } 1336 return mHasSurface && !mDestroying 1337 && ((!mAttachedHidden && mViewVisibility == View.VISIBLE && !mRootToken.hidden) 1338 || mWinAnimator.mAnimation != null 1339 || ((atoken != null) && (atoken.mAppAnimator.animation != null) 1340 && !mWinAnimator.isDummyAnimation()) 1341 || isAnimatingWithSavedSurface()); 1342 } 1343 1344 /** 1345 * Like isOnScreen, but returns false if the surface hasn't yet 1346 * been drawn. 1347 */ 1348 @Override 1349 public boolean isDisplayedLw() { 1350 final AppWindowToken atoken = mAppToken; 1351 return isDrawnLw() && mPolicyVisibility 1352 && ((!mAttachedHidden && 1353 (atoken == null || !atoken.hiddenRequested)) 1354 || mWinAnimator.mAnimating 1355 || (atoken != null && atoken.mAppAnimator.animation != null)); 1356 } 1357 1358 /** 1359 * Return true if this window or its app token is currently animating. 1360 */ 1361 @Override 1362 public boolean isAnimatingLw() { 1363 return mWinAnimator.mAnimation != null 1364 || (mAppToken != null && mAppToken.mAppAnimator.animation != null); 1365 } 1366 1367 @Override 1368 public boolean isGoneForLayoutLw() { 1369 final AppWindowToken atoken = mAppToken; 1370 return mViewVisibility == View.GONE 1371 || !mRelayoutCalled 1372 || (atoken == null && mRootToken.hidden) 1373 || (atoken != null && atoken.hiddenRequested) 1374 || mAttachedHidden 1375 || (mAnimatingExit && !isAnimatingLw()) 1376 || mDestroying; 1377 } 1378 1379 /** 1380 * Returns true if the window has a surface that it has drawn a 1381 * complete UI in to. 1382 */ 1383 public boolean isDrawFinishedLw() { 1384 return mHasSurface && !mDestroying && 1385 (mWinAnimator.mDrawState == WindowStateAnimator.COMMIT_DRAW_PENDING 1386 || mWinAnimator.mDrawState == WindowStateAnimator.READY_TO_SHOW 1387 || mWinAnimator.mDrawState == WindowStateAnimator.HAS_DRAWN); 1388 } 1389 1390 /** 1391 * Returns true if the window has a surface that it has drawn a 1392 * complete UI in to. 1393 */ 1394 @Override 1395 public boolean isDrawnLw() { 1396 return mHasSurface && !mDestroying && 1397 (mWinAnimator.mDrawState == WindowStateAnimator.READY_TO_SHOW 1398 || mWinAnimator.mDrawState == WindowStateAnimator.HAS_DRAWN); 1399 } 1400 1401 /** 1402 * Return true if the window is opaque and fully drawn. This indicates 1403 * it may obscure windows behind it. 1404 */ 1405 boolean isOpaqueDrawn() { 1406 // When there is keyguard, wallpaper could be placed over the secure app 1407 // window but invisible. We need to check wallpaper visibility explicitly 1408 // to determine if it's occluding apps. 1409 return ((!mIsWallpaper && mAttrs.format == PixelFormat.OPAQUE) 1410 || (mIsWallpaper && mWallpaperVisible)) 1411 && isDrawnLw() && mWinAnimator.mAnimation == null 1412 && (mAppToken == null || mAppToken.mAppAnimator.animation == null); 1413 } 1414 1415 /** 1416 * Return whether this window has moved. (Only makes 1417 * sense to call from performLayoutAndPlaceSurfacesLockedInner().) 1418 */ 1419 boolean hasMoved() { 1420 return mHasSurface && (mContentChanged || mMovedByResize) 1421 && !mAnimatingExit 1422 && (mFrame.top != mLastFrame.top || mFrame.left != mLastFrame.left) 1423 && (mAttachedWindow == null || !mAttachedWindow.hasMoved()); 1424 } 1425 1426 boolean isObscuringFullscreen(final DisplayInfo displayInfo) { 1427 Task task = getTask(); 1428 if (task != null && task.mStack != null && !task.mStack.isFullscreen()) { 1429 return false; 1430 } 1431 if (!isOpaqueDrawn() || !isFrameFullscreen(displayInfo)) { 1432 return false; 1433 } 1434 return true; 1435 } 1436 1437 boolean isFrameFullscreen(final DisplayInfo displayInfo) { 1438 return mFrame.left <= 0 && mFrame.top <= 0 1439 && mFrame.right >= displayInfo.appWidth && mFrame.bottom >= displayInfo.appHeight; 1440 } 1441 1442 boolean isConfigChanged() { 1443 getMergedConfig(mTmpConfig); 1444 1445 // If the merged configuration is still empty, it means that we haven't issues the 1446 // configuration to the client yet and we need to return true so the configuration updates. 1447 boolean configChanged = mMergedConfiguration.equals(Configuration.EMPTY) 1448 || mTmpConfig.diff(mMergedConfiguration) != 0; 1449 1450 if ((mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { 1451 // Retain configuration changed status until resetConfiguration called. 1452 mConfigHasChanged |= configChanged; 1453 configChanged = mConfigHasChanged; 1454 } 1455 1456 return configChanged; 1457 } 1458 1459 boolean isAdjustedForMinimizedDock() { 1460 return mAppToken != null && mAppToken.mTask != null 1461 && mAppToken.mTask.mStack.isAdjustedForMinimizedDock(); 1462 } 1463 1464 void removeLocked() { 1465 disposeInputChannel(); 1466 1467 if (isChildWindow()) { 1468 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Removing " + this + " from " + mAttachedWindow); 1469 mAttachedWindow.mChildWindows.remove(this); 1470 } 1471 mWinAnimator.destroyDeferredSurfaceLocked(); 1472 mWinAnimator.destroySurfaceLocked(); 1473 mSession.windowRemovedLocked(); 1474 try { 1475 mClient.asBinder().unlinkToDeath(mDeathRecipient, 0); 1476 } catch (RuntimeException e) { 1477 // Ignore if it has already been removed (usually because 1478 // we are doing this as part of processing a death note.) 1479 } 1480 } 1481 1482 void setHasSurface(boolean hasSurface) { 1483 mHasSurface = hasSurface; 1484 } 1485 1486 int getAnimLayerAdjustment() { 1487 if (mTargetAppToken != null) { 1488 return mTargetAppToken.mAppAnimator.animLayerAdjustment; 1489 } else if (mAppToken != null) { 1490 return mAppToken.mAppAnimator.animLayerAdjustment; 1491 } else { 1492 // Nothing is animating, so there is no animation adjustment. 1493 return 0; 1494 } 1495 } 1496 1497 void scheduleAnimationIfDimming() { 1498 if (mDisplayContent == null) { 1499 return; 1500 } 1501 final DimLayer.DimLayerUser dimLayerUser = getDimLayerUser(); 1502 if (dimLayerUser != null && mDisplayContent.mDimLayerController.isDimming( 1503 dimLayerUser, mWinAnimator)) { 1504 // Force an animation pass just to update the mDimLayer layer. 1505 mService.scheduleAnimationLocked(); 1506 } 1507 } 1508 1509 /** 1510 * Notifies this window that the corresponding task has just moved in the stack. 1511 * <p> 1512 * This is used to fix the following: If we moved in the stack, and if the last clip rect was 1513 * empty, meaning that our task was completely offscreen, we need to keep it invisible because 1514 * the actual app transition that updates the visibility is delayed by a few transactions. 1515 * Instead of messing around with the ordering and timing how transitions and transactions are 1516 * executed, we introduce this little hack which prevents this window of getting visible again 1517 * with the wrong bounds until the app transitions has started. 1518 * <p> 1519 * This method notifies the window about that we just moved in the stack so we can apply this 1520 * logic in {@link WindowStateAnimator#updateSurfaceWindowCrop} 1521 */ 1522 void notifyMovedInStack() { 1523 mJustMovedInStack = true; 1524 } 1525 1526 /** 1527 * See {@link #notifyMovedInStack}. 1528 * 1529 * @return Whether we just got moved in the corresponding stack. 1530 */ 1531 boolean hasJustMovedInStack() { 1532 return mJustMovedInStack; 1533 } 1534 1535 /** 1536 * Resets that we just moved in the corresponding stack. See {@link #notifyMovedInStack}. 1537 */ 1538 void resetJustMovedInStack() { 1539 mJustMovedInStack = false; 1540 } 1541 1542 private final class DeadWindowEventReceiver extends InputEventReceiver { 1543 DeadWindowEventReceiver(InputChannel inputChannel) { 1544 super(inputChannel, mService.mH.getLooper()); 1545 } 1546 @Override 1547 public void onInputEvent(InputEvent event) { 1548 finishInputEvent(event, true); 1549 } 1550 } 1551 /** 1552 * Dummy event receiver for windows that died visible. 1553 */ 1554 private DeadWindowEventReceiver mDeadWindowEventReceiver; 1555 1556 void openInputChannel(InputChannel outInputChannel) { 1557 if (mInputChannel != null) { 1558 throw new IllegalStateException("Window already has an input channel."); 1559 } 1560 String name = makeInputChannelName(); 1561 InputChannel[] inputChannels = InputChannel.openInputChannelPair(name); 1562 mInputChannel = inputChannels[0]; 1563 mClientChannel = inputChannels[1]; 1564 mInputWindowHandle.inputChannel = inputChannels[0]; 1565 if (outInputChannel != null) { 1566 mClientChannel.transferTo(outInputChannel); 1567 mClientChannel.dispose(); 1568 mClientChannel = null; 1569 } else { 1570 // If the window died visible, we setup a dummy input channel, so that taps 1571 // can still detected by input monitor channel, and we can relaunch the app. 1572 // Create dummy event receiver that simply reports all events as handled. 1573 mDeadWindowEventReceiver = new DeadWindowEventReceiver(mClientChannel); 1574 } 1575 mService.mInputManager.registerInputChannel(mInputChannel, mInputWindowHandle); 1576 } 1577 1578 void disposeInputChannel() { 1579 if (mDeadWindowEventReceiver != null) { 1580 mDeadWindowEventReceiver.dispose(); 1581 mDeadWindowEventReceiver = null; 1582 } 1583 1584 // unregister server channel first otherwise it complains about broken channel 1585 if (mInputChannel != null) { 1586 mService.mInputManager.unregisterInputChannel(mInputChannel); 1587 mInputChannel.dispose(); 1588 mInputChannel = null; 1589 } 1590 if (mClientChannel != null) { 1591 mClientChannel.dispose(); 1592 mClientChannel = null; 1593 } 1594 mInputWindowHandle.inputChannel = null; 1595 } 1596 1597 void applyDimLayerIfNeeded() { 1598 // When the app is terminated (eg. from Recents), the task might have already been 1599 // removed with the window pending removal. Don't apply dim in such cases, as there 1600 // will be no more updateDimLayer() calls, which leaves the dimlayer invalid. 1601 final AppWindowToken token = mAppToken; 1602 if (token != null && token.removed) { 1603 return; 1604 } 1605 1606 if (!mAnimatingExit && mAppDied) { 1607 // If app died visible, apply a dim over the window to indicate that it's inactive 1608 mDisplayContent.mDimLayerController.applyDimAbove(getDimLayerUser(), mWinAnimator); 1609 } else if ((mAttrs.flags & FLAG_DIM_BEHIND) != 0 1610 && mDisplayContent != null && !mAnimatingExit && isVisibleUnchecked()) { 1611 mDisplayContent.mDimLayerController.applyDimBehind(getDimLayerUser(), mWinAnimator); 1612 } 1613 } 1614 1615 DimLayer.DimLayerUser getDimLayerUser() { 1616 Task task = getTask(); 1617 if (task != null) { 1618 return task; 1619 } 1620 return getStack(); 1621 } 1622 1623 void maybeRemoveReplacedWindow() { 1624 if (mAppToken == null) { 1625 return; 1626 } 1627 for (int i = mAppToken.allAppWindows.size() - 1; i >= 0; i--) { 1628 final WindowState win = mAppToken.allAppWindows.get(i); 1629 if (win.mWillReplaceWindow && win.mReplacingWindow == this && hasDrawnLw()) { 1630 if (DEBUG_ADD_REMOVE) Slog.d(TAG, "Removing replaced window: " + win); 1631 if (win.isDimming()) { 1632 win.transferDimToReplacement(); 1633 } 1634 win.mWillReplaceWindow = false; 1635 final boolean animateReplacingWindow = win.mAnimateReplacingWindow; 1636 win.mAnimateReplacingWindow = false; 1637 win.mReplacingRemoveRequested = false; 1638 win.mReplacingWindow = null; 1639 mSkipEnterAnimationForSeamlessReplacement = false; 1640 if (win.mAnimatingExit || !animateReplacingWindow) { 1641 mService.removeWindowInnerLocked(win); 1642 } 1643 } 1644 } 1645 } 1646 1647 void setDisplayLayoutNeeded() { 1648 if (mDisplayContent != null) { 1649 mDisplayContent.layoutNeeded = true; 1650 } 1651 } 1652 1653 boolean inDockedWorkspace() { 1654 final Task task = getTask(); 1655 return task != null && task.inDockedWorkspace(); 1656 } 1657 1658 // TODO: Strange usage of word workspace here and above. 1659 boolean inPinnedWorkspace() { 1660 final Task task = getTask(); 1661 return task != null && task.inPinnedWorkspace(); 1662 } 1663 1664 boolean isDockedInEffect() { 1665 final Task task = getTask(); 1666 return task != null && task.isDockedInEffect(); 1667 } 1668 1669 void applyScrollIfNeeded() { 1670 final Task task = getTask(); 1671 if (task != null) { 1672 task.applyScrollToWindowIfNeeded(this); 1673 } 1674 } 1675 1676 void applyAdjustForImeIfNeeded() { 1677 final Task task = getTask(); 1678 if (task != null && task.mStack != null && task.mStack.isAdjustedForIme()) { 1679 task.mStack.applyAdjustForImeIfNeeded(task); 1680 } 1681 } 1682 1683 int getTouchableRegion(Region region, int flags) { 1684 final boolean modal = (flags & (FLAG_NOT_TOUCH_MODAL | FLAG_NOT_FOCUSABLE)) == 0; 1685 if (modal && mAppToken != null) { 1686 // Limit the outer touch to the activity stack region. 1687 flags |= FLAG_NOT_TOUCH_MODAL; 1688 // If this is a modal window we need to dismiss it if it's not full screen and the 1689 // touch happens outside of the frame that displays the content. This means we 1690 // need to intercept touches outside of that window. The dim layer user 1691 // associated with the window (task or stack) will give us the good bounds, as 1692 // they would be used to display the dim layer. 1693 final DimLayer.DimLayerUser dimLayerUser = getDimLayerUser(); 1694 if (dimLayerUser != null) { 1695 dimLayerUser.getDimBounds(mTmpRect); 1696 } else { 1697 getVisibleBounds(mTmpRect); 1698 } 1699 if (inFreeformWorkspace()) { 1700 // For freeform windows we the touch region to include the whole surface for the 1701 // shadows. 1702 final DisplayMetrics displayMetrics = getDisplayContent().getDisplayMetrics(); 1703 final int delta = WindowManagerService.dipToPixel( 1704 RESIZE_HANDLE_WIDTH_IN_DP, displayMetrics); 1705 mTmpRect.inset(-delta, -delta); 1706 } 1707 region.set(mTmpRect); 1708 cropRegionToStackBoundsIfNeeded(region); 1709 } else { 1710 // Not modal or full screen modal 1711 getTouchableRegion(region); 1712 } 1713 return flags; 1714 } 1715 1716 void checkPolicyVisibilityChange() { 1717 if (mPolicyVisibility != mPolicyVisibilityAfterAnim) { 1718 if (DEBUG_VISIBILITY) { 1719 Slog.v(TAG, "Policy visibility changing after anim in " + 1720 mWinAnimator + ": " + mPolicyVisibilityAfterAnim); 1721 } 1722 mPolicyVisibility = mPolicyVisibilityAfterAnim; 1723 setDisplayLayoutNeeded(); 1724 if (!mPolicyVisibility) { 1725 if (mService.mCurrentFocus == this) { 1726 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, 1727 "setAnimationLocked: setting mFocusMayChange true"); 1728 mService.mFocusMayChange = true; 1729 } 1730 // Window is no longer visible -- make sure if we were waiting 1731 // for it to be displayed before enabling the display, that 1732 // we allow the display to be enabled now. 1733 mService.enableScreenIfNeededLocked(); 1734 } 1735 } 1736 } 1737 1738 void setRequestedSize(int requestedWidth, int requestedHeight) { 1739 if ((mRequestedWidth != requestedWidth || mRequestedHeight != requestedHeight)) { 1740 mLayoutNeeded = true; 1741 mRequestedWidth = requestedWidth; 1742 mRequestedHeight = requestedHeight; 1743 } 1744 } 1745 1746 void prepareWindowToDisplayDuringRelayout(Configuration outConfig) { 1747 if ((mAttrs.softInputMode & SOFT_INPUT_MASK_ADJUST) 1748 == SOFT_INPUT_ADJUST_RESIZE) { 1749 mLayoutNeeded = true; 1750 } 1751 if (isDrawnLw() && mService.okToDisplay()) { 1752 mWinAnimator.applyEnterAnimationLocked(); 1753 } 1754 if ((mAttrs.flags & FLAG_TURN_SCREEN_ON) != 0) { 1755 if (DEBUG_VISIBILITY) Slog.v(TAG, "Relayout window turning screen on: " + this); 1756 mTurnOnScreen = true; 1757 } 1758 if (isConfigChanged()) { 1759 final Configuration newConfig = updateConfiguration(); 1760 if (DEBUG_CONFIGURATION) Slog.i(TAG, "Window " + this + " visible with new config: " 1761 + newConfig); 1762 outConfig.setTo(newConfig); 1763 } 1764 } 1765 1766 void adjustStartingWindowFlags() { 1767 if (mAttrs.type == TYPE_BASE_APPLICATION && mAppToken != null 1768 && mAppToken.startingWindow != null) { 1769 // Special handling of starting window over the base 1770 // window of the app: propagate lock screen flags to it, 1771 // to provide the correct semantics while starting. 1772 final int mask = FLAG_SHOW_WHEN_LOCKED | FLAG_DISMISS_KEYGUARD 1773 | FLAG_ALLOW_LOCK_WHILE_SCREEN_ON; 1774 WindowManager.LayoutParams sa = mAppToken.startingWindow.mAttrs; 1775 sa.flags = (sa.flags & ~mask) | (mAttrs.flags & mask); 1776 } 1777 } 1778 1779 void setWindowScale(int requestedWidth, int requestedHeight) { 1780 final boolean scaledWindow = (mAttrs.flags & FLAG_SCALED) != 0; 1781 1782 if (scaledWindow) { 1783 // requested{Width|Height} Surface's physical size 1784 // attrs.{width|height} Size on screen 1785 // TODO: We don't check if attrs != null here. Is it implicitly checked? 1786 mHScale = (mAttrs.width != requestedWidth) ? 1787 (mAttrs.width / (float)requestedWidth) : 1.0f; 1788 mVScale = (mAttrs.height != requestedHeight) ? 1789 (mAttrs.height / (float)requestedHeight) : 1.0f; 1790 } else { 1791 mHScale = mVScale = 1; 1792 } 1793 } 1794 1795 private class DeathRecipient implements IBinder.DeathRecipient { 1796 @Override 1797 public void binderDied() { 1798 try { 1799 synchronized(mService.mWindowMap) { 1800 WindowState win = mService.windowForClientLocked(mSession, mClient, false); 1801 Slog.i(TAG, "WIN DEATH: " + win); 1802 if (win != null) { 1803 mService.removeWindowLocked(win, shouldKeepVisibleDeadAppWindow()); 1804 if (win.mAttrs.type == TYPE_DOCK_DIVIDER) { 1805 // The owner of the docked divider died :( We reset the docked stack, 1806 // just in case they have the divider at an unstable position. Better 1807 // also reset drag resizing state, because the owner can't do it 1808 // anymore. 1809 final TaskStack stack = mService.mStackIdToStack.get(DOCKED_STACK_ID); 1810 if (stack != null) { 1811 stack.resetDockedStackToMiddle(); 1812 } 1813 mService.setDockedStackResizing(false); 1814 } 1815 } else if (mHasSurface) { 1816 Slog.e(TAG, "!!! LEAK !!! Window removed but surface still valid."); 1817 mService.removeWindowLocked(WindowState.this); 1818 } 1819 } 1820 } catch (IllegalArgumentException ex) { 1821 // This will happen if the window has already been removed. 1822 } 1823 } 1824 } 1825 1826 /** 1827 * Returns true if this window is visible and belongs to a dead app and shouldn't be removed, 1828 * because we want to preserve its location on screen to be re-activated later when the user 1829 * interacts with it. 1830 */ 1831 boolean shouldKeepVisibleDeadAppWindow() { 1832 if (!isWinVisibleLw() || mAppToken == null || mAppToken.clientHidden) { 1833 // Not a visible app window or the app isn't dead. 1834 return false; 1835 } 1836 1837 if (mAttrs.token != mClient.asBinder()) { 1838 // The window was add by a client using another client's app token. We don't want to 1839 // keep the dead window around for this case since this is meant for 'real' apps. 1840 return false; 1841 } 1842 1843 if (mAttrs.type == TYPE_APPLICATION_STARTING) { 1844 // We don't keep starting windows since they were added by the window manager before 1845 // the app even launched. 1846 return false; 1847 } 1848 1849 final TaskStack stack = getStack(); 1850 return stack != null && StackId.keepVisibleDeadAppWindowOnScreen(stack.mStackId); 1851 } 1852 1853 /** @return true if this window desires key events. */ 1854 boolean canReceiveKeys() { 1855 return isVisibleOrAdding() 1856 && (mViewVisibility == View.VISIBLE) && !mRemoveOnExit 1857 && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0) 1858 && (mAppToken == null || mAppToken.windowsAreFocusable()) 1859 && !isAdjustedForMinimizedDock(); 1860 } 1861 1862 @Override 1863 public boolean hasDrawnLw() { 1864 return mWinAnimator.mDrawState == WindowStateAnimator.HAS_DRAWN; 1865 } 1866 1867 @Override 1868 public boolean showLw(boolean doAnimation) { 1869 return showLw(doAnimation, true); 1870 } 1871 1872 boolean showLw(boolean doAnimation, boolean requestAnim) { 1873 if (isHiddenFromUserLocked()) { 1874 return false; 1875 } 1876 if (!mAppOpVisibility) { 1877 // Being hidden due to app op request. 1878 return false; 1879 } 1880 if (mPermanentlyHidden) { 1881 // Permanently hidden until the app exists as apps aren't prepared 1882 // to handle their windows being removed from under them. 1883 return false; 1884 } 1885 if (mPolicyVisibility && mPolicyVisibilityAfterAnim) { 1886 // Already showing. 1887 return false; 1888 } 1889 if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility true: " + this); 1890 if (doAnimation) { 1891 if (DEBUG_VISIBILITY) Slog.v(TAG, "doAnimation: mPolicyVisibility=" 1892 + mPolicyVisibility + " mAnimation=" + mWinAnimator.mAnimation); 1893 if (!mService.okToDisplay()) { 1894 doAnimation = false; 1895 } else if (mPolicyVisibility && mWinAnimator.mAnimation == null) { 1896 // Check for the case where we are currently visible and 1897 // not animating; we do not want to do animation at such a 1898 // point to become visible when we already are. 1899 doAnimation = false; 1900 } 1901 } 1902 mPolicyVisibility = true; 1903 mPolicyVisibilityAfterAnim = true; 1904 if (doAnimation) { 1905 mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_ENTER, true); 1906 } 1907 if (requestAnim) { 1908 mService.scheduleAnimationLocked(); 1909 } 1910 return true; 1911 } 1912 1913 @Override 1914 public boolean hideLw(boolean doAnimation) { 1915 return hideLw(doAnimation, true); 1916 } 1917 1918 boolean hideLw(boolean doAnimation, boolean requestAnim) { 1919 if (doAnimation) { 1920 if (!mService.okToDisplay()) { 1921 doAnimation = false; 1922 } 1923 } 1924 boolean current = doAnimation ? mPolicyVisibilityAfterAnim 1925 : mPolicyVisibility; 1926 if (!current) { 1927 // Already hiding. 1928 return false; 1929 } 1930 if (doAnimation) { 1931 mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_EXIT, false); 1932 if (mWinAnimator.mAnimation == null) { 1933 doAnimation = false; 1934 } 1935 } 1936 if (doAnimation) { 1937 mPolicyVisibilityAfterAnim = false; 1938 } else { 1939 if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility false: " + this); 1940 mPolicyVisibilityAfterAnim = false; 1941 mPolicyVisibility = false; 1942 // Window is no longer visible -- make sure if we were waiting 1943 // for it to be displayed before enabling the display, that 1944 // we allow the display to be enabled now. 1945 mService.enableScreenIfNeededLocked(); 1946 if (mService.mCurrentFocus == this) { 1947 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, 1948 "WindowState.hideLw: setting mFocusMayChange true"); 1949 mService.mFocusMayChange = true; 1950 } 1951 } 1952 if (requestAnim) { 1953 mService.scheduleAnimationLocked(); 1954 } 1955 return true; 1956 } 1957 1958 public void setAppOpVisibilityLw(boolean state) { 1959 if (mAppOpVisibility != state) { 1960 mAppOpVisibility = state; 1961 if (state) { 1962 // If the policy visibility had last been to hide, then this 1963 // will incorrectly show at this point since we lost that 1964 // information. Not a big deal -- for the windows that have app 1965 // ops modifies they should only be hidden by policy due to the 1966 // lock screen, and the user won't be changing this if locked. 1967 // Plus it will quickly be fixed the next time we do a layout. 1968 showLw(true, true); 1969 } else { 1970 hideLw(true, true); 1971 } 1972 } 1973 } 1974 1975 public void hidePermanentlyLw() { 1976 if (!mPermanentlyHidden) { 1977 mPermanentlyHidden = true; 1978 hideLw(true, true); 1979 } 1980 } 1981 1982 public void pokeDrawLockLw(long timeout) { 1983 if (isVisibleOrAdding()) { 1984 if (mDrawLock == null) { 1985 // We want the tag name to be somewhat stable so that it is easier to correlate 1986 // in wake lock statistics. So in particular, we don't want to include the 1987 // window's hash code as in toString(). 1988 final CharSequence tag = getWindowTag(); 1989 mDrawLock = mService.mPowerManager.newWakeLock( 1990 PowerManager.DRAW_WAKE_LOCK, "Window:" + tag); 1991 mDrawLock.setReferenceCounted(false); 1992 mDrawLock.setWorkSource(new WorkSource(mOwnerUid, mAttrs.packageName)); 1993 } 1994 // Each call to acquire resets the timeout. 1995 if (DEBUG_POWER) { 1996 Slog.d(TAG, "pokeDrawLock: poking draw lock on behalf of visible window owned by " 1997 + mAttrs.packageName); 1998 } 1999 mDrawLock.acquire(timeout); 2000 } else if (DEBUG_POWER) { 2001 Slog.d(TAG, "pokeDrawLock: suppressed draw lock request for invisible window " 2002 + "owned by " + mAttrs.packageName); 2003 } 2004 } 2005 2006 @Override 2007 public boolean isAlive() { 2008 return mClient.asBinder().isBinderAlive(); 2009 } 2010 2011 boolean isClosing() { 2012 return mAnimatingExit || (mService.mClosingApps.contains(mAppToken)); 2013 } 2014 2015 boolean isAnimatingWithSavedSurface() { 2016 return mAnimatingWithSavedSurface; 2017 } 2018 2019 boolean isAnimatingInvisibleWithSavedSurface() { 2020 return mAnimatingWithSavedSurface 2021 && (mViewVisibility != View.VISIBLE || mWindowRemovalAllowed); 2022 } 2023 2024 public void setVisibleBeforeClientHidden() { 2025 mWasVisibleBeforeClientHidden |= 2026 (mViewVisibility == View.VISIBLE || mAnimatingWithSavedSurface); 2027 } 2028 2029 public void clearVisibleBeforeClientHidden() { 2030 mWasVisibleBeforeClientHidden = false; 2031 } 2032 2033 public boolean wasVisibleBeforeClientHidden() { 2034 return mWasVisibleBeforeClientHidden; 2035 } 2036 2037 private boolean shouldSaveSurface() { 2038 if (mWinAnimator.mSurfaceController == null) { 2039 // Don't bother if the surface controller is gone for any reason. 2040 return false; 2041 } 2042 2043 if (!mWasVisibleBeforeClientHidden) { 2044 return false; 2045 } 2046 2047 if ((mAttrs.flags & FLAG_SECURE) != 0) { 2048 // We don't save secure surfaces since their content shouldn't be shown while the app 2049 // isn't on screen and content might leak through during the transition animation with 2050 // saved surface. 2051 return false; 2052 } 2053 2054 if (ActivityManager.isLowRamDeviceStatic()) { 2055 // Don't save surfaces on Svelte devices. 2056 return false; 2057 } 2058 2059 Task task = getTask(); 2060 if (task == null || task.inHomeStack()) { 2061 // Don't save surfaces for home stack apps. These usually resume and draw 2062 // first frame very fast. Saving surfaces are mostly a waste of memory. 2063 return false; 2064 } 2065 2066 final AppWindowToken taskTop = task.getTopVisibleAppToken(); 2067 if (taskTop != null && taskTop != mAppToken) { 2068 // Don't save if the window is not the topmost window. 2069 return false; 2070 } 2071 2072 if (mResizedWhileGone) { 2073 // Somebody resized our window while we were gone for layout, which means that the 2074 // client got an old size, so we have an outdated surface here. 2075 return false; 2076 } 2077 2078 if (DEBUG_DISABLE_SAVING_SURFACES) { 2079 return false; 2080 } 2081 2082 return mAppToken.shouldSaveSurface(); 2083 } 2084 2085 static final Region sEmptyRegion = new Region(); 2086 2087 void destroyOrSaveSurface() { 2088 mSurfaceSaved = shouldSaveSurface(); 2089 if (mSurfaceSaved) { 2090 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) { 2091 Slog.v(TAG, "Saving surface: " + this); 2092 } 2093 // Previous user of the surface may have set a transparent region signaling a portion 2094 // doesn't need to be composited, so reset to default empty state. 2095 mSession.setTransparentRegion(mClient, sEmptyRegion); 2096 2097 mWinAnimator.hide("saved surface"); 2098 mWinAnimator.mDrawState = WindowStateAnimator.NO_SURFACE; 2099 setHasSurface(false); 2100 // The client should have disconnected at this point, but if it doesn't, 2101 // we need to make sure it's disconnected. Otherwise when we reuse the surface 2102 // the client can't reconnect to the buffer queue, and rendering will fail. 2103 if (mWinAnimator.mSurfaceController != null) { 2104 mWinAnimator.mSurfaceController.disconnectInTransaction(); 2105 } 2106 mAnimatingWithSavedSurface = false; 2107 } else { 2108 mWinAnimator.destroySurfaceLocked(); 2109 } 2110 // Clear animating flags now, since the surface is now gone. (Note this is true even 2111 // if the surface is saved, to outside world the surface is still NO_SURFACE.) 2112 mAnimatingExit = false; 2113 } 2114 2115 void destroySavedSurface() { 2116 if (mSurfaceSaved) { 2117 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) { 2118 Slog.v(TAG, "Destroying saved surface: " + this); 2119 } 2120 mWinAnimator.destroySurfaceLocked(); 2121 mSurfaceSaved = false; 2122 } 2123 mWasVisibleBeforeClientHidden = false; 2124 } 2125 2126 void restoreSavedSurface() { 2127 if (!mSurfaceSaved) { 2128 return; 2129 } 2130 2131 // Sometimes we save surfaces due to layout invisible 2132 // directly after rotation occurs. However this means 2133 // the surface was never laid out in the new orientation. 2134 // We can only restore to the last rotation we were 2135 // laid out as visible in. 2136 if (mLastVisibleLayoutRotation != mService.mRotation) { 2137 destroySavedSurface(); 2138 return; 2139 } 2140 mSurfaceSaved = false; 2141 2142 if (mWinAnimator.mSurfaceController != null) { 2143 setHasSurface(true); 2144 mWinAnimator.mDrawState = WindowStateAnimator.READY_TO_SHOW; 2145 mAnimatingWithSavedSurface = true; 2146 2147 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) { 2148 Slog.v(TAG, "Restoring saved surface: " + this); 2149 } 2150 } else { 2151 // mSurfaceController shouldn't be null if mSurfaceSaved was still true at 2152 // this point. Even if we destroyed the saved surface because of rotation 2153 // or resize, mSurfaceSaved flag should have been cleared. So this is a wtf. 2154 Slog.wtf(TAG, "Failed to restore saved surface: surface gone! " + this); 2155 } 2156 } 2157 2158 boolean canRestoreSurface() { 2159 return mWasVisibleBeforeClientHidden && mSurfaceSaved; 2160 } 2161 2162 boolean hasSavedSurface() { 2163 return mSurfaceSaved; 2164 } 2165 2166 void clearHasSavedSurface() { 2167 mSurfaceSaved = false; 2168 mAnimatingWithSavedSurface = false; 2169 if (mWasVisibleBeforeClientHidden) { 2170 mAppToken.destroySavedSurfaces(); 2171 } 2172 } 2173 2174 boolean clearAnimatingWithSavedSurface() { 2175 if (mAnimatingWithSavedSurface) { 2176 // App has drawn something to its windows, we're no longer animating with 2177 // the saved surfaces. 2178 if (DEBUG_ANIM) Slog.d(TAG, 2179 "clearAnimatingWithSavedSurface(): win=" + this); 2180 mAnimatingWithSavedSurface = false; 2181 return true; 2182 } 2183 return false; 2184 } 2185 2186 @Override 2187 public boolean isDefaultDisplay() { 2188 final DisplayContent displayContent = getDisplayContent(); 2189 if (displayContent == null) { 2190 // Only a window that was on a non-default display can be detached from it. 2191 return false; 2192 } 2193 return displayContent.isDefaultDisplay; 2194 } 2195 2196 @Override 2197 public boolean isDimming() { 2198 final DimLayer.DimLayerUser dimLayerUser = getDimLayerUser(); 2199 return dimLayerUser != null && mDisplayContent != null && 2200 mDisplayContent.mDimLayerController.isDimming(dimLayerUser, mWinAnimator); 2201 } 2202 2203 public void setShowToOwnerOnlyLocked(boolean showToOwnerOnly) { 2204 mShowToOwnerOnly = showToOwnerOnly; 2205 } 2206 2207 boolean isHiddenFromUserLocked() { 2208 // Attached windows are evaluated based on the window that they are attached to. 2209 WindowState win = this; 2210 while (win.isChildWindow()) { 2211 win = win.mAttachedWindow; 2212 } 2213 if (win.mAttrs.type < WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW 2214 && win.mAppToken != null && win.mAppToken.showForAllUsers) { 2215 2216 // All window frames that are fullscreen extend above status bar, but some don't extend 2217 // below navigation bar. Thus, check for display frame for top/left and stable frame for 2218 // bottom right. 2219 if (win.mFrame.left <= win.mDisplayFrame.left 2220 && win.mFrame.top <= win.mDisplayFrame.top 2221 && win.mFrame.right >= win.mStableFrame.right 2222 && win.mFrame.bottom >= win.mStableFrame.bottom) { 2223 // Is a fullscreen window, like the clock alarm. Show to everyone. 2224 return false; 2225 } 2226 } 2227 2228 return win.mShowToOwnerOnly 2229 && !mService.isCurrentProfileLocked(UserHandle.getUserId(win.mOwnerUid)); 2230 } 2231 2232 private static void applyInsets(Region outRegion, Rect frame, Rect inset) { 2233 outRegion.set( 2234 frame.left + inset.left, frame.top + inset.top, 2235 frame.right - inset.right, frame.bottom - inset.bottom); 2236 } 2237 2238 void getTouchableRegion(Region outRegion) { 2239 final Rect frame = mFrame; 2240 switch (mTouchableInsets) { 2241 default: 2242 case TOUCHABLE_INSETS_FRAME: 2243 outRegion.set(frame); 2244 break; 2245 case TOUCHABLE_INSETS_CONTENT: 2246 applyInsets(outRegion, frame, mGivenContentInsets); 2247 break; 2248 case TOUCHABLE_INSETS_VISIBLE: 2249 applyInsets(outRegion, frame, mGivenVisibleInsets); 2250 break; 2251 case TOUCHABLE_INSETS_REGION: { 2252 final Region givenTouchableRegion = mGivenTouchableRegion; 2253 outRegion.set(givenTouchableRegion); 2254 outRegion.translate(frame.left, frame.top); 2255 break; 2256 } 2257 } 2258 cropRegionToStackBoundsIfNeeded(outRegion); 2259 } 2260 2261 void cropRegionToStackBoundsIfNeeded(Region region) { 2262 final Task task = getTask(); 2263 if (task == null || !task.cropWindowsToStackBounds()) { 2264 return; 2265 } 2266 2267 final TaskStack stack = task.mStack; 2268 if (stack == null) { 2269 return; 2270 } 2271 2272 stack.getDimBounds(mTmpRect); 2273 region.op(mTmpRect, Region.Op.INTERSECT); 2274 } 2275 2276 WindowList getWindowList() { 2277 final DisplayContent displayContent = getDisplayContent(); 2278 return displayContent == null ? null : displayContent.getWindowList(); 2279 } 2280 2281 /** 2282 * Report a focus change. Must be called with no locks held, and consistently 2283 * from the same serialized thread (such as dispatched from a handler). 2284 */ 2285 public void reportFocusChangedSerialized(boolean focused, boolean inTouchMode) { 2286 try { 2287 mClient.windowFocusChanged(focused, inTouchMode); 2288 } catch (RemoteException e) { 2289 } 2290 if (mFocusCallbacks != null) { 2291 final int N = mFocusCallbacks.beginBroadcast(); 2292 for (int i=0; i<N; i++) { 2293 IWindowFocusObserver obs = mFocusCallbacks.getBroadcastItem(i); 2294 try { 2295 if (focused) { 2296 obs.focusGained(mWindowId.asBinder()); 2297 } else { 2298 obs.focusLost(mWindowId.asBinder()); 2299 } 2300 } catch (RemoteException e) { 2301 } 2302 } 2303 mFocusCallbacks.finishBroadcast(); 2304 } 2305 } 2306 2307 /** 2308 * Update our current configurations, based on task configuration. 2309 * 2310 * @return A configuration suitable for sending to the client. 2311 */ 2312 private Configuration updateConfiguration() { 2313 final boolean configChanged = isConfigChanged(); 2314 getMergedConfig(mMergedConfiguration); 2315 mConfigHasChanged = false; 2316 if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION) && configChanged) { 2317 Slog.i(TAG, "Sending new config to window " + this + ": " + 2318 " / mergedConfig=" + mMergedConfiguration); 2319 } 2320 return mMergedConfiguration; 2321 } 2322 2323 private void getMergedConfig(Configuration outConfig) { 2324 if (mAppToken != null && mAppToken.mFrozenMergedConfig.size() > 0) { 2325 outConfig.setTo(mAppToken.mFrozenMergedConfig.peek()); 2326 return; 2327 } 2328 final Task task = getTask(); 2329 final Configuration overrideConfig = task != null 2330 ? task.mOverrideConfig 2331 : Configuration.EMPTY; 2332 final Configuration serviceConfig = mService.mCurConfiguration; 2333 outConfig.setTo(serviceConfig); 2334 if (overrideConfig != Configuration.EMPTY) { 2335 outConfig.updateFrom(overrideConfig); 2336 } 2337 } 2338 2339 void reportResized() { 2340 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "wm.reportResized_" + getWindowTag()); 2341 try { 2342 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, "Reporting new frame to " + this 2343 + ": " + mCompatFrame); 2344 final Configuration newConfig = isConfigChanged() ? updateConfiguration() : null; 2345 if (DEBUG_ORIENTATION && mWinAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING) 2346 Slog.i(TAG, "Resizing " + this + " WITH DRAW PENDING"); 2347 2348 final Rect frame = mFrame; 2349 final Rect overscanInsets = mLastOverscanInsets; 2350 final Rect contentInsets = mLastContentInsets; 2351 final Rect visibleInsets = mLastVisibleInsets; 2352 final Rect stableInsets = mLastStableInsets; 2353 final Rect outsets = mLastOutsets; 2354 final boolean reportDraw = mWinAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING; 2355 if (mAttrs.type != WindowManager.LayoutParams.TYPE_APPLICATION_STARTING 2356 && mClient instanceof IWindow.Stub) { 2357 // To prevent deadlock simulate one-way call if win.mClient is a local object. 2358 mService.mH.post(new Runnable() { 2359 @Override 2360 public void run() { 2361 try { 2362 dispatchResized(frame, overscanInsets, contentInsets, visibleInsets, 2363 stableInsets, outsets, reportDraw, newConfig); 2364 } catch (RemoteException e) { 2365 // Not a remote call, RemoteException won't be raised. 2366 } 2367 } 2368 }); 2369 } else { 2370 dispatchResized(frame, overscanInsets, contentInsets, visibleInsets, stableInsets, 2371 outsets, reportDraw, newConfig); 2372 } 2373 2374 //TODO (multidisplay): Accessibility supported only for the default display. 2375 if (mService.mAccessibilityController != null 2376 && getDisplayId() == Display.DEFAULT_DISPLAY) { 2377 mService.mAccessibilityController.onSomeWindowResizedOrMovedLocked(); 2378 } 2379 2380 mOverscanInsetsChanged = false; 2381 mContentInsetsChanged = false; 2382 mVisibleInsetsChanged = false; 2383 mStableInsetsChanged = false; 2384 mOutsetsChanged = false; 2385 mFrameSizeChanged = false; 2386 mResizedWhileNotDragResizingReported = true; 2387 mWinAnimator.mSurfaceResized = false; 2388 } catch (RemoteException e) { 2389 mOrientationChanging = false; 2390 mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 2391 - mService.mDisplayFreezeTime); 2392 // We are assuming the hosting process is dead or in a zombie state. 2393 Slog.w(TAG, "Failed to report 'resized' to the client of " + this 2394 + ", removing this window."); 2395 mService.mPendingRemove.add(this); 2396 mService.mWindowPlacerLocked.requestTraversal(); 2397 } 2398 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 2399 } 2400 2401 Rect getBackdropFrame(Rect frame) { 2402 // When the task is docked, we send fullscreen sized backDropFrame as soon as resizing 2403 // start even if we haven't received the relayout window, so that the client requests 2404 // the relayout sooner. When dragging stops, backDropFrame needs to stay fullscreen 2405 // until the window to small size, otherwise the multithread renderer will shift last 2406 // one or more frame to wrong offset. So here we send fullscreen backdrop if either 2407 // isDragResizing() or isDragResizeChanged() is true. 2408 boolean resizing = isDragResizing() || isDragResizeChanged(); 2409 if (StackId.useWindowFrameForBackdrop(getStackId()) || !resizing) { 2410 return frame; 2411 } 2412 DisplayInfo displayInfo = getDisplayInfo(); 2413 mTmpRect.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight); 2414 return mTmpRect; 2415 } 2416 2417 @Override 2418 public int getStackId() { 2419 final TaskStack stack = getStack(); 2420 if (stack == null) { 2421 return INVALID_STACK_ID; 2422 } 2423 return stack.mStackId; 2424 } 2425 2426 private void dispatchResized(Rect frame, Rect overscanInsets, Rect contentInsets, 2427 Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw, 2428 Configuration newConfig) throws RemoteException { 2429 final boolean forceRelayout = isDragResizeChanged() || mResizedWhileNotDragResizing; 2430 2431 mClient.resized(frame, overscanInsets, contentInsets, visibleInsets, stableInsets, outsets, 2432 reportDraw, newConfig, getBackdropFrame(frame), 2433 forceRelayout, mPolicy.isNavBarForcedShownLw(this)); 2434 mDragResizingChangeReported = true; 2435 } 2436 2437 public void registerFocusObserver(IWindowFocusObserver observer) { 2438 synchronized(mService.mWindowMap) { 2439 if (mFocusCallbacks == null) { 2440 mFocusCallbacks = new RemoteCallbackList<IWindowFocusObserver>(); 2441 } 2442 mFocusCallbacks.register(observer); 2443 } 2444 } 2445 2446 public void unregisterFocusObserver(IWindowFocusObserver observer) { 2447 synchronized(mService.mWindowMap) { 2448 if (mFocusCallbacks != null) { 2449 mFocusCallbacks.unregister(observer); 2450 } 2451 } 2452 } 2453 2454 public boolean isFocused() { 2455 synchronized(mService.mWindowMap) { 2456 return mService.mCurrentFocus == this; 2457 } 2458 } 2459 2460 boolean inFreeformWorkspace() { 2461 final Task task = getTask(); 2462 return task != null && task.inFreeformWorkspace(); 2463 } 2464 2465 @Override 2466 public boolean isInMultiWindowMode() { 2467 final Task task = getTask(); 2468 return task != null && !task.isFullscreen(); 2469 } 2470 2471 boolean isDragResizeChanged() { 2472 return mDragResizing != computeDragResizing(); 2473 } 2474 2475 /** 2476 * @return Whether we reported a drag resize change to the application or not already. 2477 */ 2478 boolean isDragResizingChangeReported() { 2479 return mDragResizingChangeReported; 2480 } 2481 2482 /** 2483 * Resets the state whether we reported a drag resize change to the app. 2484 */ 2485 void resetDragResizingChangeReported() { 2486 mDragResizingChangeReported = false; 2487 } 2488 2489 /** 2490 * Set whether we got resized but drag resizing flag was false. 2491 * @see #isResizedWhileNotDragResizing(). 2492 */ 2493 void setResizedWhileNotDragResizing(boolean resizedWhileNotDragResizing) { 2494 mResizedWhileNotDragResizing = resizedWhileNotDragResizing; 2495 mResizedWhileNotDragResizingReported = !resizedWhileNotDragResizing; 2496 } 2497 2498 /** 2499 * Indicates whether we got resized but drag resizing flag was false. In this case, we also 2500 * need to recreate the surface and defer surface bound updates in order to make sure the 2501 * buffer contents and the positioning/size stay in sync. 2502 */ 2503 boolean isResizedWhileNotDragResizing() { 2504 return mResizedWhileNotDragResizing; 2505 } 2506 2507 /** 2508 * @return Whether we reported "resize while not drag resizing" to the application. 2509 * @see #isResizedWhileNotDragResizing() 2510 */ 2511 boolean isResizedWhileNotDragResizingReported() { 2512 return mResizedWhileNotDragResizingReported; 2513 } 2514 2515 int getResizeMode() { 2516 return mResizeMode; 2517 } 2518 2519 boolean computeDragResizing() { 2520 final Task task = getTask(); 2521 if (task == null) { 2522 return false; 2523 } 2524 if (mAttrs.width != MATCH_PARENT || mAttrs.height != MATCH_PARENT) { 2525 2526 // Floating windows never enter drag resize mode. 2527 return false; 2528 } 2529 if (task.isDragResizing()) { 2530 return true; 2531 } 2532 2533 // If the bounds are currently frozen, it means that the layout size that the app sees 2534 // and the bounds we clip this window to might be different. In order to avoid holes, we 2535 // simulate that we are still resizing so the app fills the hole with the resizing 2536 // background. 2537 return (mDisplayContent.mDividerControllerLocked.isResizing() 2538 || mAppToken != null && !mAppToken.mFrozenBounds.isEmpty()) && 2539 !task.inFreeformWorkspace() && !isGoneForLayoutLw(); 2540 2541 } 2542 2543 void setDragResizing() { 2544 final boolean resizing = computeDragResizing(); 2545 if (resizing == mDragResizing) { 2546 return; 2547 } 2548 mDragResizing = resizing; 2549 final Task task = getTask(); 2550 if (task != null && task.isDragResizing()) { 2551 mResizeMode = task.getDragResizeMode(); 2552 } else { 2553 mResizeMode = mDragResizing && mDisplayContent.mDividerControllerLocked.isResizing() 2554 ? DRAG_RESIZE_MODE_DOCKED_DIVIDER 2555 : DRAG_RESIZE_MODE_FREEFORM; 2556 } 2557 } 2558 2559 boolean isDragResizing() { 2560 return mDragResizing; 2561 } 2562 2563 boolean isDockedResizing() { 2564 return mDragResizing && getResizeMode() == DRAG_RESIZE_MODE_DOCKED_DIVIDER; 2565 } 2566 2567 void dump(PrintWriter pw, String prefix, boolean dumpAll) { 2568 final TaskStack stack = getStack(); 2569 pw.print(prefix); pw.print("mDisplayId="); pw.print(getDisplayId()); 2570 if (stack != null) { 2571 pw.print(" stackId="); pw.print(stack.mStackId); 2572 } 2573 if (mNotOnAppsDisplay) { 2574 pw.print(" mNotOnAppsDisplay="); pw.print(mNotOnAppsDisplay); 2575 } 2576 pw.print(" mSession="); pw.print(mSession); 2577 pw.print(" mClient="); pw.println(mClient.asBinder()); 2578 pw.print(prefix); pw.print("mOwnerUid="); pw.print(mOwnerUid); 2579 pw.print(" mShowToOwnerOnly="); pw.print(mShowToOwnerOnly); 2580 pw.print(" package="); pw.print(mAttrs.packageName); 2581 pw.print(" appop="); pw.println(AppOpsManager.opToName(mAppOp)); 2582 pw.print(prefix); pw.print("mAttrs="); pw.println(mAttrs); 2583 pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth); 2584 pw.print(" h="); pw.print(mRequestedHeight); 2585 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq); 2586 if (mRequestedWidth != mLastRequestedWidth || mRequestedHeight != mLastRequestedHeight) { 2587 pw.print(prefix); pw.print("LastRequested w="); pw.print(mLastRequestedWidth); 2588 pw.print(" h="); pw.println(mLastRequestedHeight); 2589 } 2590 if (isChildWindow() || mLayoutAttached) { 2591 pw.print(prefix); pw.print("mAttachedWindow="); pw.print(mAttachedWindow); 2592 pw.print(" mLayoutAttached="); pw.println(mLayoutAttached); 2593 } 2594 if (mIsImWindow || mIsWallpaper || mIsFloatingLayer) { 2595 pw.print(prefix); pw.print("mIsImWindow="); pw.print(mIsImWindow); 2596 pw.print(" mIsWallpaper="); pw.print(mIsWallpaper); 2597 pw.print(" mIsFloatingLayer="); pw.print(mIsFloatingLayer); 2598 pw.print(" mWallpaperVisible="); pw.println(mWallpaperVisible); 2599 } 2600 if (dumpAll) { 2601 pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer); 2602 pw.print(" mSubLayer="); pw.print(mSubLayer); 2603 pw.print(" mAnimLayer="); pw.print(mLayer); pw.print("+"); 2604 pw.print((mTargetAppToken != null ? 2605 mTargetAppToken.mAppAnimator.animLayerAdjustment 2606 : (mAppToken != null ? mAppToken.mAppAnimator.animLayerAdjustment : 0))); 2607 pw.print("="); pw.print(mWinAnimator.mAnimLayer); 2608 pw.print(" mLastLayer="); pw.println(mWinAnimator.mLastLayer); 2609 } 2610 if (dumpAll) { 2611 pw.print(prefix); pw.print("mToken="); pw.println(mToken); 2612 pw.print(prefix); pw.print("mRootToken="); pw.println(mRootToken); 2613 if (mAppToken != null) { 2614 pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken); 2615 pw.print(prefix); pw.print(" isAnimatingWithSavedSurface()="); 2616 pw.print(isAnimatingWithSavedSurface()); 2617 pw.print(" mAppDied=");pw.println(mAppDied); 2618 } 2619 if (mTargetAppToken != null) { 2620 pw.print(prefix); pw.print("mTargetAppToken="); pw.println(mTargetAppToken); 2621 } 2622 pw.print(prefix); pw.print("mViewVisibility=0x"); 2623 pw.print(Integer.toHexString(mViewVisibility)); 2624 pw.print(" mHaveFrame="); pw.print(mHaveFrame); 2625 pw.print(" mObscured="); pw.println(mObscured); 2626 pw.print(prefix); pw.print("mSeq="); pw.print(mSeq); 2627 pw.print(" mSystemUiVisibility=0x"); 2628 pw.println(Integer.toHexString(mSystemUiVisibility)); 2629 } 2630 if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || !mAppOpVisibility 2631 || mAttachedHidden || mPermanentlyHidden) { 2632 pw.print(prefix); pw.print("mPolicyVisibility="); 2633 pw.print(mPolicyVisibility); 2634 pw.print(" mPolicyVisibilityAfterAnim="); 2635 pw.print(mPolicyVisibilityAfterAnim); 2636 pw.print(" mAppOpVisibility="); 2637 pw.print(mAppOpVisibility); 2638 pw.print(" mAttachedHidden="); pw.println(mAttachedHidden); 2639 pw.print(" mPermanentlyHidden="); pw.println(mPermanentlyHidden); 2640 } 2641 if (!mRelayoutCalled || mLayoutNeeded) { 2642 pw.print(prefix); pw.print("mRelayoutCalled="); pw.print(mRelayoutCalled); 2643 pw.print(" mLayoutNeeded="); pw.println(mLayoutNeeded); 2644 } 2645 if (mXOffset != 0 || mYOffset != 0) { 2646 pw.print(prefix); pw.print("Offsets x="); pw.print(mXOffset); 2647 pw.print(" y="); pw.println(mYOffset); 2648 } 2649 if (dumpAll) { 2650 pw.print(prefix); pw.print("mGivenContentInsets="); 2651 mGivenContentInsets.printShortString(pw); 2652 pw.print(" mGivenVisibleInsets="); 2653 mGivenVisibleInsets.printShortString(pw); 2654 pw.println(); 2655 if (mTouchableInsets != 0 || mGivenInsetsPending) { 2656 pw.print(prefix); pw.print("mTouchableInsets="); pw.print(mTouchableInsets); 2657 pw.print(" mGivenInsetsPending="); pw.println(mGivenInsetsPending); 2658 Region region = new Region(); 2659 getTouchableRegion(region); 2660 pw.print(prefix); pw.print("touchable region="); pw.println(region); 2661 } 2662 pw.print(prefix); pw.print("mMergedConfiguration="); pw.println(mMergedConfiguration); 2663 } 2664 pw.print(prefix); pw.print("mHasSurface="); pw.print(mHasSurface); 2665 pw.print(" mShownPosition="); mShownPosition.printShortString(pw); 2666 pw.print(" isReadyForDisplay()="); pw.print(isReadyForDisplay()); 2667 pw.print(" hasSavedSurface()="); pw.print(hasSavedSurface()); 2668 pw.print(" mWindowRemovalAllowed="); pw.println(mWindowRemovalAllowed); 2669 if (dumpAll) { 2670 pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw); 2671 pw.print(" last="); mLastFrame.printShortString(pw); 2672 pw.println(); 2673 } 2674 if (mEnforceSizeCompat) { 2675 pw.print(prefix); pw.print("mCompatFrame="); mCompatFrame.printShortString(pw); 2676 pw.println(); 2677 } 2678 if (dumpAll) { 2679 pw.print(prefix); pw.print("Frames: containing="); 2680 mContainingFrame.printShortString(pw); 2681 pw.print(" parent="); mParentFrame.printShortString(pw); 2682 pw.println(); 2683 pw.print(prefix); pw.print(" display="); mDisplayFrame.printShortString(pw); 2684 pw.print(" overscan="); mOverscanFrame.printShortString(pw); 2685 pw.println(); 2686 pw.print(prefix); pw.print(" content="); mContentFrame.printShortString(pw); 2687 pw.print(" visible="); mVisibleFrame.printShortString(pw); 2688 pw.println(); 2689 pw.print(prefix); pw.print(" decor="); mDecorFrame.printShortString(pw); 2690 pw.println(); 2691 pw.print(prefix); pw.print(" outset="); mOutsetFrame.printShortString(pw); 2692 pw.println(); 2693 pw.print(prefix); pw.print("Cur insets: overscan="); 2694 mOverscanInsets.printShortString(pw); 2695 pw.print(" content="); mContentInsets.printShortString(pw); 2696 pw.print(" visible="); mVisibleInsets.printShortString(pw); 2697 pw.print(" stable="); mStableInsets.printShortString(pw); 2698 pw.print(" surface="); mAttrs.surfaceInsets.printShortString(pw); 2699 pw.print(" outsets="); mOutsets.printShortString(pw); 2700 pw.println(); 2701 pw.print(prefix); pw.print("Lst insets: overscan="); 2702 mLastOverscanInsets.printShortString(pw); 2703 pw.print(" content="); mLastContentInsets.printShortString(pw); 2704 pw.print(" visible="); mLastVisibleInsets.printShortString(pw); 2705 pw.print(" stable="); mLastStableInsets.printShortString(pw); 2706 pw.print(" physical="); mLastOutsets.printShortString(pw); 2707 pw.print(" outset="); mLastOutsets.printShortString(pw); 2708 pw.println(); 2709 } 2710 pw.print(prefix); pw.print(mWinAnimator); pw.println(":"); 2711 mWinAnimator.dump(pw, prefix + " ", dumpAll); 2712 if (mAnimatingExit || mRemoveOnExit || mDestroying || mRemoved) { 2713 pw.print(prefix); pw.print("mAnimatingExit="); pw.print(mAnimatingExit); 2714 pw.print(" mRemoveOnExit="); pw.print(mRemoveOnExit); 2715 pw.print(" mDestroying="); pw.print(mDestroying); 2716 pw.print(" mRemoved="); pw.println(mRemoved); 2717 } 2718 if (mOrientationChanging || mAppFreezing || mTurnOnScreen) { 2719 pw.print(prefix); pw.print("mOrientationChanging="); 2720 pw.print(mOrientationChanging); 2721 pw.print(" mAppFreezing="); pw.print(mAppFreezing); 2722 pw.print(" mTurnOnScreen="); pw.println(mTurnOnScreen); 2723 } 2724 if (mLastFreezeDuration != 0) { 2725 pw.print(prefix); pw.print("mLastFreezeDuration="); 2726 TimeUtils.formatDuration(mLastFreezeDuration, pw); pw.println(); 2727 } 2728 if (mHScale != 1 || mVScale != 1) { 2729 pw.print(prefix); pw.print("mHScale="); pw.print(mHScale); 2730 pw.print(" mVScale="); pw.println(mVScale); 2731 } 2732 if (mWallpaperX != -1 || mWallpaperY != -1) { 2733 pw.print(prefix); pw.print("mWallpaperX="); pw.print(mWallpaperX); 2734 pw.print(" mWallpaperY="); pw.println(mWallpaperY); 2735 } 2736 if (mWallpaperXStep != -1 || mWallpaperYStep != -1) { 2737 pw.print(prefix); pw.print("mWallpaperXStep="); pw.print(mWallpaperXStep); 2738 pw.print(" mWallpaperYStep="); pw.println(mWallpaperYStep); 2739 } 2740 if (mWallpaperDisplayOffsetX != Integer.MIN_VALUE 2741 || mWallpaperDisplayOffsetY != Integer.MIN_VALUE) { 2742 pw.print(prefix); pw.print("mWallpaperDisplayOffsetX="); 2743 pw.print(mWallpaperDisplayOffsetX); 2744 pw.print(" mWallpaperDisplayOffsetY="); 2745 pw.println(mWallpaperDisplayOffsetY); 2746 } 2747 if (mDrawLock != null) { 2748 pw.print(prefix); pw.println("mDrawLock=" + mDrawLock); 2749 } 2750 if (isDragResizing()) { 2751 pw.print(prefix); pw.println("isDragResizing=" + isDragResizing()); 2752 } 2753 if (computeDragResizing()) { 2754 pw.print(prefix); pw.println("computeDragResizing=" + computeDragResizing()); 2755 } 2756 } 2757 2758 String makeInputChannelName() { 2759 return Integer.toHexString(System.identityHashCode(this)) 2760 + " " + getWindowTag(); 2761 } 2762 2763 CharSequence getWindowTag() { 2764 CharSequence tag = mAttrs.getTitle(); 2765 if (tag == null || tag.length() <= 0) { 2766 tag = mAttrs.packageName; 2767 } 2768 return tag; 2769 } 2770 2771 @Override 2772 public String toString() { 2773 final CharSequence title = getWindowTag(); 2774 if (mStringNameCache == null || mLastTitle != title || mWasExiting != mAnimatingExit) { 2775 mLastTitle = title; 2776 mWasExiting = mAnimatingExit; 2777 mStringNameCache = "Window{" + Integer.toHexString(System.identityHashCode(this)) 2778 + " u" + UserHandle.getUserId(mSession.mUid) 2779 + " " + mLastTitle + (mAnimatingExit ? " EXITING}" : "}"); 2780 } 2781 return mStringNameCache; 2782 } 2783 2784 void transformClipRectFromScreenToSurfaceSpace(Rect clipRect) { 2785 if (mHScale >= 0) { 2786 clipRect.left = (int) (clipRect.left / mHScale); 2787 clipRect.right = (int) Math.ceil(clipRect.right / mHScale); 2788 } 2789 if (mVScale >= 0) { 2790 clipRect.top = (int) (clipRect.top / mVScale); 2791 clipRect.bottom = (int) Math.ceil(clipRect.bottom / mVScale); 2792 } 2793 } 2794 2795 void applyGravityAndUpdateFrame(Rect containingFrame, Rect displayFrame) { 2796 final int pw = containingFrame.width(); 2797 final int ph = containingFrame.height(); 2798 final Task task = getTask(); 2799 final boolean nonFullscreenTask = isInMultiWindowMode(); 2800 final boolean noLimits = (mAttrs.flags & FLAG_LAYOUT_NO_LIMITS) != 0; 2801 2802 // We need to fit it to the display if either 2803 // a) The task is fullscreen, or we don't have a task (we assume fullscreen for the taskless 2804 // windows) 2805 // b) If it's a child window, we also need to fit it to the display unless 2806 // FLAG_LAYOUT_NO_LIMITS is set. This is so we place Popup and similar windows on screen, 2807 // but SurfaceViews want to be always at a specific location so we don't fit it to the 2808 // display. 2809 final boolean fitToDisplay = (task == null || !nonFullscreenTask) 2810 || (isChildWindow() && !noLimits); 2811 float x, y; 2812 int w,h; 2813 2814 if ((mAttrs.flags & FLAG_SCALED) != 0) { 2815 if (mAttrs.width < 0) { 2816 w = pw; 2817 } else if (mEnforceSizeCompat) { 2818 w = (int)(mAttrs.width * mGlobalScale + .5f); 2819 } else { 2820 w = mAttrs.width; 2821 } 2822 if (mAttrs.height < 0) { 2823 h = ph; 2824 } else if (mEnforceSizeCompat) { 2825 h = (int)(mAttrs.height * mGlobalScale + .5f); 2826 } else { 2827 h = mAttrs.height; 2828 } 2829 } else { 2830 if (mAttrs.width == MATCH_PARENT) { 2831 w = pw; 2832 } else if (mEnforceSizeCompat) { 2833 w = (int)(mRequestedWidth * mGlobalScale + .5f); 2834 } else { 2835 w = mRequestedWidth; 2836 } 2837 if (mAttrs.height == MATCH_PARENT) { 2838 h = ph; 2839 } else if (mEnforceSizeCompat) { 2840 h = (int)(mRequestedHeight * mGlobalScale + .5f); 2841 } else { 2842 h = mRequestedHeight; 2843 } 2844 } 2845 2846 if (mEnforceSizeCompat) { 2847 x = mAttrs.x * mGlobalScale; 2848 y = mAttrs.y * mGlobalScale; 2849 } else { 2850 x = mAttrs.x; 2851 y = mAttrs.y; 2852 } 2853 2854 if (nonFullscreenTask && !layoutInParentFrame()) { 2855 // Make sure window fits in containing frame since it is in a non-fullscreen task as 2856 // required by {@link Gravity#apply} call. 2857 w = Math.min(w, pw); 2858 h = Math.min(h, ph); 2859 } 2860 2861 // Set mFrame 2862 Gravity.apply(mAttrs.gravity, w, h, containingFrame, 2863 (int) (x + mAttrs.horizontalMargin * pw), 2864 (int) (y + mAttrs.verticalMargin * ph), mFrame); 2865 2866 // Now make sure the window fits in the overall display frame. 2867 if (fitToDisplay) { 2868 Gravity.applyDisplay(mAttrs.gravity, displayFrame, mFrame); 2869 } 2870 2871 // We need to make sure we update the CompatFrame as it is used for 2872 // cropping decisions, etc, on systems where we lack a decor layer. 2873 mCompatFrame.set(mFrame); 2874 if (mEnforceSizeCompat) { 2875 // See comparable block in computeFrameLw. 2876 mCompatFrame.scale(mInvGlobalScale); 2877 } 2878 } 2879 2880 boolean isChildWindow() { 2881 return mAttachedWindow != null; 2882 } 2883 2884 boolean layoutInParentFrame() { 2885 return isChildWindow() && (mAttrs.privateFlags & PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME) != 0; 2886 } 2887 2888 void setReplacing(boolean animate) { 2889 if ((mAttrs.privateFlags & PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH) != 0 2890 || mAttrs.type == TYPE_APPLICATION_STARTING) { 2891 // We don't set replacing on starting windows since they are added by window manager and 2892 // not the client so won't be replaced by the client. 2893 return; 2894 } 2895 2896 mWillReplaceWindow = true; 2897 mReplacingWindow = null; 2898 mAnimateReplacingWindow = animate; 2899 } 2900 2901 void resetReplacing() { 2902 mWillReplaceWindow = false; 2903 mReplacingWindow = null; 2904 mAnimateReplacingWindow = false; 2905 } 2906 2907 void requestUpdateWallpaperIfNeeded() { 2908 if (mDisplayContent != null && (mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) { 2909 mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 2910 mDisplayContent.layoutNeeded = true; 2911 mService.mWindowPlacerLocked.requestTraversal(); 2912 } 2913 } 2914 2915 float translateToWindowX(float x) { 2916 float winX = x - mFrame.left; 2917 if (mEnforceSizeCompat) { 2918 winX *= mGlobalScale; 2919 } 2920 return winX; 2921 } 2922 2923 float translateToWindowY(float y) { 2924 float winY = y - mFrame.top; 2925 if (mEnforceSizeCompat) { 2926 winY *= mGlobalScale; 2927 } 2928 return winY; 2929 } 2930 2931 void transferDimToReplacement() { 2932 final DimLayer.DimLayerUser dimLayerUser = getDimLayerUser(); 2933 if (dimLayerUser != null && mDisplayContent != null) { 2934 mDisplayContent.mDimLayerController.applyDim(dimLayerUser, 2935 mReplacingWindow.mWinAnimator, 2936 (mAttrs.flags & FLAG_DIM_BEHIND) != 0 ? true : false); 2937 } 2938 } 2939 2940 // During activity relaunch due to resize, we sometimes use window replacement 2941 // for only child windows (as the main window is handled by window preservation) 2942 // and the big surface. 2943 // 2944 // Though windows of TYPE_APPLICATION or TYPE_DRAWN_APPLICATION (as opposed to 2945 // TYPE_BASE_APPLICATION) are not children in the sense of an attached window, 2946 // we also want to replace them at such phases, as they won't be covered by window 2947 // preservation, and in general we expect them to return following relaunch. 2948 boolean shouldBeReplacedWithChildren() { 2949 return isChildWindow() || mAttrs.type == TYPE_APPLICATION 2950 || mAttrs.type == TYPE_DRAWN_APPLICATION; 2951 } 2952 2953 public int getRotationAnimationHint() { 2954 if (mAppToken != null) { 2955 return mAppToken.mRotationAnimationHint; 2956 } else { 2957 return -1; 2958 } 2959 } 2960 2961 public boolean isRtl() { 2962 return mMergedConfiguration.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL; 2963 } 2964 2965 public boolean isRemovedOrHidden() { 2966 return mPermanentlyHidden || mAnimatingExit 2967 || mRemoveOnExit || mWindowRemovalAllowed 2968 || mViewVisibility == View.GONE; 2969 } 2970 } 2971