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