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