1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.wm; 18 19 import static android.app.ActivityManager.StackId.DOCKED_STACK_ID; 20 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID; 21 import static android.app.ActivityManager.StackId.HOME_STACK_ID; 22 import static android.app.ActivityManager.StackId.PINNED_STACK_ID; 23 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND; 24 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET; 25 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 26 import static android.view.Display.DEFAULT_DISPLAY; 27 import static android.view.Display.FLAG_PRIVATE; 28 import static android.view.Surface.ROTATION_0; 29 import static android.view.Surface.ROTATION_180; 30 import static android.view.Surface.ROTATION_270; 31 import static android.view.Surface.ROTATION_90; 32 import static android.view.View.GONE; 33 import static android.view.WindowManager.DOCKED_BOTTOM; 34 import static android.view.WindowManager.DOCKED_INVALID; 35 import static android.view.WindowManager.DOCKED_TOP; 36 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 37 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; 38 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; 39 import static android.view.WindowManager.LayoutParams.FLAG_SECURE; 40 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; 41 import static android.view.WindowManager.LayoutParams.NEEDS_MENU_SET_TRUE; 42 import static android.view.WindowManager.LayoutParams.NEEDS_MENU_UNSET; 43 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; 44 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; 45 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; 46 import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS; 47 import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION; 48 import static android.view.WindowManager.LayoutParams.TYPE_DREAM; 49 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; 50 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; 51 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; 52 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG; 53 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR; 54 import static android.view.WindowManager.LayoutParams.TYPE_TOAST; 55 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; 56 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; 57 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG; 58 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 59 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 60 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE; 61 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT; 62 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY; 63 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS; 64 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT; 65 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD; 66 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS; 67 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT; 68 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS; 69 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION; 70 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT; 71 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREEN_ON; 72 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK; 73 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT; 74 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER; 75 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT; 76 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS; 77 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS; 78 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS; 79 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; 80 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 81 import static com.android.server.wm.WindowManagerService.CUSTOM_SCREEN_ROTATION; 82 import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION; 83 import static com.android.server.wm.WindowManagerService.H.UPDATE_DOCKED_STACK_DIVIDER; 84 import static com.android.server.wm.WindowManagerService.H.WINDOW_HIDE_TIMEOUT; 85 import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD; 86 import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION; 87 import static com.android.server.wm.WindowManagerService.SEAMLESS_ROTATION_TIMEOUT_DURATION; 88 import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER; 89 import static com.android.server.wm.WindowManagerService.TYPE_LAYER_OFFSET; 90 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES; 91 import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_ACTIVE; 92 import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_TIMEOUT; 93 import static com.android.server.wm.WindowManagerService.WINDOW_FREEZE_TIMEOUT_DURATION; 94 import static com.android.server.wm.WindowManagerService.dipToPixel; 95 import static com.android.server.wm.WindowManagerService.logSurface; 96 import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP; 97 import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING; 98 import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW; 99 import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE; 100 101 import android.annotation.NonNull; 102 import android.app.ActivityManager.StackId; 103 import android.content.res.CompatibilityInfo; 104 import android.content.res.Configuration; 105 import android.graphics.Bitmap; 106 import android.graphics.GraphicBuffer; 107 import android.graphics.Matrix; 108 import android.graphics.Rect; 109 import android.graphics.RectF; 110 import android.graphics.Region; 111 import android.graphics.Region.Op; 112 import android.hardware.display.DisplayManagerInternal; 113 import android.os.Debug; 114 import android.os.Handler; 115 import android.os.IBinder; 116 import android.os.RemoteException; 117 import android.os.SystemClock; 118 import android.util.DisplayMetrics; 119 import android.util.MutableBoolean; 120 import android.util.Slog; 121 import android.view.Display; 122 import android.view.DisplayInfo; 123 import android.view.InputDevice; 124 import android.view.Surface; 125 import android.view.SurfaceControl; 126 import android.view.WindowManagerPolicy; 127 128 import com.android.internal.annotations.VisibleForTesting; 129 import com.android.internal.util.ToBooleanFunction; 130 import com.android.internal.view.IInputMethodClient; 131 132 import java.io.FileDescriptor; 133 import java.io.PrintWriter; 134 import java.util.ArrayList; 135 import java.util.Comparator; 136 import java.util.HashMap; 137 import java.util.Iterator; 138 import java.util.LinkedList; 139 import java.util.List; 140 import java.util.function.Consumer; 141 import java.util.function.Predicate; 142 143 /** 144 * Utility class for keeping track of the WindowStates and other pertinent contents of a 145 * particular Display. 146 * 147 * IMPORTANT: No method from this class should ever be used without holding 148 * WindowManagerService.mWindowMap. 149 */ 150 class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowContainer> { 151 private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayContent" : TAG_WM; 152 153 /** Unique identifier of this stack. */ 154 private final int mDisplayId; 155 156 /** The containers below are the only child containers the display can have. */ 157 // Contains all window containers that are related to apps (Activities) 158 private final TaskStackContainers mTaskStackContainers = new TaskStackContainers(); 159 // Contains all non-app window containers that should be displayed above the app containers 160 // (e.g. Status bar) 161 private final NonAppWindowContainers mAboveAppWindowsContainers = 162 new NonAppWindowContainers("mAboveAppWindowsContainers"); 163 // Contains all non-app window containers that should be displayed below the app containers 164 // (e.g. Wallpaper). 165 private final NonAppWindowContainers mBelowAppWindowsContainers = 166 new NonAppWindowContainers("mBelowAppWindowsContainers"); 167 // Contains all IME window containers. Note that the z-ordering of the IME windows will depend 168 // on the IME target. We mainly have this container grouping so we can keep track of all the IME 169 // window containers together and move them in-sync if/when needed. 170 private final NonAppWindowContainers mImeWindowsContainers = 171 new NonAppWindowContainers("mImeWindowsContainers"); 172 173 private WindowState mTmpWindow; 174 private WindowState mTmpWindow2; 175 private WindowAnimator mTmpWindowAnimator; 176 private boolean mTmpRecoveringMemory; 177 private boolean mUpdateImeTarget; 178 private boolean mTmpInitial; 179 private int mMaxUiWidth; 180 181 // Mapping from a token IBinder to a WindowToken object on this display. 182 private final HashMap<IBinder, WindowToken> mTokenMap = new HashMap(); 183 184 // Initial display metrics. 185 int mInitialDisplayWidth = 0; 186 int mInitialDisplayHeight = 0; 187 int mInitialDisplayDensity = 0; 188 189 /** 190 * Overridden display size. Initialized with {@link #mInitialDisplayWidth} 191 * and {@link #mInitialDisplayHeight}, but can be set via shell command "adb shell wm size". 192 * @see WindowManagerService#setForcedDisplaySize(int, int, int) 193 */ 194 int mBaseDisplayWidth = 0; 195 int mBaseDisplayHeight = 0; 196 /** 197 * Overridden display density for current user. Initialized with {@link #mInitialDisplayDensity} 198 * but can be set from Settings or via shell command "adb shell wm density". 199 * @see WindowManagerService#setForcedDisplayDensityForUser(int, int, int) 200 */ 201 int mBaseDisplayDensity = 0; 202 boolean mDisplayScalingDisabled; 203 private final DisplayInfo mDisplayInfo = new DisplayInfo(); 204 private final Display mDisplay; 205 private final DisplayMetrics mDisplayMetrics = new DisplayMetrics(); 206 /** 207 * For default display it contains real metrics, empty for others. 208 * @see WindowManagerService#createWatermarkInTransaction() 209 */ 210 final DisplayMetrics mRealDisplayMetrics = new DisplayMetrics(); 211 /** @see #computeCompatSmallestWidth(boolean, int, int, int, int) */ 212 private final DisplayMetrics mTmpDisplayMetrics = new DisplayMetrics(); 213 /** 214 * Compat metrics computed based on {@link #mDisplayMetrics}. 215 * @see #updateDisplayAndOrientation(int) 216 */ 217 private final DisplayMetrics mCompatDisplayMetrics = new DisplayMetrics(); 218 219 /** The desired scaling factor for compatible apps. */ 220 float mCompatibleScreenScale; 221 222 /** 223 * Current rotation of the display. 224 * Constants as per {@link android.view.Surface.Rotation}. 225 * 226 * @see #updateRotationUnchecked(boolean) 227 */ 228 private int mRotation = 0; 229 /** 230 * Last applied orientation of the display. 231 * Constants as per {@link android.content.pm.ActivityInfo.ScreenOrientation}. 232 * 233 * @see WindowManagerService#updateOrientationFromAppTokensLocked(boolean, int) 234 */ 235 private int mLastOrientation = SCREEN_ORIENTATION_UNSPECIFIED; 236 /** 237 * Flag indicating that the application is receiving an orientation that has different metrics 238 * than it expected. E.g. Portrait instead of Landscape. 239 * 240 * @see #updateRotationUnchecked(boolean) 241 */ 242 private boolean mAltOrientation = false; 243 /** 244 * Orientation forced by some window. If there is no visible window that specifies orientation 245 * it is set to {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED}. 246 * 247 * @see NonAppWindowContainers#getOrientation() 248 */ 249 private int mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED; 250 /** 251 * Last orientation forced by the keyguard. It is applied when keyguard is shown and is not 252 * occluded. 253 * 254 * @see NonAppWindowContainers#getOrientation() 255 */ 256 private int mLastKeyguardForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED; 257 258 private Rect mBaseDisplayRect = new Rect(); 259 private Rect mContentRect = new Rect(); 260 261 // Accessed directly by all users. 262 private boolean mLayoutNeeded; 263 int pendingLayoutChanges; 264 // TODO(multi-display): remove some of the usages. 265 boolean isDefaultDisplay; 266 267 /** Window tokens that are in the process of exiting, but still on screen for animations. */ 268 final ArrayList<WindowToken> mExitingTokens = new ArrayList<>(); 269 270 /** A special TaskStack with id==HOME_STACK_ID that moves to the bottom whenever any TaskStack 271 * (except a future lockscreen TaskStack) moves to the top. */ 272 private TaskStack mHomeStack = null; 273 274 /** Detect user tapping outside of current focused task bounds .*/ 275 TaskTapPointerEventListener mTapDetector; 276 277 /** Detect user tapping outside of current focused stack bounds .*/ 278 private Region mTouchExcludeRegion = new Region(); 279 280 /** Save allocating when calculating rects */ 281 private final Rect mTmpRect = new Rect(); 282 private final Rect mTmpRect2 = new Rect(); 283 private final RectF mTmpRectF = new RectF(); 284 private final Matrix mTmpMatrix = new Matrix(); 285 private final Region mTmpRegion = new Region(); 286 287 WindowManagerService mService; 288 289 /** Remove this display when animation on it has completed. */ 290 private boolean mDeferredRemoval; 291 292 final DockedStackDividerController mDividerControllerLocked; 293 final PinnedStackController mPinnedStackControllerLocked; 294 295 DimLayerController mDimLayerController; 296 297 final ArrayList<WindowState> mTapExcludedWindows = new ArrayList<>(); 298 299 private boolean mHaveBootMsg = false; 300 private boolean mHaveApp = false; 301 private boolean mHaveWallpaper = false; 302 private boolean mHaveKeyguard = true; 303 304 private final LinkedList<AppWindowToken> mTmpUpdateAllDrawn = new LinkedList(); 305 306 private final TaskForResizePointSearchResult mTmpTaskForResizePointSearchResult = 307 new TaskForResizePointSearchResult(); 308 private final ApplySurfaceChangesTransactionState mTmpApplySurfaceChangesTransactionState = 309 new ApplySurfaceChangesTransactionState(); 310 private final ScreenshotApplicationState mScreenshotApplicationState = 311 new ScreenshotApplicationState(); 312 313 // True if this display is in the process of being removed. Used to determine if the removal of 314 // the display's direct children should be allowed. 315 private boolean mRemovingDisplay = false; 316 317 // {@code false} if this display is in the processing of being created. 318 private boolean mDisplayReady = false; 319 320 private final WindowLayersController mLayersController; 321 WallpaperController mWallpaperController; 322 int mInputMethodAnimLayerAdjustment; 323 324 private final Consumer<WindowState> mUpdateWindowsForAnimator = w -> { 325 WindowStateAnimator winAnimator = w.mWinAnimator; 326 if (winAnimator.hasSurface()) { 327 final boolean wasAnimating = winAnimator.mWasAnimating; 328 final boolean nowAnimating = winAnimator.stepAnimationLocked( 329 mTmpWindowAnimator.mCurrentTime); 330 winAnimator.mWasAnimating = nowAnimating; 331 mTmpWindowAnimator.orAnimating(nowAnimating); 332 333 if (DEBUG_WALLPAPER) Slog.v(TAG, 334 w + ": wasAnimating=" + wasAnimating + ", nowAnimating=" + nowAnimating); 335 336 if (wasAnimating && !winAnimator.mAnimating 337 && mWallpaperController.isWallpaperTarget(w)) { 338 mTmpWindowAnimator.mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE; 339 pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 340 if (DEBUG_LAYOUT_REPEATS) { 341 mService.mWindowPlacerLocked.debugLayoutRepeats( 342 "updateWindowsAndWallpaperLocked 2", pendingLayoutChanges); 343 } 344 } 345 } 346 347 final AppWindowToken atoken = w.mAppToken; 348 if (winAnimator.mDrawState == READY_TO_SHOW) { 349 if (atoken == null || atoken.allDrawn) { 350 if (w.performShowLocked()) { 351 pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM; 352 if (DEBUG_LAYOUT_REPEATS) { 353 mService.mWindowPlacerLocked.debugLayoutRepeats( 354 "updateWindowsAndWallpaperLocked 5", pendingLayoutChanges); 355 } 356 } 357 } 358 } 359 final AppWindowAnimator appAnimator = winAnimator.mAppAnimator; 360 if (appAnimator != null && appAnimator.thumbnail != null) { 361 if (appAnimator.thumbnailTransactionSeq 362 != mTmpWindowAnimator.mAnimTransactionSequence) { 363 appAnimator.thumbnailTransactionSeq = 364 mTmpWindowAnimator.mAnimTransactionSequence; 365 appAnimator.thumbnailLayer = 0; 366 } 367 if (appAnimator.thumbnailLayer < winAnimator.mAnimLayer) { 368 appAnimator.thumbnailLayer = winAnimator.mAnimLayer; 369 } 370 } 371 }; 372 373 private final Consumer<WindowState> mUpdateWallpaperForAnimator = w -> { 374 final WindowStateAnimator winAnimator = w.mWinAnimator; 375 if (winAnimator.mSurfaceController == null || !winAnimator.hasSurface()) { 376 return; 377 } 378 379 final int flags = w.mAttrs.flags; 380 381 // If this window is animating, make a note that we have an animating window and take 382 // care of a request to run a detached wallpaper animation. 383 if (winAnimator.mAnimating) { 384 if (winAnimator.mAnimation != null) { 385 if ((flags & FLAG_SHOW_WALLPAPER) != 0 386 && winAnimator.mAnimation.getDetachWallpaper()) { 387 mTmpWindow = w; 388 } 389 final int color = winAnimator.mAnimation.getBackgroundColor(); 390 if (color != 0) { 391 final TaskStack stack = w.getStack(); 392 if (stack != null) { 393 stack.setAnimationBackground(winAnimator, color); 394 } 395 } 396 } 397 mTmpWindowAnimator.setAnimating(true); 398 } 399 400 // If this window's app token is running a detached wallpaper animation, make a note so 401 // we can ensure the wallpaper is displayed behind it. 402 final AppWindowAnimator appAnimator = winAnimator.mAppAnimator; 403 if (appAnimator != null && appAnimator.animation != null 404 && appAnimator.animating) { 405 if ((flags & FLAG_SHOW_WALLPAPER) != 0 406 && appAnimator.animation.getDetachWallpaper()) { 407 mTmpWindow = w; 408 } 409 410 final int color = appAnimator.animation.getBackgroundColor(); 411 if (color != 0) { 412 final TaskStack stack = w.getStack(); 413 if (stack != null) { 414 stack.setAnimationBackground(winAnimator, color); 415 } 416 } 417 } 418 }; 419 420 private final Consumer<WindowState> mScheduleToastTimeout = w -> { 421 final int lostFocusUid = mTmpWindow.mOwnerUid; 422 final Handler handler = mService.mH; 423 if (w.mAttrs.type == TYPE_TOAST && w.mOwnerUid == lostFocusUid) { 424 if (!handler.hasMessages(WINDOW_HIDE_TIMEOUT, w)) { 425 handler.sendMessageDelayed(handler.obtainMessage(WINDOW_HIDE_TIMEOUT, w), 426 w.mAttrs.hideTimeoutMilliseconds); 427 } 428 } 429 }; 430 431 private final ToBooleanFunction<WindowState> mFindFocusedWindow = w -> { 432 final AppWindowToken focusedApp = mService.mFocusedApp; 433 if (DEBUG_FOCUS) Slog.v(TAG_WM, "Looking for focus: " + w 434 + ", flags=" + w.mAttrs.flags + ", canReceive=" + w.canReceiveKeys()); 435 436 if (!w.canReceiveKeys()) { 437 return false; 438 } 439 440 final AppWindowToken wtoken = w.mAppToken; 441 442 // If this window's application has been removed, just skip it. 443 if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) { 444 if (DEBUG_FOCUS) Slog.v(TAG_WM, "Skipping " + wtoken + " because " 445 + (wtoken.removed ? "removed" : "sendingToBottom")); 446 return false; 447 } 448 449 if (focusedApp == null) { 450 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp=null" 451 + " using new focus @ " + w); 452 mTmpWindow = w; 453 return true; 454 } 455 456 if (!focusedApp.windowsAreFocusable()) { 457 // Current focused app windows aren't focusable... 458 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp windows not" 459 + " focusable using new focus @ " + w); 460 mTmpWindow = w; 461 return true; 462 } 463 464 // Descend through all of the app tokens and find the first that either matches 465 // win.mAppToken (return win) or mFocusedApp (return null). 466 if (wtoken != null && w.mAttrs.type != TYPE_APPLICATION_STARTING) { 467 if (focusedApp.compareTo(wtoken) > 0) { 468 // App stack below focused app stack. No focus for you!!! 469 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, 470 "findFocusedWindow: Reached focused app=" + focusedApp); 471 mTmpWindow = null; 472 return true; 473 } 474 } 475 476 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: Found new focus @ " + w); 477 mTmpWindow = w; 478 return true; 479 }; 480 481 private final Consumer<WindowState> mPrepareWindowSurfaces = 482 w -> w.mWinAnimator.prepareSurfaceLocked(true); 483 484 private final Consumer<WindowState> mPerformLayout = w -> { 485 // Don't do layout of a window if it is not visible, or soon won't be visible, to avoid 486 // wasting time and funky changes while a window is animating away. 487 final boolean gone = (mTmpWindow != null && mService.mPolicy.canBeHiddenByKeyguardLw(w)) 488 || w.isGoneForLayoutLw(); 489 490 if (DEBUG_LAYOUT && !w.mLayoutAttached) { 491 Slog.v(TAG, "1ST PASS " + w + ": gone=" + gone + " mHaveFrame=" + w.mHaveFrame 492 + " mLayoutAttached=" + w.mLayoutAttached 493 + " screen changed=" + w.isConfigChanged()); 494 final AppWindowToken atoken = w.mAppToken; 495 if (gone) Slog.v(TAG, " GONE: mViewVisibility=" + w.mViewVisibility 496 + " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.hidden 497 + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested) 498 + " parentHidden=" + w.isParentWindowHidden()); 499 else Slog.v(TAG, " VIS: mViewVisibility=" + w.mViewVisibility 500 + " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.hidden 501 + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested) 502 + " parentHidden=" + w.isParentWindowHidden()); 503 } 504 505 // If this view is GONE, then skip it -- keep the current frame, and let the caller know 506 // so they can ignore it if they want. (We do the normal layout for INVISIBLE windows, 507 // since that means "perform layout as normal, just don't display"). 508 if (!gone || !w.mHaveFrame || w.mLayoutNeeded 509 || ((w.isConfigChanged() || w.setReportResizeHints()) 510 && !w.isGoneForLayoutLw() && 511 ((w.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 || 512 (w.mHasSurface && w.mAppToken != null && 513 w.mAppToken.layoutConfigChanges)))) { 514 if (!w.mLayoutAttached) { 515 if (mTmpInitial) { 516 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 517 w.mContentChanged = false; 518 } 519 if (w.mAttrs.type == TYPE_DREAM) { 520 // Don't layout windows behind a dream, so that if it does stuff like hide 521 // the status bar we won't get a bad transition when it goes away. 522 mTmpWindow = w; 523 } 524 w.mLayoutNeeded = false; 525 w.prelayout(); 526 final boolean firstLayout = !w.isLaidOut(); 527 mService.mPolicy.layoutWindowLw(w, null); 528 w.mLayoutSeq = mService.mLayoutSeq; 529 530 // If this is the first layout, we need to initialize the last inset values as 531 // otherwise we'd immediately cause an unnecessary resize. 532 if (firstLayout) { 533 w.updateLastInsetValues(); 534 } 535 536 // Window frames may have changed. Update dim layer with the new bounds. 537 final Task task = w.getTask(); 538 if (task != null) { 539 mDimLayerController.updateDimLayer(task); 540 } 541 542 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" + w.mFrame 543 + " mContainingFrame=" + w.mContainingFrame 544 + " mDisplayFrame=" + w.mDisplayFrame); 545 } 546 } 547 }; 548 549 private final Consumer<WindowState> mPerformLayoutAttached = w -> { 550 if (w.mLayoutAttached) { 551 if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + w + " mHaveFrame=" + w.mHaveFrame 552 + " mViewVisibility=" + w.mViewVisibility 553 + " mRelayoutCalled=" + w.mRelayoutCalled); 554 // If this view is GONE, then skip it -- keep the current frame, and let the caller 555 // know so they can ignore it if they want. (We do the normal layout for INVISIBLE 556 // windows, since that means "perform layout as normal, just don't display"). 557 if (mTmpWindow != null && mService.mPolicy.canBeHiddenByKeyguardLw(w)) { 558 return; 559 } 560 if ((w.mViewVisibility != GONE && w.mRelayoutCalled) || !w.mHaveFrame 561 || w.mLayoutNeeded) { 562 if (mTmpInitial) { 563 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 564 w.mContentChanged = false; 565 } 566 w.mLayoutNeeded = false; 567 w.prelayout(); 568 mService.mPolicy.layoutWindowLw(w, w.getParentWindow()); 569 w.mLayoutSeq = mService.mLayoutSeq; 570 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" + w.mFrame 571 + " mContainingFrame=" + w.mContainingFrame 572 + " mDisplayFrame=" + w.mDisplayFrame); 573 } 574 } else if (w.mAttrs.type == TYPE_DREAM) { 575 // Don't layout windows behind a dream, so that if it does stuff like hide the 576 // status bar we won't get a bad transition when it goes away. 577 mTmpWindow = mTmpWindow2; 578 } 579 }; 580 581 private final Predicate<WindowState> mComputeImeTargetPredicate = w -> { 582 if (DEBUG_INPUT_METHOD && mUpdateImeTarget) Slog.i(TAG_WM, "Checking window @" + w 583 + " fl=0x" + Integer.toHexString(w.mAttrs.flags)); 584 return w.canBeImeTarget(); 585 }; 586 587 private final Consumer<WindowState> mApplyPostLayoutPolicy = 588 w -> mService.mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs, w.getParentWindow(), 589 mService.mInputMethodTarget); 590 591 private final Consumer<WindowState> mApplySurfaceChangesTransaction = w -> { 592 final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked; 593 final boolean obscuredChanged = w.mObscured != 594 mTmpApplySurfaceChangesTransactionState.obscured; 595 final RootWindowContainer root = mService.mRoot; 596 // Only used if default window 597 final boolean someoneLosingFocus = !mService.mLosingFocus.isEmpty(); 598 599 // Update effect. 600 w.mObscured = mTmpApplySurfaceChangesTransactionState.obscured; 601 if (!mTmpApplySurfaceChangesTransactionState.obscured) { 602 final boolean isDisplayed = w.isDisplayedLw(); 603 604 if (isDisplayed && w.isObscuringDisplay()) { 605 // This window completely covers everything behind it, so we want to leave all 606 // of them as undimmed (for performance reasons). 607 root.mObscuringWindow = w; 608 mTmpApplySurfaceChangesTransactionState.obscured = true; 609 } 610 611 mTmpApplySurfaceChangesTransactionState.displayHasContent |= 612 root.handleNotObscuredLocked(w, 613 mTmpApplySurfaceChangesTransactionState.obscured, 614 mTmpApplySurfaceChangesTransactionState.syswin); 615 616 if (w.mHasSurface && isDisplayed) { 617 final int type = w.mAttrs.type; 618 if (type == TYPE_SYSTEM_DIALOG || type == TYPE_SYSTEM_ERROR 619 || (w.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { 620 mTmpApplySurfaceChangesTransactionState.syswin = true; 621 } 622 if (mTmpApplySurfaceChangesTransactionState.preferredRefreshRate == 0 623 && w.mAttrs.preferredRefreshRate != 0) { 624 mTmpApplySurfaceChangesTransactionState.preferredRefreshRate 625 = w.mAttrs.preferredRefreshRate; 626 } 627 if (mTmpApplySurfaceChangesTransactionState.preferredModeId == 0 628 && w.mAttrs.preferredDisplayModeId != 0) { 629 mTmpApplySurfaceChangesTransactionState.preferredModeId 630 = w.mAttrs.preferredDisplayModeId; 631 } 632 } 633 } 634 635 w.applyDimLayerIfNeeded(); 636 637 if (isDefaultDisplay && obscuredChanged && w.isVisibleLw() 638 && mWallpaperController.isWallpaperTarget(w)) { 639 // This is the wallpaper target and its obscured state changed... make sure the 640 // current wallpaper's visibility has been updated accordingly. 641 mWallpaperController.updateWallpaperVisibility(); 642 } 643 644 w.handleWindowMovedIfNeeded(); 645 646 final WindowStateAnimator winAnimator = w.mWinAnimator; 647 648 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); 649 w.mContentChanged = false; 650 651 // Moved from updateWindowsAndWallpaperLocked(). 652 if (w.mHasSurface) { 653 // Take care of the window being ready to display. 654 final boolean committed = winAnimator.commitFinishDrawingLocked(); 655 if (isDefaultDisplay && committed) { 656 if (w.mAttrs.type == TYPE_DREAM) { 657 // HACK: When a dream is shown, it may at that point hide the lock screen. 658 // So we need to redo the layout to let the phone window manager make this 659 // happen. 660 pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT; 661 if (DEBUG_LAYOUT_REPEATS) { 662 surfacePlacer.debugLayoutRepeats( 663 "dream and commitFinishDrawingLocked true", 664 pendingLayoutChanges); 665 } 666 } 667 if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) { 668 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 669 "First draw done in potential wallpaper target " + w); 670 root.mWallpaperMayChange = true; 671 pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 672 if (DEBUG_LAYOUT_REPEATS) { 673 surfacePlacer.debugLayoutRepeats( 674 "wallpaper and commitFinishDrawingLocked true", 675 pendingLayoutChanges); 676 } 677 } 678 } 679 final TaskStack stack = w.getStack(); 680 if ((!winAnimator.isAnimationStarting() && !winAnimator.isWaitingForOpening()) 681 || (stack != null && stack.isAnimatingBounds())) { 682 // Updates the shown frame before we set up the surface. This is needed 683 // because the resizing could change the top-left position (in addition to 684 // size) of the window. setSurfaceBoundariesLocked uses mShownPosition to 685 // position the surface. 686 // 687 // If an animation is being started, we can't call this method because the 688 // animation hasn't processed its initial transformation yet, but in general 689 // we do want to update the position if the window is animating. We make an exception 690 // for the bounds animating state, where an application may have been waiting 691 // for an exit animation to start, but instead enters PiP. We need to ensure 692 // we always recompute the top-left in this case. 693 winAnimator.computeShownFrameLocked(); 694 } 695 winAnimator.setSurfaceBoundariesLocked(mTmpRecoveringMemory /* recoveringMemory */); 696 } 697 698 final AppWindowToken atoken = w.mAppToken; 699 if (atoken != null) { 700 final boolean updateAllDrawn = atoken.updateDrawnWindowStates(w); 701 if (updateAllDrawn && !mTmpUpdateAllDrawn.contains(atoken)) { 702 mTmpUpdateAllDrawn.add(atoken); 703 } 704 } 705 706 if (isDefaultDisplay && someoneLosingFocus && w == mService.mCurrentFocus 707 && w.isDisplayedLw()) { 708 mTmpApplySurfaceChangesTransactionState.focusDisplayed = true; 709 } 710 711 w.updateResizingWindowIfNeeded(); 712 }; 713 714 /** 715 * Create new {@link DisplayContent} instance, add itself to the root window container and 716 * initialize direct children. 717 * @param display May not be null. 718 * @param service You know. 719 * @param layersController window layer controller used to assign layer to the windows on this 720 * display. 721 * @param wallpaperController wallpaper windows controller used to adjust the positioning of the 722 * wallpaper windows in the window list. 723 */ 724 DisplayContent(Display display, WindowManagerService service, 725 WindowLayersController layersController, WallpaperController wallpaperController) { 726 if (service.mRoot.getDisplayContent(display.getDisplayId()) != null) { 727 throw new IllegalArgumentException("Display with ID=" + display.getDisplayId() 728 + " already exists=" + service.mRoot.getDisplayContent(display.getDisplayId()) 729 + " new=" + display); 730 } 731 732 mDisplay = display; 733 mDisplayId = display.getDisplayId(); 734 mLayersController = layersController; 735 mWallpaperController = wallpaperController; 736 display.getDisplayInfo(mDisplayInfo); 737 display.getMetrics(mDisplayMetrics); 738 isDefaultDisplay = mDisplayId == DEFAULT_DISPLAY; 739 mService = service; 740 initializeDisplayBaseInfo(); 741 mDividerControllerLocked = new DockedStackDividerController(service, this); 742 mPinnedStackControllerLocked = new PinnedStackController(service, this); 743 mDimLayerController = new DimLayerController(this); 744 745 // These are the only direct children we should ever have and they are permanent. 746 super.addChild(mBelowAppWindowsContainers, null); 747 super.addChild(mTaskStackContainers, null); 748 super.addChild(mAboveAppWindowsContainers, null); 749 super.addChild(mImeWindowsContainers, null); 750 751 // Add itself as a child to the root container. 752 mService.mRoot.addChild(this, null); 753 754 // TODO(b/62541591): evaluate whether this is the best spot to declare the 755 // {@link DisplayContent} ready for use. 756 mDisplayReady = true; 757 } 758 759 boolean isReady() { 760 // The display is ready when the system and the individual display are both ready. 761 return mService.mDisplayReady && mDisplayReady; 762 } 763 764 int getDisplayId() { 765 return mDisplayId; 766 } 767 768 WindowToken getWindowToken(IBinder binder) { 769 return mTokenMap.get(binder); 770 } 771 772 AppWindowToken getAppWindowToken(IBinder binder) { 773 final WindowToken token = getWindowToken(binder); 774 if (token == null) { 775 return null; 776 } 777 return token.asAppWindowToken(); 778 } 779 780 private void addWindowToken(IBinder binder, WindowToken token) { 781 final DisplayContent dc = mService.mRoot.getWindowTokenDisplay(token); 782 if (dc != null) { 783 // We currently don't support adding a window token to the display if the display 784 // already has the binder mapped to another token. If there is a use case for supporting 785 // this moving forward we will either need to merge the WindowTokens some how or have 786 // the binder map to a list of window tokens. 787 throw new IllegalArgumentException("Can't map token=" + token + " to display=" 788 + getName() + " already mapped to display=" + dc + " tokens=" + dc.mTokenMap); 789 } 790 if (binder == null) { 791 throw new IllegalArgumentException("Can't map token=" + token + " to display=" 792 + getName() + " binder is null"); 793 } 794 if (token == null) { 795 throw new IllegalArgumentException("Can't map null token to display=" 796 + getName() + " binder=" + binder); 797 } 798 799 mTokenMap.put(binder, token); 800 801 if (token.asAppWindowToken() == null) { 802 // Add non-app token to container hierarchy on the display. App tokens are added through 803 // the parent container managing them (e.g. Tasks). 804 switch (token.windowType) { 805 case TYPE_WALLPAPER: 806 mBelowAppWindowsContainers.addChild(token); 807 break; 808 case TYPE_INPUT_METHOD: 809 case TYPE_INPUT_METHOD_DIALOG: 810 mImeWindowsContainers.addChild(token); 811 break; 812 default: 813 mAboveAppWindowsContainers.addChild(token); 814 break; 815 } 816 } 817 } 818 819 WindowToken removeWindowToken(IBinder binder) { 820 final WindowToken token = mTokenMap.remove(binder); 821 if (token != null && token.asAppWindowToken() == null) { 822 token.setExiting(); 823 } 824 return token; 825 } 826 827 /** Changes the display the input window token is housed on to this one. */ 828 void reParentWindowToken(WindowToken token) { 829 final DisplayContent prevDc = token.getDisplayContent(); 830 if (prevDc == this) { 831 return; 832 } 833 if (prevDc != null && prevDc.mTokenMap.remove(token.token) != null 834 && token.asAppWindowToken() == null) { 835 // Removed the token from the map, but made sure it's not an app token before removing 836 // from parent. 837 token.getParent().removeChild(token); 838 } 839 840 addWindowToken(token.token, token); 841 } 842 843 void removeAppToken(IBinder binder) { 844 final WindowToken token = removeWindowToken(binder); 845 if (token == null) { 846 Slog.w(TAG_WM, "removeAppToken: Attempted to remove non-existing token: " + binder); 847 return; 848 } 849 850 final AppWindowToken appToken = token.asAppWindowToken(); 851 852 if (appToken == null) { 853 Slog.w(TAG_WM, "Attempted to remove non-App token: " + binder + " token=" + token); 854 return; 855 } 856 857 appToken.onRemovedFromDisplay(); 858 } 859 860 Display getDisplay() { 861 return mDisplay; 862 } 863 864 DisplayInfo getDisplayInfo() { 865 return mDisplayInfo; 866 } 867 868 DisplayMetrics getDisplayMetrics() { 869 return mDisplayMetrics; 870 } 871 872 int getRotation() { 873 return mRotation; 874 } 875 876 void setRotation(int newRotation) { 877 mRotation = newRotation; 878 } 879 880 int getLastOrientation() { 881 return mLastOrientation; 882 } 883 884 void setLastOrientation(int orientation) { 885 mLastOrientation = orientation; 886 } 887 888 boolean getAltOrientation() { 889 return mAltOrientation; 890 } 891 892 void setAltOrientation(boolean altOrientation) { 893 mAltOrientation = altOrientation; 894 } 895 896 int getLastWindowForcedOrientation() { 897 return mLastWindowForcedOrientation; 898 } 899 900 /** 901 * Update rotation of the display. 902 * 903 * Returns true if the rotation has been changed. In this case YOU MUST CALL 904 * {@link WindowManagerService#sendNewConfiguration(int)} TO UNFREEZE THE SCREEN. 905 */ 906 boolean updateRotationUnchecked(boolean inTransaction) { 907 if (mService.mDeferredRotationPauseCount > 0) { 908 // Rotation updates have been paused temporarily. Defer the update until 909 // updates have been resumed. 910 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, rotation is paused."); 911 return false; 912 } 913 914 ScreenRotationAnimation screenRotationAnimation = 915 mService.mAnimator.getScreenRotationAnimationLocked(mDisplayId); 916 if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) { 917 // Rotation updates cannot be performed while the previous rotation change 918 // animation is still in progress. Skip this update. We will try updating 919 // again after the animation is finished and the display is unfrozen. 920 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, animation in progress."); 921 return false; 922 } 923 if (mService.mDisplayFrozen) { 924 // Even if the screen rotation animation has finished (e.g. isAnimating 925 // returns false), there is still some time where we haven't yet unfrozen 926 // the display. We also need to abort rotation here. 927 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, 928 "Deferring rotation, still finishing previous rotation"); 929 return false; 930 } 931 932 if (!mService.mDisplayEnabled) { 933 // No point choosing a rotation if the display is not enabled. 934 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, display is not enabled."); 935 return false; 936 } 937 938 final int oldRotation = mRotation; 939 final int lastOrientation = mLastOrientation; 940 final boolean oldAltOrientation = mAltOrientation; 941 int rotation = mService.mPolicy.rotationForOrientationLw(lastOrientation, oldRotation); 942 final boolean rotateSeamlessly = mService.mPolicy.shouldRotateSeamlessly(oldRotation, 943 rotation); 944 945 if (rotateSeamlessly) { 946 final WindowState seamlessRotated = getWindow((w) -> w.mSeamlesslyRotated); 947 if (seamlessRotated != null) { 948 // We can't rotate (seamlessly or not) while waiting for the last seamless rotation 949 // to complete (that is, waiting for windows to redraw). It's tempting to check 950 // w.mSeamlessRotationCount but that could be incorrect in the case of 951 // window-removal. 952 return false; 953 } 954 } 955 956 // TODO: Implement forced rotation changes. 957 // Set mAltOrientation to indicate that the application is receiving 958 // an orientation that has different metrics than it expected. 959 // eg. Portrait instead of Landscape. 960 961 final boolean altOrientation = !mService.mPolicy.rotationHasCompatibleMetricsLw( 962 lastOrientation, rotation); 963 964 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Selected orientation " + lastOrientation 965 + ", got rotation " + rotation + " which has " 966 + (altOrientation ? "incompatible" : "compatible") + " metrics"); 967 968 if (oldRotation == rotation && oldAltOrientation == altOrientation) { 969 // No change. 970 return false; 971 } 972 973 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Rotation changed to " + rotation 974 + (altOrientation ? " (alt)" : "") + " from " + oldRotation 975 + (oldAltOrientation ? " (alt)" : "") + ", lastOrientation=" + lastOrientation); 976 977 if (DisplayContent.deltaRotation(rotation, oldRotation) != 2) { 978 mService.mWaitingForConfig = true; 979 } 980 981 mRotation = rotation; 982 mAltOrientation = altOrientation; 983 if (isDefaultDisplay) { 984 mService.mPolicy.setRotationLw(rotation); 985 } 986 987 mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE; 988 mService.mH.removeMessages(WindowManagerService.H.WINDOW_FREEZE_TIMEOUT); 989 mService.mH.sendEmptyMessageDelayed(WindowManagerService.H.WINDOW_FREEZE_TIMEOUT, 990 WINDOW_FREEZE_TIMEOUT_DURATION); 991 992 setLayoutNeeded(); 993 final int[] anim = new int[2]; 994 if (isDimming()) { 995 anim[0] = anim[1] = 0; 996 } else { 997 mService.mPolicy.selectRotationAnimationLw(anim); 998 } 999 1000 if (!rotateSeamlessly) { 1001 mService.startFreezingDisplayLocked(inTransaction, anim[0], anim[1], this); 1002 // startFreezingDisplayLocked can reset the ScreenRotationAnimation. 1003 screenRotationAnimation = mService.mAnimator.getScreenRotationAnimationLocked( 1004 mDisplayId); 1005 } else { 1006 // The screen rotation animation uses a screenshot to freeze the screen 1007 // while windows resize underneath. 1008 // When we are rotating seamlessly, we allow the elements to transition 1009 // to their rotated state independently and without a freeze required. 1010 screenRotationAnimation = null; 1011 1012 // We have to reset this in case a window was removed before it 1013 // finished seamless rotation. 1014 mService.mSeamlessRotationCount = 0; 1015 } 1016 1017 // We need to update our screen size information to match the new rotation. If the rotation 1018 // has actually changed then this method will return true and, according to the comment at 1019 // the top of the method, the caller is obligated to call computeNewConfigurationLocked(). 1020 // By updating the Display info here it will be available to 1021 // #computeScreenConfiguration() later. 1022 updateDisplayAndOrientation(getConfiguration().uiMode); 1023 1024 if (!inTransaction) { 1025 if (SHOW_TRANSACTIONS) { 1026 Slog.i(TAG_WM, ">>> OPEN TRANSACTION setRotationUnchecked"); 1027 } 1028 mService.openSurfaceTransaction(); 1029 } 1030 try { 1031 // NOTE: We disable the rotation in the emulator because 1032 // it doesn't support hardware OpenGL emulation yet. 1033 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null 1034 && screenRotationAnimation.hasScreenshot()) { 1035 if (screenRotationAnimation.setRotationInTransaction( 1036 rotation, mService.mFxSession, 1037 MAX_ANIMATION_DURATION, mService.getTransitionAnimationScaleLocked(), 1038 mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight)) { 1039 mService.scheduleAnimationLocked(); 1040 } 1041 } 1042 1043 if (rotateSeamlessly) { 1044 forAllWindows(w -> { 1045 w.mWinAnimator.seamlesslyRotateWindow(oldRotation, rotation); 1046 }, true /* traverseTopToBottom */); 1047 } 1048 1049 mService.mDisplayManagerInternal.performTraversalInTransactionFromWindowManager(); 1050 } finally { 1051 if (!inTransaction) { 1052 mService.closeSurfaceTransaction(); 1053 if (SHOW_LIGHT_TRANSACTIONS) { 1054 Slog.i(TAG_WM, "<<< CLOSE TRANSACTION setRotationUnchecked"); 1055 } 1056 } 1057 } 1058 1059 forAllWindows(w -> { 1060 // Discard surface after orientation change, these can't be reused. 1061 if (w.mAppToken != null) { 1062 w.mAppToken.destroySavedSurfaces(); 1063 } 1064 if (w.mHasSurface && !rotateSeamlessly) { 1065 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Set mOrientationChanging of " + w); 1066 w.mOrientationChanging = true; 1067 mService.mRoot.mOrientationChangeComplete = false; 1068 w.mLastFreezeDuration = 0; 1069 } 1070 w.mReportOrientationChanged = true; 1071 }, true /* traverseTopToBottom */); 1072 1073 if (rotateSeamlessly) { 1074 mService.mH.removeMessages(WindowManagerService.H.SEAMLESS_ROTATION_TIMEOUT); 1075 mService.mH.sendEmptyMessageDelayed(WindowManagerService.H.SEAMLESS_ROTATION_TIMEOUT, 1076 SEAMLESS_ROTATION_TIMEOUT_DURATION); 1077 } 1078 1079 for (int i = mService.mRotationWatchers.size() - 1; i >= 0; i--) { 1080 final WindowManagerService.RotationWatcher rotationWatcher 1081 = mService.mRotationWatchers.get(i); 1082 if (rotationWatcher.mDisplayId == mDisplayId) { 1083 try { 1084 rotationWatcher.mWatcher.onRotationChanged(rotation); 1085 } catch (RemoteException e) { 1086 // Ignore 1087 } 1088 } 1089 } 1090 1091 // TODO (multi-display): Magnification is supported only for the default display. 1092 // Announce rotation only if we will not animate as we already have the 1093 // windows in final state. Otherwise, we make this call at the rotation end. 1094 if (screenRotationAnimation == null && mService.mAccessibilityController != null 1095 && isDefaultDisplay) { 1096 mService.mAccessibilityController.onRotationChangedLocked(this); 1097 } 1098 1099 return true; 1100 } 1101 1102 /** 1103 * Update {@link #mDisplayInfo} and other internal variables when display is rotated or config 1104 * changed. 1105 * Do not call if {@link WindowManagerService#mDisplayReady} == false. 1106 */ 1107 private DisplayInfo updateDisplayAndOrientation(int uiMode) { 1108 // Use the effective "visual" dimensions based on current rotation 1109 final boolean rotated = (mRotation == ROTATION_90 || mRotation == ROTATION_270); 1110 final int realdw = rotated ? mBaseDisplayHeight : mBaseDisplayWidth; 1111 final int realdh = rotated ? mBaseDisplayWidth : mBaseDisplayHeight; 1112 int dw = realdw; 1113 int dh = realdh; 1114 1115 if (mAltOrientation) { 1116 if (realdw > realdh) { 1117 // Turn landscape into portrait. 1118 int maxw = (int)(realdh/1.3f); 1119 if (maxw < realdw) { 1120 dw = maxw; 1121 } 1122 } else { 1123 // Turn portrait into landscape. 1124 int maxh = (int)(realdw/1.3f); 1125 if (maxh < realdh) { 1126 dh = maxh; 1127 } 1128 } 1129 } 1130 1131 // Update application display metrics. 1132 final int appWidth = mService.mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation, uiMode, 1133 mDisplayId); 1134 final int appHeight = mService.mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation, uiMode, 1135 mDisplayId); 1136 mDisplayInfo.rotation = mRotation; 1137 mDisplayInfo.logicalWidth = dw; 1138 mDisplayInfo.logicalHeight = dh; 1139 mDisplayInfo.logicalDensityDpi = mBaseDisplayDensity; 1140 mDisplayInfo.appWidth = appWidth; 1141 mDisplayInfo.appHeight = appHeight; 1142 if (isDefaultDisplay) { 1143 mDisplayInfo.getLogicalMetrics(mRealDisplayMetrics, 1144 CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null); 1145 } 1146 mDisplayInfo.getAppMetrics(mDisplayMetrics); 1147 if (mDisplayScalingDisabled) { 1148 mDisplayInfo.flags |= Display.FLAG_SCALING_DISABLED; 1149 } else { 1150 mDisplayInfo.flags &= ~Display.FLAG_SCALING_DISABLED; 1151 } 1152 1153 mService.mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(mDisplayId, 1154 mDisplayInfo); 1155 1156 mBaseDisplayRect.set(0, 0, dw, dh); 1157 1158 if (isDefaultDisplay) { 1159 mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(mDisplayMetrics, 1160 mCompatDisplayMetrics); 1161 } 1162 return mDisplayInfo; 1163 } 1164 1165 /** 1166 * Compute display configuration based on display properties and policy settings. 1167 * Do not call if mDisplayReady == false. 1168 */ 1169 void computeScreenConfiguration(Configuration config) { 1170 final DisplayInfo displayInfo = updateDisplayAndOrientation(config.uiMode); 1171 1172 final int dw = displayInfo.logicalWidth; 1173 final int dh = displayInfo.logicalHeight; 1174 config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT : 1175 Configuration.ORIENTATION_LANDSCAPE; 1176 config.screenWidthDp = 1177 (int)(mService.mPolicy.getConfigDisplayWidth(dw, dh, displayInfo.rotation, 1178 config.uiMode, mDisplayId) / mDisplayMetrics.density); 1179 config.screenHeightDp = 1180 (int)(mService.mPolicy.getConfigDisplayHeight(dw, dh, displayInfo.rotation, 1181 config.uiMode, mDisplayId) / mDisplayMetrics.density); 1182 1183 mService.mPolicy.getNonDecorInsetsLw(displayInfo.rotation, dw, dh, mTmpRect); 1184 final int leftInset = mTmpRect.left; 1185 final int topInset = mTmpRect.top; 1186 // appBounds at the root level should mirror the app screen size. 1187 config.setAppBounds(leftInset /*left*/, topInset /*top*/, leftInset + displayInfo.appWidth /*right*/, 1188 topInset + displayInfo.appHeight /*bottom*/); 1189 final boolean rotated = (displayInfo.rotation == Surface.ROTATION_90 1190 || displayInfo.rotation == Surface.ROTATION_270); 1191 1192 computeSizeRangesAndScreenLayout(displayInfo, mDisplayId, rotated, config.uiMode, dw, dh, 1193 mDisplayMetrics.density, config); 1194 1195 config.screenLayout = (config.screenLayout & ~Configuration.SCREENLAYOUT_ROUND_MASK) 1196 | ((displayInfo.flags & Display.FLAG_ROUND) != 0 1197 ? Configuration.SCREENLAYOUT_ROUND_YES 1198 : Configuration.SCREENLAYOUT_ROUND_NO); 1199 1200 config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale); 1201 config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale); 1202 config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, config.uiMode, dw, 1203 dh, mDisplayId); 1204 config.densityDpi = displayInfo.logicalDensityDpi; 1205 1206 config.colorMode = 1207 (displayInfo.isHdr() 1208 ? Configuration.COLOR_MODE_HDR_YES 1209 : Configuration.COLOR_MODE_HDR_NO) 1210 | (displayInfo.isWideColorGamut() 1211 ? Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_YES 1212 : Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_NO); 1213 1214 // Update the configuration based on available input devices, lid switch, 1215 // and platform configuration. 1216 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 1217 config.keyboard = Configuration.KEYBOARD_NOKEYS; 1218 config.navigation = Configuration.NAVIGATION_NONAV; 1219 1220 int keyboardPresence = 0; 1221 int navigationPresence = 0; 1222 final InputDevice[] devices = mService.mInputManager.getInputDevices(); 1223 final int len = devices != null ? devices.length : 0; 1224 for (int i = 0; i < len; i++) { 1225 InputDevice device = devices[i]; 1226 if (!device.isVirtual()) { 1227 final int sources = device.getSources(); 1228 final int presenceFlag = device.isExternal() ? 1229 WindowManagerPolicy.PRESENCE_EXTERNAL : 1230 WindowManagerPolicy.PRESENCE_INTERNAL; 1231 1232 // TODO(multi-display): Configure on per-display basis. 1233 if (mService.mIsTouchDevice) { 1234 if ((sources & InputDevice.SOURCE_TOUCHSCREEN) == 1235 InputDevice.SOURCE_TOUCHSCREEN) { 1236 config.touchscreen = Configuration.TOUCHSCREEN_FINGER; 1237 } 1238 } else { 1239 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 1240 } 1241 1242 if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) { 1243 config.navigation = Configuration.NAVIGATION_TRACKBALL; 1244 navigationPresence |= presenceFlag; 1245 } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD 1246 && config.navigation == Configuration.NAVIGATION_NONAV) { 1247 config.navigation = Configuration.NAVIGATION_DPAD; 1248 navigationPresence |= presenceFlag; 1249 } 1250 1251 if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) { 1252 config.keyboard = Configuration.KEYBOARD_QWERTY; 1253 keyboardPresence |= presenceFlag; 1254 } 1255 } 1256 } 1257 1258 if (config.navigation == Configuration.NAVIGATION_NONAV && mService.mHasPermanentDpad) { 1259 config.navigation = Configuration.NAVIGATION_DPAD; 1260 navigationPresence |= WindowManagerPolicy.PRESENCE_INTERNAL; 1261 } 1262 1263 // Determine whether a hard keyboard is available and enabled. 1264 // TODO(multi-display): Should the hardware keyboard be tied to a display or to a device? 1265 boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS; 1266 if (hardKeyboardAvailable != mService.mHardKeyboardAvailable) { 1267 mService.mHardKeyboardAvailable = hardKeyboardAvailable; 1268 mService.mH.removeMessages(WindowManagerService.H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 1269 mService.mH.sendEmptyMessage(WindowManagerService.H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 1270 } 1271 1272 // Let the policy update hidden states. 1273 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO; 1274 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO; 1275 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO; 1276 mService.mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence); 1277 } 1278 1279 private int computeCompatSmallestWidth(boolean rotated, int uiMode, int dw, int dh, 1280 int displayId) { 1281 mTmpDisplayMetrics.setTo(mDisplayMetrics); 1282 final DisplayMetrics tmpDm = mTmpDisplayMetrics; 1283 final int unrotDw, unrotDh; 1284 if (rotated) { 1285 unrotDw = dh; 1286 unrotDh = dw; 1287 } else { 1288 unrotDw = dw; 1289 unrotDh = dh; 1290 } 1291 int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, uiMode, tmpDm, unrotDw, unrotDh, 1292 displayId); 1293 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, uiMode, tmpDm, unrotDh, unrotDw, 1294 displayId); 1295 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, uiMode, tmpDm, unrotDw, unrotDh, 1296 displayId); 1297 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, uiMode, tmpDm, unrotDh, unrotDw, 1298 displayId); 1299 return sw; 1300 } 1301 1302 private int reduceCompatConfigWidthSize(int curSize, int rotation, int uiMode, 1303 DisplayMetrics dm, int dw, int dh, int displayId) { 1304 dm.noncompatWidthPixels = mService.mPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode, 1305 displayId); 1306 dm.noncompatHeightPixels = mService.mPolicy.getNonDecorDisplayHeight(dw, dh, rotation, 1307 uiMode, displayId); 1308 float scale = CompatibilityInfo.computeCompatibleScaling(dm, null); 1309 int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f); 1310 if (curSize == 0 || size < curSize) { 1311 curSize = size; 1312 } 1313 return curSize; 1314 } 1315 1316 private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, int displayId, 1317 boolean rotated, int uiMode, int dw, int dh, float density, Configuration outConfig) { 1318 1319 // We need to determine the smallest width that will occur under normal 1320 // operation. To this, start with the base screen size and compute the 1321 // width under the different possible rotations. We need to un-rotate 1322 // the current screen dimensions before doing this. 1323 int unrotDw, unrotDh; 1324 if (rotated) { 1325 unrotDw = dh; 1326 unrotDh = dw; 1327 } else { 1328 unrotDw = dw; 1329 unrotDh = dh; 1330 } 1331 displayInfo.smallestNominalAppWidth = 1<<30; 1332 displayInfo.smallestNominalAppHeight = 1<<30; 1333 displayInfo.largestNominalAppWidth = 0; 1334 displayInfo.largestNominalAppHeight = 0; 1335 adjustDisplaySizeRanges(displayInfo, displayId, Surface.ROTATION_0, uiMode, unrotDw, 1336 unrotDh); 1337 adjustDisplaySizeRanges(displayInfo, displayId, Surface.ROTATION_90, uiMode, unrotDh, 1338 unrotDw); 1339 adjustDisplaySizeRanges(displayInfo, displayId, Surface.ROTATION_180, uiMode, unrotDw, 1340 unrotDh); 1341 adjustDisplaySizeRanges(displayInfo, displayId, Surface.ROTATION_270, uiMode, unrotDh, 1342 unrotDw); 1343 int sl = Configuration.resetScreenLayout(outConfig.screenLayout); 1344 sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh, uiMode, 1345 displayId); 1346 sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw, uiMode, 1347 displayId); 1348 sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh, uiMode, 1349 displayId); 1350 sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw, uiMode, 1351 displayId); 1352 outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density); 1353 outConfig.screenLayout = sl; 1354 } 1355 1356 private int reduceConfigLayout(int curLayout, int rotation, float density, int dw, int dh, 1357 int uiMode, int displayId) { 1358 // Get the app screen size at this rotation. 1359 int w = mService.mPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode, displayId); 1360 int h = mService.mPolicy.getNonDecorDisplayHeight(dw, dh, rotation, uiMode, displayId); 1361 1362 // Compute the screen layout size class for this rotation. 1363 int longSize = w; 1364 int shortSize = h; 1365 if (longSize < shortSize) { 1366 int tmp = longSize; 1367 longSize = shortSize; 1368 shortSize = tmp; 1369 } 1370 longSize = (int)(longSize/density); 1371 shortSize = (int)(shortSize/density); 1372 return Configuration.reduceScreenLayout(curLayout, longSize, shortSize); 1373 } 1374 1375 private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int displayId, int rotation, 1376 int uiMode, int dw, int dh) { 1377 final int width = mService.mPolicy.getConfigDisplayWidth(dw, dh, rotation, uiMode, 1378 displayId); 1379 if (width < displayInfo.smallestNominalAppWidth) { 1380 displayInfo.smallestNominalAppWidth = width; 1381 } 1382 if (width > displayInfo.largestNominalAppWidth) { 1383 displayInfo.largestNominalAppWidth = width; 1384 } 1385 final int height = mService.mPolicy.getConfigDisplayHeight(dw, dh, rotation, uiMode, 1386 displayId); 1387 if (height < displayInfo.smallestNominalAppHeight) { 1388 displayInfo.smallestNominalAppHeight = height; 1389 } 1390 if (height > displayInfo.largestNominalAppHeight) { 1391 displayInfo.largestNominalAppHeight = height; 1392 } 1393 } 1394 1395 DockedStackDividerController getDockedDividerController() { 1396 return mDividerControllerLocked; 1397 } 1398 1399 PinnedStackController getPinnedStackController() { 1400 return mPinnedStackControllerLocked; 1401 } 1402 1403 /** 1404 * Returns true if the specified UID has access to this display. 1405 */ 1406 boolean hasAccess(int uid) { 1407 return mDisplay.hasAccess(uid); 1408 } 1409 1410 boolean isPrivate() { 1411 return (mDisplay.getFlags() & FLAG_PRIVATE) != 0; 1412 } 1413 1414 TaskStack getHomeStack() { 1415 if (mHomeStack == null && mDisplayId == DEFAULT_DISPLAY) { 1416 Slog.e(TAG_WM, "getHomeStack: Returning null from this=" + this); 1417 } 1418 return mHomeStack; 1419 } 1420 1421 TaskStack getStackById(int stackId) { 1422 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 1423 final TaskStack stack = mTaskStackContainers.get(i); 1424 if (stack.mStackId == stackId) { 1425 return stack; 1426 } 1427 } 1428 return null; 1429 } 1430 1431 @VisibleForTesting 1432 int getStackCount() { 1433 return mTaskStackContainers.size(); 1434 } 1435 1436 @VisibleForTesting 1437 int getStaskPosById(int stackId) { 1438 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 1439 final TaskStack stack = mTaskStackContainers.get(i); 1440 if (stack.mStackId == stackId) { 1441 return i; 1442 } 1443 } 1444 return -1; 1445 } 1446 1447 @Override 1448 void onConfigurationChanged(Configuration newParentConfig) { 1449 super.onConfigurationChanged(newParentConfig); 1450 1451 // The display size information is heavily dependent on the resources in the current 1452 // configuration, so we need to reconfigure it every time the configuration changes. 1453 // See {@link PhoneWindowManager#setInitialDisplaySize}...sigh... 1454 mService.reconfigureDisplayLocked(this); 1455 1456 getDockedDividerController().onConfigurationChanged(); 1457 getPinnedStackController().onConfigurationChanged(); 1458 } 1459 1460 /** 1461 * Callback used to trigger bounds update after configuration change and get ids of stacks whose 1462 * bounds were updated. 1463 */ 1464 void updateStackBoundsAfterConfigChange(@NonNull List<Integer> changedStackList) { 1465 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 1466 final TaskStack stack = mTaskStackContainers.get(i); 1467 if (stack.updateBoundsAfterConfigChange()) { 1468 changedStackList.add(stack.mStackId); 1469 } 1470 } 1471 1472 // If there was no pinned stack, we still need to notify the controller of the display info 1473 // update as a result of the config change. We do this here to consolidate the flow between 1474 // changes when there is and is not a stack. 1475 if (getStackById(PINNED_STACK_ID) == null) { 1476 mPinnedStackControllerLocked.onDisplayInfoChanged(); 1477 } 1478 } 1479 1480 @Override 1481 boolean fillsParent() { 1482 return true; 1483 } 1484 1485 @Override 1486 boolean isVisible() { 1487 return true; 1488 } 1489 1490 @Override 1491 void onAppTransitionDone() { 1492 super.onAppTransitionDone(); 1493 mService.mWindowsChanged = true; 1494 } 1495 1496 @Override 1497 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) { 1498 // Special handling so we can process IME windows with #forAllImeWindows above their IME 1499 // target, or here in order if there isn't an IME target. 1500 if (traverseTopToBottom) { 1501 for (int i = mChildren.size() - 1; i >= 0; --i) { 1502 final DisplayChildWindowContainer child = mChildren.get(i); 1503 if (child == mImeWindowsContainers && mService.mInputMethodTarget != null) { 1504 // In this case the Ime windows will be processed above their target so we skip 1505 // here. 1506 continue; 1507 } 1508 if (child.forAllWindows(callback, traverseTopToBottom)) { 1509 return true; 1510 } 1511 } 1512 } else { 1513 final int count = mChildren.size(); 1514 for (int i = 0; i < count; i++) { 1515 final DisplayChildWindowContainer child = mChildren.get(i); 1516 if (child == mImeWindowsContainers && mService.mInputMethodTarget != null) { 1517 // In this case the Ime windows will be processed above their target so we skip 1518 // here. 1519 continue; 1520 } 1521 if (child.forAllWindows(callback, traverseTopToBottom)) { 1522 return true; 1523 } 1524 } 1525 } 1526 return false; 1527 } 1528 1529 boolean forAllImeWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) { 1530 return mImeWindowsContainers.forAllWindows(callback, traverseTopToBottom); 1531 } 1532 1533 @Override 1534 int getOrientation() { 1535 final WindowManagerPolicy policy = mService.mPolicy; 1536 1537 if (mService.mDisplayFrozen) { 1538 if (mLastWindowForcedOrientation != SCREEN_ORIENTATION_UNSPECIFIED) { 1539 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, 1540 "Display is frozen, return " + mLastWindowForcedOrientation); 1541 // If the display is frozen, some activities may be in the middle of restarting, and 1542 // thus have removed their old window. If the window has the flag to hide the lock 1543 // screen, then the lock screen can re-appear and inflict its own orientation on us. 1544 // Keep the orientation stable until this all settles down. 1545 return mLastWindowForcedOrientation; 1546 } else if (policy.isKeyguardLocked()) { 1547 // Use the last orientation the while the display is frozen with the keyguard 1548 // locked. This could be the keyguard forced orientation or from a SHOW_WHEN_LOCKED 1549 // window. We don't want to check the show when locked window directly though as 1550 // things aren't stable while the display is frozen, for example the window could be 1551 // momentarily unavailable due to activity relaunch. 1552 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display is frozen while keyguard locked, " 1553 + "return " + mLastOrientation); 1554 return mLastOrientation; 1555 } 1556 } else { 1557 final int orientation = mAboveAppWindowsContainers.getOrientation(); 1558 if (orientation != SCREEN_ORIENTATION_UNSET) { 1559 return orientation; 1560 } 1561 } 1562 1563 // Top system windows are not requesting an orientation. Start searching from apps. 1564 return mTaskStackContainers.getOrientation(); 1565 } 1566 1567 void updateDisplayInfo() { 1568 // Check if display metrics changed and update base values if needed. 1569 updateBaseDisplayMetricsIfNeeded(); 1570 1571 mDisplay.getDisplayInfo(mDisplayInfo); 1572 mDisplay.getMetrics(mDisplayMetrics); 1573 1574 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 1575 mTaskStackContainers.get(i).updateDisplayInfo(null); 1576 } 1577 } 1578 1579 void initializeDisplayBaseInfo() { 1580 final DisplayManagerInternal displayManagerInternal = mService.mDisplayManagerInternal; 1581 if (displayManagerInternal != null) { 1582 // Bootstrap the default logical display from the display manager. 1583 final DisplayInfo newDisplayInfo = displayManagerInternal.getDisplayInfo(mDisplayId); 1584 if (newDisplayInfo != null) { 1585 mDisplayInfo.copyFrom(newDisplayInfo); 1586 } 1587 } 1588 1589 updateBaseDisplayMetrics(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight, 1590 mDisplayInfo.logicalDensityDpi); 1591 mInitialDisplayWidth = mDisplayInfo.logicalWidth; 1592 mInitialDisplayHeight = mDisplayInfo.logicalHeight; 1593 mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi; 1594 } 1595 1596 void getLogicalDisplayRect(Rect out) { 1597 // Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked. 1598 final int orientation = mDisplayInfo.rotation; 1599 boolean rotated = (orientation == ROTATION_90 || orientation == ROTATION_270); 1600 final int physWidth = rotated ? mBaseDisplayHeight : mBaseDisplayWidth; 1601 final int physHeight = rotated ? mBaseDisplayWidth : mBaseDisplayHeight; 1602 int width = mDisplayInfo.logicalWidth; 1603 int left = (physWidth - width) / 2; 1604 int height = mDisplayInfo.logicalHeight; 1605 int top = (physHeight - height) / 2; 1606 out.set(left, top, left + width, top + height); 1607 } 1608 1609 private void getLogicalDisplayRect(Rect out, int orientation) { 1610 getLogicalDisplayRect(out); 1611 1612 // Rotate the Rect if needed. 1613 final int currentRotation = mDisplayInfo.rotation; 1614 final int rotationDelta = deltaRotation(currentRotation, orientation); 1615 if (rotationDelta == ROTATION_90 || rotationDelta == ROTATION_270) { 1616 createRotationMatrix(rotationDelta, mBaseDisplayWidth, mBaseDisplayHeight, mTmpMatrix); 1617 mTmpRectF.set(out); 1618 mTmpMatrix.mapRect(mTmpRectF); 1619 mTmpRectF.round(out); 1620 } 1621 } 1622 1623 /** 1624 * If display metrics changed, overrides are not set and it's not just a rotation - update base 1625 * values. 1626 */ 1627 private void updateBaseDisplayMetricsIfNeeded() { 1628 // Get real display metrics without overrides from WM. 1629 mService.mDisplayManagerInternal.getNonOverrideDisplayInfo(mDisplayId, mDisplayInfo); 1630 final int orientation = mDisplayInfo.rotation; 1631 final boolean rotated = (orientation == ROTATION_90 || orientation == ROTATION_270); 1632 final int newWidth = rotated ? mDisplayInfo.logicalHeight : mDisplayInfo.logicalWidth; 1633 final int newHeight = rotated ? mDisplayInfo.logicalWidth : mDisplayInfo.logicalHeight; 1634 final int newDensity = mDisplayInfo.logicalDensityDpi; 1635 1636 final boolean displayMetricsChanged = mInitialDisplayWidth != newWidth 1637 || mInitialDisplayHeight != newHeight 1638 || mInitialDisplayDensity != mDisplayInfo.logicalDensityDpi; 1639 1640 if (displayMetricsChanged) { 1641 // Check if display size or density is forced. 1642 final boolean isDisplaySizeForced = mBaseDisplayWidth != mInitialDisplayWidth 1643 || mBaseDisplayHeight != mInitialDisplayHeight; 1644 final boolean isDisplayDensityForced = mBaseDisplayDensity != mInitialDisplayDensity; 1645 1646 // If there is an override set for base values - use it, otherwise use new values. 1647 updateBaseDisplayMetrics(isDisplaySizeForced ? mBaseDisplayWidth : newWidth, 1648 isDisplaySizeForced ? mBaseDisplayHeight : newHeight, 1649 isDisplayDensityForced ? mBaseDisplayDensity : newDensity); 1650 1651 // Real display metrics changed, so we should also update initial values. 1652 mInitialDisplayWidth = newWidth; 1653 mInitialDisplayHeight = newHeight; 1654 mInitialDisplayDensity = newDensity; 1655 mService.reconfigureDisplayLocked(this); 1656 } 1657 } 1658 1659 /** Sets the maximum width the screen resolution can be */ 1660 void setMaxUiWidth(int width) { 1661 if (DEBUG_DISPLAY) { 1662 Slog.v(TAG_WM, "Setting max ui width:" + width + " on display:" + getDisplayId()); 1663 } 1664 1665 mMaxUiWidth = width; 1666 1667 // Update existing metrics. 1668 updateBaseDisplayMetrics(mBaseDisplayWidth, mBaseDisplayHeight, mBaseDisplayDensity); 1669 } 1670 1671 /** Update base (override) display metrics. */ 1672 void updateBaseDisplayMetrics(int baseWidth, int baseHeight, int baseDensity) { 1673 mBaseDisplayWidth = baseWidth; 1674 mBaseDisplayHeight = baseHeight; 1675 mBaseDisplayDensity = baseDensity; 1676 1677 if (mMaxUiWidth > 0 && mBaseDisplayWidth > mMaxUiWidth) { 1678 mBaseDisplayHeight = (mMaxUiWidth * mBaseDisplayHeight) / mBaseDisplayWidth; 1679 mBaseDisplayDensity = (mMaxUiWidth * mBaseDisplayDensity) / mBaseDisplayWidth; 1680 mBaseDisplayWidth = mMaxUiWidth; 1681 1682 if (DEBUG_DISPLAY) { 1683 Slog.v(TAG_WM, "Applying config restraints:" + mBaseDisplayWidth + "x" 1684 + mBaseDisplayHeight + " at density:" + mBaseDisplayDensity 1685 + " on display:" + getDisplayId()); 1686 } 1687 } 1688 1689 mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight); 1690 } 1691 1692 void getContentRect(Rect out) { 1693 out.set(mContentRect); 1694 } 1695 1696 TaskStack addStackToDisplay(int stackId, boolean onTop) { 1697 if (DEBUG_STACK) Slog.d(TAG_WM, "Create new stackId=" + stackId + " on displayId=" 1698 + mDisplayId); 1699 1700 TaskStack stack = getStackById(stackId); 1701 if (stack != null) { 1702 // It's already attached to the display...clear mDeferRemoval and move stack to 1703 // appropriate z-order on display as needed. 1704 stack.mDeferRemoval = false; 1705 // We're not moving the display to front when we're adding stacks, only when 1706 // requested to change the position of stack explicitly. 1707 mTaskStackContainers.positionChildAt(onTop ? POSITION_TOP : POSITION_BOTTOM, stack, 1708 false /* includingParents */); 1709 } else { 1710 stack = new TaskStack(mService, stackId); 1711 mTaskStackContainers.addStackToDisplay(stack, onTop); 1712 } 1713 1714 if (stackId == DOCKED_STACK_ID) { 1715 mDividerControllerLocked.notifyDockedStackExistsChanged(true); 1716 } 1717 return stack; 1718 } 1719 1720 void moveStackToDisplay(TaskStack stack, boolean onTop) { 1721 final DisplayContent prevDc = stack.getDisplayContent(); 1722 if (prevDc == null) { 1723 throw new IllegalStateException("Trying to move stackId=" + stack.mStackId 1724 + " which is not currently attached to any display"); 1725 } 1726 if (prevDc.getDisplayId() == mDisplayId) { 1727 throw new IllegalArgumentException("Trying to move stackId=" + stack.mStackId 1728 + " to its current displayId=" + mDisplayId); 1729 } 1730 1731 prevDc.mTaskStackContainers.removeStackFromDisplay(stack); 1732 mTaskStackContainers.addStackToDisplay(stack, onTop); 1733 } 1734 1735 @Override 1736 protected void addChild(DisplayChildWindowContainer child, 1737 Comparator<DisplayChildWindowContainer> comparator) { 1738 throw new UnsupportedOperationException("See DisplayChildWindowContainer"); 1739 } 1740 1741 @Override 1742 protected void addChild(DisplayChildWindowContainer child, int index) { 1743 throw new UnsupportedOperationException("See DisplayChildWindowContainer"); 1744 } 1745 1746 @Override 1747 protected void removeChild(DisplayChildWindowContainer child) { 1748 // Only allow removal of direct children from this display if the display is in the process 1749 // of been removed. 1750 if (mRemovingDisplay) { 1751 super.removeChild(child); 1752 return; 1753 } 1754 throw new UnsupportedOperationException("See DisplayChildWindowContainer"); 1755 } 1756 1757 @Override 1758 void positionChildAt(int position, DisplayChildWindowContainer child, boolean includingParents) { 1759 // Children of the display are statically ordered, so the real intention here is to perform 1760 // the operation on the display and not the static direct children. 1761 getParent().positionChildAt(position, this, includingParents); 1762 } 1763 1764 int taskIdFromPoint(int x, int y) { 1765 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) { 1766 final TaskStack stack = mTaskStackContainers.get(stackNdx); 1767 final int taskId = stack.taskIdFromPoint(x, y); 1768 if (taskId != -1) { 1769 return taskId; 1770 } 1771 } 1772 return -1; 1773 } 1774 1775 /** 1776 * Find the task whose outside touch area (for resizing) (x, y) falls within. 1777 * Returns null if the touch doesn't fall into a resizing area. 1778 */ 1779 Task findTaskForResizePoint(int x, int y) { 1780 final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics); 1781 mTmpTaskForResizePointSearchResult.reset(); 1782 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) { 1783 final TaskStack stack = mTaskStackContainers.get(stackNdx); 1784 if (!StackId.isTaskResizeAllowed(stack.mStackId)) { 1785 return null; 1786 } 1787 1788 stack.findTaskForResizePoint(x, y, delta, mTmpTaskForResizePointSearchResult); 1789 if (mTmpTaskForResizePointSearchResult.searchDone) { 1790 return mTmpTaskForResizePointSearchResult.taskForResize; 1791 } 1792 } 1793 return null; 1794 } 1795 1796 void setTouchExcludeRegion(Task focusedTask) { 1797 // The provided task is the task on this display with focus, so if WindowManagerService's 1798 // focused app is not on this display, focusedTask will be null. 1799 if (focusedTask == null) { 1800 mTouchExcludeRegion.setEmpty(); 1801 } else { 1802 mTouchExcludeRegion.set(mBaseDisplayRect); 1803 final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics); 1804 mTmpRect2.setEmpty(); 1805 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) { 1806 final TaskStack stack = mTaskStackContainers.get(stackNdx); 1807 stack.setTouchExcludeRegion( 1808 focusedTask, delta, mTouchExcludeRegion, mContentRect, mTmpRect2); 1809 } 1810 // If we removed the focused task above, add it back and only leave its 1811 // outside touch area in the exclusion. TapDectector is not interested in 1812 // any touch inside the focused task itself. 1813 if (!mTmpRect2.isEmpty()) { 1814 mTouchExcludeRegion.op(mTmpRect2, Region.Op.UNION); 1815 } 1816 } 1817 final WindowState inputMethod = mService.mInputMethodWindow; 1818 if (inputMethod != null && inputMethod.isVisibleLw()) { 1819 // If the input method is visible and the user is typing, we don't want these touch 1820 // events to be intercepted and used to change focus. This would likely cause a 1821 // disappearance of the input method. 1822 inputMethod.getTouchableRegion(mTmpRegion); 1823 if (inputMethod.getDisplayId() == mDisplayId) { 1824 mTouchExcludeRegion.op(mTmpRegion, Op.UNION); 1825 } else { 1826 // IME is on a different display, so we need to update its tap detector. 1827 // TODO(multidisplay): Remove when IME will always appear on same display. 1828 inputMethod.getDisplayContent().setTouchExcludeRegion(null /* focusedTask */); 1829 } 1830 } 1831 for (int i = mTapExcludedWindows.size() - 1; i >= 0; i--) { 1832 WindowState win = mTapExcludedWindows.get(i); 1833 win.getTouchableRegion(mTmpRegion); 1834 mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION); 1835 } 1836 // TODO(multi-display): Support docked stacks on secondary displays. 1837 if (mDisplayId == DEFAULT_DISPLAY && getDockedStackLocked() != null) { 1838 mDividerControllerLocked.getTouchRegion(mTmpRect); 1839 mTmpRegion.set(mTmpRect); 1840 mTouchExcludeRegion.op(mTmpRegion, Op.UNION); 1841 } 1842 if (mTapDetector != null) { 1843 mTapDetector.setTouchExcludeRegion(mTouchExcludeRegion); 1844 } 1845 } 1846 1847 @Override 1848 void switchUser() { 1849 super.switchUser(); 1850 mService.mWindowsChanged = true; 1851 } 1852 1853 private void resetAnimationBackgroundAnimator() { 1854 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) { 1855 mTaskStackContainers.get(stackNdx).resetAnimationBackgroundAnimator(); 1856 } 1857 } 1858 1859 boolean animateDimLayers() { 1860 return mDimLayerController.animateDimLayers(); 1861 } 1862 1863 private void resetDimming() { 1864 mDimLayerController.resetDimming(); 1865 } 1866 1867 boolean isDimming() { 1868 return mDimLayerController.isDimming(); 1869 } 1870 1871 private void stopDimmingIfNeeded() { 1872 mDimLayerController.stopDimmingIfNeeded(); 1873 } 1874 1875 @Override 1876 void removeIfPossible() { 1877 if (isAnimating()) { 1878 mDeferredRemoval = true; 1879 return; 1880 } 1881 removeImmediately(); 1882 } 1883 1884 @Override 1885 void removeImmediately() { 1886 mRemovingDisplay = true; 1887 try { 1888 super.removeImmediately(); 1889 if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + this); 1890 mDimLayerController.close(); 1891 if (mDisplayId == DEFAULT_DISPLAY && mService.canDispatchPointerEvents()) { 1892 mService.unregisterPointerEventListener(mTapDetector); 1893 mService.unregisterPointerEventListener(mService.mMousePositionTracker); 1894 } 1895 } finally { 1896 mRemovingDisplay = false; 1897 } 1898 } 1899 1900 /** Returns true if a removal action is still being deferred. */ 1901 @Override 1902 boolean checkCompleteDeferredRemoval() { 1903 final boolean stillDeferringRemoval = super.checkCompleteDeferredRemoval(); 1904 1905 if (!stillDeferringRemoval && mDeferredRemoval) { 1906 removeImmediately(); 1907 mService.onDisplayRemoved(mDisplayId); 1908 return false; 1909 } 1910 return true; 1911 } 1912 1913 /** @return 'true' if removal of this display content is deferred due to active animation. */ 1914 boolean isRemovalDeferred() { 1915 return mDeferredRemoval; 1916 } 1917 1918 boolean animateForIme(float interpolatedValue, float animationTarget, 1919 float dividerAnimationTarget) { 1920 boolean updated = false; 1921 1922 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 1923 final TaskStack stack = mTaskStackContainers.get(i); 1924 if (stack == null || !stack.isAdjustedForIme()) { 1925 continue; 1926 } 1927 1928 if (interpolatedValue >= 1f && animationTarget == 0f && dividerAnimationTarget == 0f) { 1929 stack.resetAdjustedForIme(true /* adjustBoundsNow */); 1930 updated = true; 1931 } else { 1932 mDividerControllerLocked.mLastAnimationProgress = 1933 mDividerControllerLocked.getInterpolatedAnimationValue(interpolatedValue); 1934 mDividerControllerLocked.mLastDividerProgress = 1935 mDividerControllerLocked.getInterpolatedDividerValue(interpolatedValue); 1936 updated |= stack.updateAdjustForIme( 1937 mDividerControllerLocked.mLastAnimationProgress, 1938 mDividerControllerLocked.mLastDividerProgress, 1939 false /* force */); 1940 } 1941 if (interpolatedValue >= 1f) { 1942 stack.endImeAdjustAnimation(); 1943 } 1944 } 1945 1946 return updated; 1947 } 1948 1949 boolean clearImeAdjustAnimation() { 1950 boolean changed = false; 1951 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 1952 final TaskStack stack = mTaskStackContainers.get(i); 1953 if (stack != null && stack.isAdjustedForIme()) { 1954 stack.resetAdjustedForIme(true /* adjustBoundsNow */); 1955 changed = true; 1956 } 1957 } 1958 return changed; 1959 } 1960 1961 void beginImeAdjustAnimation() { 1962 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 1963 final TaskStack stack = mTaskStackContainers.get(i); 1964 if (stack.isVisible() && stack.isAdjustedForIme()) { 1965 stack.beginImeAdjustAnimation(); 1966 } 1967 } 1968 } 1969 1970 void adjustForImeIfNeeded() { 1971 final WindowState imeWin = mService.mInputMethodWindow; 1972 final boolean imeVisible = imeWin != null && imeWin.isVisibleLw() && imeWin.isDisplayedLw() 1973 && !mDividerControllerLocked.isImeHideRequested(); 1974 final boolean dockVisible = isStackVisible(DOCKED_STACK_ID); 1975 final TaskStack imeTargetStack = mService.getImeFocusStackLocked(); 1976 final int imeDockSide = (dockVisible && imeTargetStack != null) ? 1977 imeTargetStack.getDockSide() : DOCKED_INVALID; 1978 final boolean imeOnTop = (imeDockSide == DOCKED_TOP); 1979 final boolean imeOnBottom = (imeDockSide == DOCKED_BOTTOM); 1980 final boolean dockMinimized = mDividerControllerLocked.isMinimizedDock(); 1981 final int imeHeight = mService.mPolicy.getInputMethodWindowVisibleHeightLw(); 1982 final boolean imeHeightChanged = imeVisible && 1983 imeHeight != mDividerControllerLocked.getImeHeightAdjustedFor(); 1984 1985 // The divider could be adjusted for IME position, or be thinner than usual, 1986 // or both. There are three possible cases: 1987 // - If IME is visible, and focus is on top, divider is not moved for IME but thinner. 1988 // - If IME is visible, and focus is on bottom, divider is moved for IME and thinner. 1989 // - If IME is not visible, divider is not moved and is normal width. 1990 1991 if (imeVisible && dockVisible && (imeOnTop || imeOnBottom) && !dockMinimized) { 1992 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 1993 final TaskStack stack = mTaskStackContainers.get(i); 1994 final boolean isDockedOnBottom = stack.getDockSide() == DOCKED_BOTTOM; 1995 if (stack.isVisible() && (imeOnBottom || isDockedOnBottom) && 1996 StackId.isStackAffectedByDragResizing(stack.mStackId)) { 1997 stack.setAdjustedForIme(imeWin, imeOnBottom && imeHeightChanged); 1998 } else { 1999 stack.resetAdjustedForIme(false); 2000 } 2001 } 2002 mDividerControllerLocked.setAdjustedForIme( 2003 imeOnBottom /*ime*/, true /*divider*/, true /*animate*/, imeWin, imeHeight); 2004 } else { 2005 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 2006 final TaskStack stack = mTaskStackContainers.get(i); 2007 stack.resetAdjustedForIme(!dockVisible); 2008 } 2009 mDividerControllerLocked.setAdjustedForIme( 2010 false /*ime*/, false /*divider*/, dockVisible /*animate*/, imeWin, imeHeight); 2011 } 2012 mPinnedStackControllerLocked.setAdjustedForIme(imeVisible, imeHeight); 2013 } 2014 2015 void setInputMethodAnimLayerAdjustment(int adj) { 2016 if (DEBUG_LAYERS) Slog.v(TAG_WM, "Setting im layer adj to " + adj); 2017 mInputMethodAnimLayerAdjustment = adj; 2018 assignWindowLayers(false /* relayoutNeeded */); 2019 } 2020 2021 /** 2022 * If a window that has an animation specifying a colored background and the current wallpaper 2023 * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to 2024 * suddenly disappear. 2025 */ 2026 int getLayerForAnimationBackground(WindowStateAnimator winAnimator) { 2027 final WindowState visibleWallpaper = mBelowAppWindowsContainers.getWindow( 2028 w -> w.mIsWallpaper && w.isVisibleNow()); 2029 2030 if (visibleWallpaper != null) { 2031 return visibleWallpaper.mWinAnimator.mAnimLayer; 2032 } 2033 return winAnimator.mAnimLayer; 2034 } 2035 2036 void prepareFreezingTaskBounds() { 2037 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) { 2038 final TaskStack stack = mTaskStackContainers.get(stackNdx); 2039 stack.prepareFreezingTaskBounds(); 2040 } 2041 } 2042 2043 void rotateBounds(int oldRotation, int newRotation, Rect bounds) { 2044 getLogicalDisplayRect(mTmpRect, newRotation); 2045 2046 // Compute a transform matrix to undo the coordinate space transformation, 2047 // and present the window at the same physical position it previously occupied. 2048 final int deltaRotation = deltaRotation(newRotation, oldRotation); 2049 createRotationMatrix(deltaRotation, mTmpRect.width(), mTmpRect.height(), mTmpMatrix); 2050 2051 mTmpRectF.set(bounds); 2052 mTmpMatrix.mapRect(mTmpRectF); 2053 mTmpRectF.round(bounds); 2054 } 2055 2056 static int deltaRotation(int oldRotation, int newRotation) { 2057 int delta = newRotation - oldRotation; 2058 if (delta < 0) delta += 4; 2059 return delta; 2060 } 2061 2062 private static void createRotationMatrix(int rotation, float displayWidth, float displayHeight, 2063 Matrix outMatrix) { 2064 // For rotations without Z-ordering we don't need the target rectangle's position. 2065 createRotationMatrix(rotation, 0 /* rectLeft */, 0 /* rectTop */, displayWidth, 2066 displayHeight, outMatrix); 2067 } 2068 2069 static void createRotationMatrix(int rotation, float rectLeft, float rectTop, 2070 float displayWidth, float displayHeight, Matrix outMatrix) { 2071 switch (rotation) { 2072 case ROTATION_0: 2073 outMatrix.reset(); 2074 break; 2075 case ROTATION_270: 2076 outMatrix.setRotate(270, 0, 0); 2077 outMatrix.postTranslate(0, displayHeight); 2078 outMatrix.postTranslate(rectTop, 0); 2079 break; 2080 case ROTATION_180: 2081 outMatrix.reset(); 2082 break; 2083 case ROTATION_90: 2084 outMatrix.setRotate(90, 0, 0); 2085 outMatrix.postTranslate(displayWidth, 0); 2086 outMatrix.postTranslate(-rectTop, rectLeft); 2087 break; 2088 } 2089 } 2090 2091 public void dump(String prefix, PrintWriter pw) { 2092 pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId); 2093 final String subPrefix = " " + prefix; 2094 pw.print(subPrefix); pw.print("init="); pw.print(mInitialDisplayWidth); pw.print("x"); 2095 pw.print(mInitialDisplayHeight); pw.print(" "); pw.print(mInitialDisplayDensity); 2096 pw.print("dpi"); 2097 if (mInitialDisplayWidth != mBaseDisplayWidth 2098 || mInitialDisplayHeight != mBaseDisplayHeight 2099 || mInitialDisplayDensity != mBaseDisplayDensity) { 2100 pw.print(" base="); 2101 pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight); 2102 pw.print(" "); pw.print(mBaseDisplayDensity); pw.print("dpi"); 2103 } 2104 if (mDisplayScalingDisabled) { 2105 pw.println(" noscale"); 2106 } 2107 pw.print(" cur="); 2108 pw.print(mDisplayInfo.logicalWidth); 2109 pw.print("x"); pw.print(mDisplayInfo.logicalHeight); 2110 pw.print(" app="); 2111 pw.print(mDisplayInfo.appWidth); 2112 pw.print("x"); pw.print(mDisplayInfo.appHeight); 2113 pw.print(" rng="); pw.print(mDisplayInfo.smallestNominalAppWidth); 2114 pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight); 2115 pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth); 2116 pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight); 2117 pw.println(subPrefix + "deferred=" + mDeferredRemoval 2118 + " mLayoutNeeded=" + mLayoutNeeded); 2119 2120 pw.println(); 2121 pw.println(prefix + "Application tokens in top down Z order:"); 2122 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) { 2123 final TaskStack stack = mTaskStackContainers.get(stackNdx); 2124 stack.dump(prefix + " ", pw); 2125 } 2126 2127 pw.println(); 2128 if (!mExitingTokens.isEmpty()) { 2129 pw.println(); 2130 pw.println(" Exiting tokens:"); 2131 for (int i = mExitingTokens.size() - 1; i >= 0; i--) { 2132 final WindowToken token = mExitingTokens.get(i); 2133 pw.print(" Exiting #"); pw.print(i); 2134 pw.print(' '); pw.print(token); 2135 pw.println(':'); 2136 token.dump(pw, " "); 2137 } 2138 } 2139 pw.println(); 2140 mDimLayerController.dump(prefix, pw); 2141 pw.println(); 2142 mDividerControllerLocked.dump(prefix, pw); 2143 pw.println(); 2144 mPinnedStackControllerLocked.dump(prefix, pw); 2145 2146 if (mInputMethodAnimLayerAdjustment != 0) { 2147 pw.println(subPrefix 2148 + "mInputMethodAnimLayerAdjustment=" + mInputMethodAnimLayerAdjustment); 2149 } 2150 } 2151 2152 @Override 2153 public String toString() { 2154 return "Display " + mDisplayId + " info=" + mDisplayInfo + " stacks=" + mChildren; 2155 } 2156 2157 String getName() { 2158 return "Display " + mDisplayId + " name=\"" + mDisplayInfo.name + "\""; 2159 } 2160 2161 /** Checks if stack with provided id is visible on this display. */ 2162 boolean isStackVisible(int stackId) { 2163 final TaskStack stack = getStackById(stackId); 2164 return (stack != null && stack.isVisible()); 2165 } 2166 2167 /** 2168 * @return The docked stack, but only if it is visible, and {@code null} otherwise. 2169 */ 2170 TaskStack getDockedStackLocked() { 2171 final TaskStack stack = getStackById(DOCKED_STACK_ID); 2172 return (stack != null && stack.isVisible()) ? stack : null; 2173 } 2174 2175 /** 2176 * Like {@link #getDockedStackLocked}, but also returns the docked stack if it's currently not 2177 * visible. 2178 */ 2179 TaskStack getDockedStackIgnoringVisibility() { 2180 return getStackById(DOCKED_STACK_ID); 2181 } 2182 2183 /** Find the visible, touch-deliverable window under the given point */ 2184 WindowState getTouchableWinAtPointLocked(float xf, float yf) { 2185 final int x = (int) xf; 2186 final int y = (int) yf; 2187 final WindowState touchedWin = getWindow(w -> { 2188 final int flags = w.mAttrs.flags; 2189 if (!w.isVisibleLw()) { 2190 return false; 2191 } 2192 if ((flags & FLAG_NOT_TOUCHABLE) != 0) { 2193 return false; 2194 } 2195 2196 w.getVisibleBounds(mTmpRect); 2197 if (!mTmpRect.contains(x, y)) { 2198 return false; 2199 } 2200 2201 w.getTouchableRegion(mTmpRegion); 2202 2203 final int touchFlags = flags & (FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL); 2204 return mTmpRegion.contains(x, y) || touchFlags == 0; 2205 }); 2206 2207 return touchedWin; 2208 } 2209 2210 boolean canAddToastWindowForUid(int uid) { 2211 // We allow one toast window per UID being shown at a time. 2212 // Also if the app is focused adding more than one toast at 2213 // a time for better backwards compatibility. 2214 final WindowState focusedWindowForUid = getWindow(w -> 2215 w.mOwnerUid == uid && w.isFocused()); 2216 if (focusedWindowForUid != null) { 2217 return true; 2218 } 2219 final WindowState win = getWindow(w -> 2220 w.mAttrs.type == TYPE_TOAST && w.mOwnerUid == uid && !w.mPermanentlyHidden 2221 && !w.mWindowRemovalAllowed); 2222 return win == null; 2223 } 2224 2225 void scheduleToastWindowsTimeoutIfNeededLocked(WindowState oldFocus, WindowState newFocus) { 2226 if (oldFocus == null || (newFocus != null && newFocus.mOwnerUid == oldFocus.mOwnerUid)) { 2227 return; 2228 } 2229 2230 // Used to communicate the old focus to the callback method. 2231 mTmpWindow = oldFocus; 2232 2233 forAllWindows(mScheduleToastTimeout, false /* traverseTopToBottom */); 2234 } 2235 2236 WindowState findFocusedWindow() { 2237 mTmpWindow = null; 2238 2239 forAllWindows(mFindFocusedWindow, true /* traverseTopToBottom */); 2240 2241 if (mTmpWindow == null) { 2242 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: No focusable windows."); 2243 return null; 2244 } 2245 return mTmpWindow; 2246 } 2247 2248 /** Updates the layer assignment of windows on this display. */ 2249 void assignWindowLayers(boolean setLayoutNeeded) { 2250 mLayersController.assignWindowLayers(this); 2251 if (setLayoutNeeded) { 2252 setLayoutNeeded(); 2253 } 2254 } 2255 2256 // TODO: This should probably be called any time a visual change is made to the hierarchy like 2257 // moving containers or resizing them. Need to investigate the best way to have it automatically 2258 // happen so we don't run into issues with programmers forgetting to do it. 2259 void layoutAndAssignWindowLayersIfNeeded() { 2260 mService.mWindowsChanged = true; 2261 setLayoutNeeded(); 2262 2263 if (!mService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 2264 false /*updateInputWindows*/)) { 2265 assignWindowLayers(false /* setLayoutNeeded */); 2266 } 2267 2268 mService.mInputMonitor.setUpdateInputWindowsNeededLw(); 2269 mService.mWindowPlacerLocked.performSurfacePlacement(); 2270 mService.mInputMonitor.updateInputWindowsLw(false /*force*/); 2271 } 2272 2273 /** Returns true if a leaked surface was destroyed */ 2274 boolean destroyLeakedSurfaces() { 2275 // Used to indicate that a surface was leaked. 2276 mTmpWindow = null; 2277 forAllWindows(w -> { 2278 final WindowStateAnimator wsa = w.mWinAnimator; 2279 if (wsa.mSurfaceController == null) { 2280 return; 2281 } 2282 if (!mService.mSessions.contains(wsa.mSession)) { 2283 Slog.w(TAG_WM, "LEAKED SURFACE (session doesn't exist): " 2284 + w + " surface=" + wsa.mSurfaceController 2285 + " token=" + w.mToken 2286 + " pid=" + w.mSession.mPid 2287 + " uid=" + w.mSession.mUid); 2288 wsa.destroySurface(); 2289 mService.mForceRemoves.add(w); 2290 mTmpWindow = w; 2291 } else if (w.mAppToken != null && w.mAppToken.isClientHidden()) { 2292 Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): " 2293 + w + " surface=" + wsa.mSurfaceController 2294 + " token=" + w.mAppToken 2295 + " saved=" + w.hasSavedSurface()); 2296 if (SHOW_TRANSACTIONS) logSurface(w, "LEAK DESTROY", false); 2297 wsa.destroySurface(); 2298 mTmpWindow = w; 2299 } 2300 }, false /* traverseTopToBottom */); 2301 2302 return mTmpWindow != null; 2303 } 2304 2305 /** 2306 * Determine and return the window that should be the IME target. 2307 * @param updateImeTarget If true the system IME target will be updated to match what we found. 2308 * @return The window that should be used as the IME target or null if there isn't any. 2309 */ 2310 WindowState computeImeTarget(boolean updateImeTarget) { 2311 if (mService.mInputMethodWindow == null) { 2312 // There isn't an IME so there shouldn't be a target...That was easy! 2313 if (updateImeTarget) { 2314 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " 2315 + mService.mInputMethodTarget + " to null since mInputMethodWindow is null"); 2316 setInputMethodTarget(null, mService.mInputMethodTargetWaitingAnim, 0); 2317 } 2318 return null; 2319 } 2320 2321 // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the 2322 // same display. Or even when the current IME/target are not on the same screen as the next 2323 // IME/target. For now only look for input windows on the main screen. 2324 mUpdateImeTarget = updateImeTarget; 2325 WindowState target = getWindow(mComputeImeTargetPredicate); 2326 2327 2328 // Yet more tricksyness! If this window is a "starting" window, we do actually want 2329 // to be on top of it, but it is not -really- where input will go. So look down below 2330 // for a real window to target... 2331 if (target != null && target.mAttrs.type == TYPE_APPLICATION_STARTING) { 2332 final AppWindowToken token = target.mAppToken; 2333 if (token != null) { 2334 final WindowState betterTarget = token.getImeTargetBelowWindow(target); 2335 if (betterTarget != null) { 2336 target = betterTarget; 2337 } 2338 } 2339 } 2340 2341 if (DEBUG_INPUT_METHOD && updateImeTarget) Slog.v(TAG_WM, 2342 "Proposed new IME target: " + target); 2343 2344 // Now, a special case -- if the last target's window is in the process of exiting, and is 2345 // above the new target, keep on the last target to avoid flicker. Consider for example a 2346 // Dialog with the IME shown: when the Dialog is dismissed, we want to keep the IME above it 2347 // until it is completely gone so it doesn't drop behind the dialog or its full-screen 2348 // scrim. 2349 final WindowState curTarget = mService.mInputMethodTarget; 2350 if (curTarget != null && curTarget.isDisplayedLw() && curTarget.isClosing() 2351 && (target == null 2352 || curTarget.mWinAnimator.mAnimLayer > target.mWinAnimator.mAnimLayer)) { 2353 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Current target higher, not changing"); 2354 return curTarget; 2355 } 2356 2357 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Desired input method target=" + target 2358 + " updateImeTarget=" + updateImeTarget); 2359 2360 if (target == null) { 2361 if (updateImeTarget) { 2362 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget 2363 + " to null." + (SHOW_STACK_CRAWLS ? " Callers=" 2364 + Debug.getCallers(4) : "")); 2365 setInputMethodTarget(null, mService.mInputMethodTargetWaitingAnim, 0); 2366 } 2367 2368 return null; 2369 } 2370 2371 if (updateImeTarget) { 2372 AppWindowToken token = curTarget == null ? null : curTarget.mAppToken; 2373 if (token != null) { 2374 2375 // Now some fun for dealing with window animations that modify the Z order. We need 2376 // to look at all windows below the current target that are in this app, finding the 2377 // highest visible one in layering. 2378 WindowState highestTarget = null; 2379 if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) { 2380 highestTarget = token.getHighestAnimLayerWindow(curTarget); 2381 } 2382 2383 if (highestTarget != null) { 2384 final AppTransition appTransition = mService.mAppTransition; 2385 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, appTransition + " " + highestTarget 2386 + " animating=" + highestTarget.mWinAnimator.isAnimationSet() 2387 + " layer=" + highestTarget.mWinAnimator.mAnimLayer 2388 + " new layer=" + target.mWinAnimator.mAnimLayer); 2389 2390 if (appTransition.isTransitionSet()) { 2391 // If we are currently setting up for an animation, hold everything until we 2392 // can find out what will happen. 2393 setInputMethodTarget(highestTarget, true, mInputMethodAnimLayerAdjustment); 2394 return highestTarget; 2395 } else if (highestTarget.mWinAnimator.isAnimationSet() && 2396 highestTarget.mWinAnimator.mAnimLayer > target.mWinAnimator.mAnimLayer) { 2397 // If the window we are currently targeting is involved with an animation, 2398 // and it is on top of the next target we will be over, then hold off on 2399 // moving until that is done. 2400 setInputMethodTarget(highestTarget, true, mInputMethodAnimLayerAdjustment); 2401 return highestTarget; 2402 } 2403 } 2404 } 2405 2406 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget + " to " 2407 + target + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : "")); 2408 setInputMethodTarget(target, false, target.mAppToken != null 2409 ? target.mAppToken.getAnimLayerAdjustment() : 0); 2410 } 2411 2412 return target; 2413 } 2414 2415 private void setInputMethodTarget(WindowState target, boolean targetWaitingAnim, int layerAdj) { 2416 if (target == mService.mInputMethodTarget 2417 && mService.mInputMethodTargetWaitingAnim == targetWaitingAnim 2418 && mInputMethodAnimLayerAdjustment == layerAdj) { 2419 return; 2420 } 2421 2422 mService.mInputMethodTarget = target; 2423 mService.mInputMethodTargetWaitingAnim = targetWaitingAnim; 2424 setInputMethodAnimLayerAdjustment(layerAdj); 2425 assignWindowLayers(false /* setLayoutNeeded */); 2426 } 2427 2428 boolean getNeedsMenu(WindowState top, WindowManagerPolicy.WindowState bottom) { 2429 if (top.mAttrs.needsMenuKey != NEEDS_MENU_UNSET) { 2430 return top.mAttrs.needsMenuKey == NEEDS_MENU_SET_TRUE; 2431 } 2432 2433 // Used to indicate we have reached the first window in the range we are interested in. 2434 mTmpWindow = null; 2435 2436 // TODO: Figure-out a more efficient way to do this. 2437 final WindowState candidate = getWindow(w -> { 2438 if (w == top) { 2439 // Reached the first window in the range we are interested in. 2440 mTmpWindow = w; 2441 } 2442 if (mTmpWindow == null) { 2443 return false; 2444 } 2445 2446 if (w.mAttrs.needsMenuKey != NEEDS_MENU_UNSET) { 2447 return true; 2448 } 2449 // If we reached the bottom of the range of windows we are considering, 2450 // assume no menu is needed. 2451 if (w == bottom) { 2452 return true; 2453 } 2454 return false; 2455 }); 2456 2457 return candidate != null && candidate.mAttrs.needsMenuKey == NEEDS_MENU_SET_TRUE; 2458 } 2459 2460 void setLayoutNeeded() { 2461 if (DEBUG_LAYOUT) Slog.w(TAG_WM, "setLayoutNeeded: callers=" + Debug.getCallers(3)); 2462 mLayoutNeeded = true; 2463 } 2464 2465 private void clearLayoutNeeded() { 2466 if (DEBUG_LAYOUT) Slog.w(TAG_WM, "clearLayoutNeeded: callers=" + Debug.getCallers(3)); 2467 mLayoutNeeded = false; 2468 } 2469 2470 boolean isLayoutNeeded() { 2471 return mLayoutNeeded; 2472 } 2473 2474 void dumpTokens(PrintWriter pw, boolean dumpAll) { 2475 if (mTokenMap.isEmpty()) { 2476 return; 2477 } 2478 pw.println(" Display #" + mDisplayId); 2479 final Iterator<WindowToken> it = mTokenMap.values().iterator(); 2480 while (it.hasNext()) { 2481 final WindowToken token = it.next(); 2482 pw.print(" "); 2483 pw.print(token); 2484 if (dumpAll) { 2485 pw.println(':'); 2486 token.dump(pw, " "); 2487 } else { 2488 pw.println(); 2489 } 2490 } 2491 } 2492 2493 void dumpWindowAnimators(PrintWriter pw, String subPrefix) { 2494 final int[] index = new int[1]; 2495 forAllWindows(w -> { 2496 final WindowStateAnimator wAnim = w.mWinAnimator; 2497 pw.println(subPrefix + "Window #" + index[0] + ": " + wAnim); 2498 index[0] = index[0] + 1; 2499 }, false /* traverseTopToBottom */); 2500 } 2501 2502 void enableSurfaceTrace(FileDescriptor fd) { 2503 forAllWindows(w -> { 2504 w.mWinAnimator.enableSurfaceTrace(fd); 2505 }, true /* traverseTopToBottom */); 2506 } 2507 2508 void disableSurfaceTrace() { 2509 forAllWindows(w -> { 2510 w.mWinAnimator.disableSurfaceTrace(); 2511 }, true /* traverseTopToBottom */); 2512 } 2513 2514 /** 2515 * Starts the Keyguard exit animation on all windows that don't belong to an app token. 2516 */ 2517 void startKeyguardExitOnNonAppWindows(boolean onWallpaper, boolean goingToShade) { 2518 final WindowManagerPolicy policy = mService.mPolicy; 2519 forAllWindows(w -> { 2520 if (w.mAppToken == null && policy.canBeHiddenByKeyguardLw(w) 2521 && w.wouldBeVisibleIfPolicyIgnored() && !w.isVisible()) { 2522 w.mWinAnimator.setAnimation( 2523 policy.createHiddenByKeyguardExit(onWallpaper, goingToShade)); 2524 } 2525 }, true /* traverseTopToBottom */); 2526 } 2527 2528 boolean checkWaitingForWindows() { 2529 2530 mHaveBootMsg = false; 2531 mHaveApp = false; 2532 mHaveWallpaper = false; 2533 mHaveKeyguard = true; 2534 2535 final WindowState visibleWindow = getWindow(w -> { 2536 if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) { 2537 return true; 2538 } 2539 if (w.isDrawnLw()) { 2540 if (w.mAttrs.type == TYPE_BOOT_PROGRESS) { 2541 mHaveBootMsg = true; 2542 } else if (w.mAttrs.type == TYPE_APPLICATION 2543 || w.mAttrs.type == TYPE_DRAWN_APPLICATION) { 2544 mHaveApp = true; 2545 } else if (w.mAttrs.type == TYPE_WALLPAPER) { 2546 mHaveWallpaper = true; 2547 } else if (w.mAttrs.type == TYPE_STATUS_BAR) { 2548 mHaveKeyguard = mService.mPolicy.isKeyguardDrawnLw(); 2549 } 2550 } 2551 return false; 2552 }); 2553 2554 if (visibleWindow != null) { 2555 // We have a visible window. 2556 return true; 2557 } 2558 2559 // if the wallpaper service is disabled on the device, we're never going to have 2560 // wallpaper, don't bother waiting for it 2561 boolean wallpaperEnabled = mService.mContext.getResources().getBoolean( 2562 com.android.internal.R.bool.config_enableWallpaperService) 2563 && !mService.mOnlyCore; 2564 2565 if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG_WM, 2566 "******** booted=" + mService.mSystemBooted 2567 + " msg=" + mService.mShowingBootMessages 2568 + " haveBoot=" + mHaveBootMsg + " haveApp=" + mHaveApp 2569 + " haveWall=" + mHaveWallpaper + " wallEnabled=" + wallpaperEnabled 2570 + " haveKeyguard=" + mHaveKeyguard); 2571 2572 // If we are turning on the screen to show the boot message, don't do it until the boot 2573 // message is actually displayed. 2574 if (!mService.mSystemBooted && !mHaveBootMsg) { 2575 return true; 2576 } 2577 2578 // If we are turning on the screen after the boot is completed normally, don't do so until 2579 // we have the application and wallpaper. 2580 if (mService.mSystemBooted 2581 && ((!mHaveApp && !mHaveKeyguard) || (wallpaperEnabled && !mHaveWallpaper))) { 2582 return true; 2583 } 2584 2585 return false; 2586 } 2587 2588 void updateWindowsForAnimator(WindowAnimator animator) { 2589 mTmpWindowAnimator = animator; 2590 forAllWindows(mUpdateWindowsForAnimator, true /* traverseTopToBottom */); 2591 } 2592 2593 void updateWallpaperForAnimator(WindowAnimator animator) { 2594 resetAnimationBackgroundAnimator(); 2595 2596 // Used to indicate a detached wallpaper. 2597 mTmpWindow = null; 2598 mTmpWindowAnimator = animator; 2599 2600 forAllWindows(mUpdateWallpaperForAnimator, true /* traverseTopToBottom */); 2601 2602 if (animator.mWindowDetachedWallpaper != mTmpWindow) { 2603 if (DEBUG_WALLPAPER) Slog.v(TAG, "Detached wallpaper changed from " 2604 + animator.mWindowDetachedWallpaper + " to " + mTmpWindow); 2605 animator.mWindowDetachedWallpaper = mTmpWindow; 2606 animator.mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE; 2607 } 2608 } 2609 2610 void prepareWindowSurfaces() { 2611 forAllWindows(mPrepareWindowSurfaces, false /* traverseTopToBottom */); 2612 } 2613 2614 boolean inputMethodClientHasFocus(IInputMethodClient client) { 2615 final WindowState imFocus = computeImeTarget(false /* updateImeTarget */); 2616 if (imFocus == null) { 2617 return false; 2618 } 2619 2620 if (DEBUG_INPUT_METHOD) { 2621 Slog.i(TAG_WM, "Desired input method target: " + imFocus); 2622 Slog.i(TAG_WM, "Current focus: " + mService.mCurrentFocus); 2623 Slog.i(TAG_WM, "Last focus: " + mService.mLastFocus); 2624 } 2625 2626 final IInputMethodClient imeClient = imFocus.mSession.mClient; 2627 2628 if (DEBUG_INPUT_METHOD) { 2629 Slog.i(TAG_WM, "IM target client: " + imeClient); 2630 if (imeClient != null) { 2631 Slog.i(TAG_WM, "IM target client binder: " + imeClient.asBinder()); 2632 Slog.i(TAG_WM, "Requesting client binder: " + client.asBinder()); 2633 } 2634 } 2635 2636 return imeClient != null && imeClient.asBinder() == client.asBinder(); 2637 } 2638 2639 boolean hasSecureWindowOnScreen() { 2640 final WindowState win = getWindow( 2641 w -> w.isOnScreen() && (w.mAttrs.flags & FLAG_SECURE) != 0); 2642 return win != null; 2643 } 2644 2645 void updateSystemUiVisibility(int visibility, int globalDiff) { 2646 forAllWindows(w -> { 2647 try { 2648 final int curValue = w.mSystemUiVisibility; 2649 final int diff = (curValue ^ visibility) & globalDiff; 2650 final int newValue = (curValue & ~diff) | (visibility & diff); 2651 if (newValue != curValue) { 2652 w.mSeq++; 2653 w.mSystemUiVisibility = newValue; 2654 } 2655 if (newValue != curValue || w.mAttrs.hasSystemUiListeners) { 2656 w.mClient.dispatchSystemUiVisibilityChanged(w.mSeq, 2657 visibility, newValue, diff); 2658 } 2659 } catch (RemoteException e) { 2660 // so sorry 2661 } 2662 }, true /* traverseTopToBottom */); 2663 } 2664 2665 void onWindowFreezeTimeout() { 2666 Slog.w(TAG_WM, "Window freeze timeout expired."); 2667 mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT; 2668 2669 forAllWindows(w -> { 2670 if (!w.mOrientationChanging) { 2671 return; 2672 } 2673 w.mOrientationChanging = false; 2674 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 2675 - mService.mDisplayFreezeTime); 2676 Slog.w(TAG_WM, "Force clearing orientation change: " + w); 2677 }, true /* traverseTopToBottom */); 2678 mService.mWindowPlacerLocked.performSurfacePlacement(); 2679 } 2680 2681 void waitForAllWindowsDrawn() { 2682 final WindowManagerPolicy policy = mService.mPolicy; 2683 forAllWindows(w -> { 2684 final boolean keyguard = policy.isKeyguardHostWindow(w.mAttrs); 2685 if (w.isVisibleLw() && (w.mAppToken != null || keyguard)) { 2686 w.mWinAnimator.mDrawState = DRAW_PENDING; 2687 // Force add to mResizingWindows. 2688 w.mLastContentInsets.set(-1, -1, -1, -1); 2689 mService.mWaitingForDrawn.add(w); 2690 } 2691 }, true /* traverseTopToBottom */); 2692 } 2693 2694 // TODO: Super crazy long method that should be broken down... 2695 boolean applySurfaceChangesTransaction(boolean recoveringMemory) { 2696 2697 final int dw = mDisplayInfo.logicalWidth; 2698 final int dh = mDisplayInfo.logicalHeight; 2699 final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked; 2700 2701 mTmpUpdateAllDrawn.clear(); 2702 2703 int repeats = 0; 2704 do { 2705 repeats++; 2706 if (repeats > 6) { 2707 Slog.w(TAG, "Animation repeat aborted after too many iterations"); 2708 clearLayoutNeeded(); 2709 break; 2710 } 2711 2712 if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("On entry to LockedInner", 2713 pendingLayoutChanges); 2714 2715 // TODO(multi-display): For now adjusting wallpaper only on primary display to avoid 2716 // the wallpaper window jumping across displays. 2717 // Remove check for default display when there will be support for multiple wallpaper 2718 // targets (on different displays). 2719 if (isDefaultDisplay && (pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) { 2720 mWallpaperController.adjustWallpaperWindows(this); 2721 } 2722 2723 if (isDefaultDisplay && (pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) { 2724 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); 2725 if (mService.updateOrientationFromAppTokensLocked(true, mDisplayId)) { 2726 setLayoutNeeded(); 2727 mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, mDisplayId).sendToTarget(); 2728 } 2729 } 2730 2731 if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_LAYOUT) != 0) { 2732 setLayoutNeeded(); 2733 } 2734 2735 // FIRST LOOP: Perform a layout, if needed. 2736 if (repeats < LAYOUT_REPEAT_THRESHOLD) { 2737 performLayout(repeats == 1, false /* updateInputWindows */); 2738 } else { 2739 Slog.w(TAG, "Layout repeat skipped after too many iterations"); 2740 } 2741 2742 // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think it is animating. 2743 pendingLayoutChanges = 0; 2744 2745 if (isDefaultDisplay) { 2746 mService.mPolicy.beginPostLayoutPolicyLw(dw, dh); 2747 forAllWindows(mApplyPostLayoutPolicy, true /* traverseTopToBottom */); 2748 pendingLayoutChanges |= mService.mPolicy.finishPostLayoutPolicyLw(); 2749 if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats( 2750 "after finishPostLayoutPolicyLw", pendingLayoutChanges); 2751 } 2752 } while (pendingLayoutChanges != 0); 2753 2754 mTmpApplySurfaceChangesTransactionState.reset(); 2755 resetDimming(); 2756 2757 mTmpRecoveringMemory = recoveringMemory; 2758 forAllWindows(mApplySurfaceChangesTransaction, true /* traverseTopToBottom */); 2759 2760 mService.mDisplayManagerInternal.setDisplayProperties(mDisplayId, 2761 mTmpApplySurfaceChangesTransactionState.displayHasContent, 2762 mTmpApplySurfaceChangesTransactionState.preferredRefreshRate, 2763 mTmpApplySurfaceChangesTransactionState.preferredModeId, 2764 true /* inTraversal, must call performTraversalInTrans... below */); 2765 2766 stopDimmingIfNeeded(); 2767 2768 while (!mTmpUpdateAllDrawn.isEmpty()) { 2769 final AppWindowToken atoken = mTmpUpdateAllDrawn.removeLast(); 2770 // See if any windows have been drawn, so they (and others associated with them) 2771 // can now be shown. 2772 atoken.updateAllDrawn(); 2773 } 2774 2775 return mTmpApplySurfaceChangesTransactionState.focusDisplayed; 2776 } 2777 2778 void performLayout(boolean initial, boolean updateInputWindows) { 2779 if (!isLayoutNeeded()) { 2780 return; 2781 } 2782 clearLayoutNeeded(); 2783 2784 final int dw = mDisplayInfo.logicalWidth; 2785 final int dh = mDisplayInfo.logicalHeight; 2786 2787 if (DEBUG_LAYOUT) { 2788 Slog.v(TAG, "-------------------------------------"); 2789 Slog.v(TAG, "performLayout: needed=" + isLayoutNeeded() + " dw=" + dw + " dh=" + dh); 2790 } 2791 2792 mService.mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mRotation, 2793 getConfiguration().uiMode); 2794 if (isDefaultDisplay) { 2795 // Not needed on non-default displays. 2796 mService.mSystemDecorLayer = mService.mPolicy.getSystemDecorLayerLw(); 2797 mService.mScreenRect.set(0, 0, dw, dh); 2798 } 2799 2800 mService.mPolicy.getContentRectLw(mContentRect); 2801 2802 int seq = mService.mLayoutSeq + 1; 2803 if (seq < 0) seq = 0; 2804 mService.mLayoutSeq = seq; 2805 2806 // Used to indicate that we have processed the dream window and all additional windows are 2807 // behind it. 2808 mTmpWindow = null; 2809 mTmpInitial = initial; 2810 2811 // First perform layout of any root windows (not attached to another window). 2812 forAllWindows(mPerformLayout, true /* traverseTopToBottom */); 2813 2814 // Used to indicate that we have processed the dream window and all additional attached 2815 // windows are behind it. 2816 mTmpWindow2 = mTmpWindow; 2817 mTmpWindow = null; 2818 2819 // Now perform layout of attached windows, which usually depend on the position of the 2820 // window they are attached to. XXX does not deal with windows that are attached to windows 2821 // that are themselves attached. 2822 forAllWindows(mPerformLayoutAttached, true /* traverseTopToBottom */); 2823 2824 // Window frames may have changed. Tell the input dispatcher about it. 2825 mService.mInputMonitor.layoutInputConsumers(dw, dh); 2826 mService.mInputMonitor.setUpdateInputWindowsNeededLw(); 2827 if (updateInputWindows) { 2828 mService.mInputMonitor.updateInputWindowsLw(false /*force*/); 2829 } 2830 2831 mService.mPolicy.finishLayoutLw(); 2832 mService.mH.sendEmptyMessage(UPDATE_DOCKED_STACK_DIVIDER); 2833 } 2834 2835 /** 2836 * Takes a snapshot of the display. In landscape mode this grabs the whole screen. 2837 * In portrait mode, it grabs the full screenshot. 2838 * 2839 * @param width the width of the target bitmap 2840 * @param height the height of the target bitmap 2841 * @param includeFullDisplay true if the screen should not be cropped before capture 2842 * @param frameScale the scale to apply to the frame, only used when width = -1 and height = -1 2843 * @param config of the output bitmap 2844 * @param wallpaperOnly true if only the wallpaper layer should be included in the screenshot 2845 * @param includeDecor whether to include window decors, like the status or navigation bar 2846 * background of the window 2847 */ 2848 Bitmap screenshotApplications(IBinder appToken, int width, int height, 2849 boolean includeFullDisplay, float frameScale, Bitmap.Config config, 2850 boolean wallpaperOnly, boolean includeDecor) { 2851 Bitmap bitmap = screenshotApplications(appToken, width, height, includeFullDisplay, 2852 frameScale, wallpaperOnly, includeDecor, SurfaceControl::screenshot); 2853 if (bitmap == null) { 2854 return null; 2855 } 2856 2857 if (DEBUG_SCREENSHOT) { 2858 // TEST IF IT's ALL BLACK 2859 int[] buffer = new int[bitmap.getWidth() * bitmap.getHeight()]; 2860 bitmap.getPixels(buffer, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), 2861 bitmap.getHeight()); 2862 boolean allBlack = true; 2863 final int firstColor = buffer[0]; 2864 for (int i = 0; i < buffer.length; i++) { 2865 if (buffer[i] != firstColor) { 2866 allBlack = false; 2867 break; 2868 } 2869 } 2870 if (allBlack) { 2871 final WindowState appWin = mScreenshotApplicationState.appWin; 2872 final int maxLayer = mScreenshotApplicationState.maxLayer; 2873 final int minLayer = mScreenshotApplicationState.minLayer; 2874 Slog.i(TAG_WM, "Screenshot " + appWin + " was monochrome(" + 2875 Integer.toHexString(firstColor) + ")! mSurfaceLayer=" + 2876 (appWin != null ? 2877 appWin.mWinAnimator.mSurfaceController.getLayer() : "null") + 2878 " minLayer=" + minLayer + " maxLayer=" + maxLayer); 2879 } 2880 } 2881 2882 // Create a copy of the screenshot that is immutable and backed in ashmem. 2883 // This greatly reduces the overhead of passing the bitmap between processes. 2884 Bitmap ret = bitmap.createAshmemBitmap(config); 2885 bitmap.recycle(); 2886 return ret; 2887 } 2888 2889 GraphicBuffer screenshotApplicationsToBuffer(IBinder appToken, int width, int height, 2890 boolean includeFullDisplay, float frameScale, boolean wallpaperOnly, 2891 boolean includeDecor) { 2892 return screenshotApplications(appToken, width, height, includeFullDisplay, frameScale, 2893 wallpaperOnly, includeDecor, SurfaceControl::screenshotToBuffer); 2894 } 2895 2896 private <E> E screenshotApplications(IBinder appToken, int width, int height, 2897 boolean includeFullDisplay, float frameScale, boolean wallpaperOnly, 2898 boolean includeDecor, Screenshoter<E> screenshoter) { 2899 int dw = mDisplayInfo.logicalWidth; 2900 int dh = mDisplayInfo.logicalHeight; 2901 if (dw == 0 || dh == 0) { 2902 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken 2903 + ": returning null. logical widthxheight=" + dw + "x" + dh); 2904 return null; 2905 } 2906 2907 E bitmap; 2908 2909 mScreenshotApplicationState.reset(appToken == null && !wallpaperOnly); 2910 final Rect frame = new Rect(); 2911 final Rect stackBounds = new Rect(); 2912 2913 final int aboveAppLayer = (mService.mPolicy.getWindowLayerFromTypeLw(TYPE_APPLICATION) + 1) 2914 * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET; 2915 final MutableBoolean mutableIncludeFullDisplay = new MutableBoolean(includeFullDisplay); 2916 synchronized(mService.mWindowMap) { 2917 if (!mService.mPolicy.isScreenOn()) { 2918 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Attempted to take screenshot while display" 2919 + " was off."); 2920 return null; 2921 } 2922 // Figure out the part of the screen that is actually the app. 2923 mScreenshotApplicationState.appWin = null; 2924 forAllWindows(w -> { 2925 if (!w.mHasSurface) { 2926 return false; 2927 } 2928 if (w.mLayer >= aboveAppLayer) { 2929 return false; 2930 } 2931 if (wallpaperOnly && !w.mIsWallpaper) { 2932 return false; 2933 } 2934 if (w.mIsImWindow) { 2935 return false; 2936 } else if (w.mIsWallpaper) { 2937 // If this is the wallpaper layer and we're only looking for the wallpaper layer 2938 // then the target window state is this one. 2939 if (wallpaperOnly) { 2940 mScreenshotApplicationState.appWin = w; 2941 } 2942 2943 if (mScreenshotApplicationState.appWin == null) { 2944 // We have not ran across the target window yet, so it is probably behind 2945 // the wallpaper. This can happen when the keyguard is up and all windows 2946 // are moved behind the wallpaper. We don't want to include the wallpaper 2947 // layer in the screenshot as it will cover-up the layer of the target 2948 // window. 2949 return false; 2950 } 2951 // Fall through. The target window is in front of the wallpaper. For this 2952 // case we want to include the wallpaper layer in the screenshot because 2953 // the target window might have some transparent areas. 2954 } else if (appToken != null) { 2955 if (w.mAppToken == null || w.mAppToken.token != appToken) { 2956 // This app window is of no interest if it is not associated with the 2957 // screenshot app. 2958 return false; 2959 } 2960 mScreenshotApplicationState.appWin = w; 2961 } 2962 2963 // Include this window. 2964 2965 final WindowStateAnimator winAnim = w.mWinAnimator; 2966 int layer = winAnim.mSurfaceController.getLayer(); 2967 if (mScreenshotApplicationState.maxLayer < layer) { 2968 mScreenshotApplicationState.maxLayer = layer; 2969 } 2970 if (mScreenshotApplicationState.minLayer > layer) { 2971 mScreenshotApplicationState.minLayer = layer; 2972 } 2973 2974 // Don't include wallpaper in bounds calculation 2975 if (!w.mIsWallpaper && !mutableIncludeFullDisplay.value) { 2976 if (includeDecor) { 2977 final TaskStack stack = w.getStack(); 2978 if (stack != null) { 2979 stack.getBounds(frame); 2980 } 2981 2982 // We want to screenshot with the exact bounds of the surface of the app. Thus, 2983 // intersect it with the frame. 2984 frame.intersect(w.mFrame); 2985 } else { 2986 final Rect wf = w.mFrame; 2987 final Rect cr = w.mContentInsets; 2988 int left = wf.left + cr.left; 2989 int top = wf.top + cr.top; 2990 int right = wf.right - cr.right; 2991 int bottom = wf.bottom - cr.bottom; 2992 frame.union(left, top, right, bottom); 2993 w.getVisibleBounds(stackBounds); 2994 if (!Rect.intersects(frame, stackBounds)) { 2995 // Set frame empty if there's no intersection. 2996 frame.setEmpty(); 2997 } 2998 } 2999 } 3000 3001 final boolean foundTargetWs = 3002 (w.mAppToken != null && w.mAppToken.token == appToken) 3003 || (mScreenshotApplicationState.appWin != null && wallpaperOnly); 3004 if (foundTargetWs && winAnim.getShown()) { 3005 mScreenshotApplicationState.screenshotReady = true; 3006 } 3007 3008 if (w.isObscuringDisplay()){ 3009 return true; 3010 } 3011 return false; 3012 }, true /* traverseTopToBottom */); 3013 3014 final WindowState appWin = mScreenshotApplicationState.appWin; 3015 final boolean screenshotReady = mScreenshotApplicationState.screenshotReady; 3016 final int maxLayer = mScreenshotApplicationState.maxLayer; 3017 final int minLayer = mScreenshotApplicationState.minLayer; 3018 3019 if (appToken != null && appWin == null) { 3020 // Can't find a window to snapshot. 3021 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, 3022 "Screenshot: Couldn't find a surface matching " + appToken); 3023 return null; 3024 } 3025 3026 if (!screenshotReady) { 3027 Slog.i(TAG_WM, "Failed to capture screenshot of " + appToken + 3028 " appWin=" + (appWin == null ? "null" : (appWin + " drawState=" + 3029 appWin.mWinAnimator.mDrawState))); 3030 return null; 3031 } 3032 3033 // Screenshot is ready to be taken. Everything from here below will continue 3034 // through the bottom of the loop and return a value. We only stay in the loop 3035 // because we don't want to release the mWindowMap lock until the screenshot is 3036 // taken. 3037 3038 if (maxLayer == 0) { 3039 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken 3040 + ": returning null maxLayer=" + maxLayer); 3041 return null; 3042 } 3043 3044 if (!mutableIncludeFullDisplay.value) { 3045 // Constrain frame to the screen size. 3046 if (!frame.intersect(0, 0, dw, dh)) { 3047 frame.setEmpty(); 3048 } 3049 } else { 3050 // Caller just wants entire display. 3051 frame.set(0, 0, dw, dh); 3052 } 3053 if (frame.isEmpty()) { 3054 return null; 3055 } 3056 3057 if (width < 0) { 3058 width = (int) (frame.width() * frameScale); 3059 } 3060 if (height < 0) { 3061 height = (int) (frame.height() * frameScale); 3062 } 3063 3064 // Tell surface flinger what part of the image to crop. Take the top 3065 // right part of the application, and crop the larger dimension to fit. 3066 Rect crop = new Rect(frame); 3067 if (width / (float) frame.width() < height / (float) frame.height()) { 3068 int cropWidth = (int)((float)width / (float)height * frame.height()); 3069 crop.right = crop.left + cropWidth; 3070 } else { 3071 int cropHeight = (int)((float)height / (float)width * frame.width()); 3072 crop.bottom = crop.top + cropHeight; 3073 } 3074 3075 // The screenshot API does not apply the current screen rotation. 3076 int rot = mDisplay.getRotation(); 3077 3078 if (rot == ROTATION_90 || rot == ROTATION_270) { 3079 rot = (rot == ROTATION_90) ? ROTATION_270 : ROTATION_90; 3080 } 3081 3082 // Surfaceflinger is not aware of orientation, so convert our logical 3083 // crop to surfaceflinger's portrait orientation. 3084 convertCropForSurfaceFlinger(crop, rot, dw, dh); 3085 3086 if (DEBUG_SCREENSHOT) { 3087 Slog.i(TAG_WM, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to " 3088 + maxLayer + " appToken=" + appToken); 3089 forAllWindows(w -> { 3090 final WindowSurfaceController controller = w.mWinAnimator.mSurfaceController; 3091 Slog.i(TAG_WM, w + ": " + w.mLayer 3092 + " animLayer=" + w.mWinAnimator.mAnimLayer 3093 + " surfaceLayer=" + ((controller == null) 3094 ? "null" : controller.getLayer())); 3095 }, false /* traverseTopToBottom */); 3096 } 3097 3098 final ScreenRotationAnimation screenRotationAnimation = 3099 mService.mAnimator.getScreenRotationAnimationLocked(DEFAULT_DISPLAY); 3100 final boolean inRotation = screenRotationAnimation != null && 3101 screenRotationAnimation.isAnimating(); 3102 if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG_WM, 3103 "Taking screenshot while rotating"); 3104 3105 // We force pending transactions to flush before taking 3106 // the screenshot by pushing an empty synchronous transaction. 3107 SurfaceControl.openTransaction(); 3108 SurfaceControl.closeTransactionSync(); 3109 3110 bitmap = screenshoter.screenshot(crop, width, height, minLayer, maxLayer, 3111 inRotation, rot); 3112 if (bitmap == null) { 3113 Slog.w(TAG_WM, "Screenshot failure taking screenshot for (" + dw + "x" + dh 3114 + ") to layer " + maxLayer); 3115 return null; 3116 } 3117 } 3118 return bitmap; 3119 } 3120 3121 // TODO: Can this use createRotationMatrix()? 3122 private static void convertCropForSurfaceFlinger(Rect crop, int rot, int dw, int dh) { 3123 if (rot == Surface.ROTATION_90) { 3124 final int tmp = crop.top; 3125 crop.top = dw - crop.right; 3126 crop.right = crop.bottom; 3127 crop.bottom = dw - crop.left; 3128 crop.left = tmp; 3129 } else if (rot == Surface.ROTATION_180) { 3130 int tmp = crop.top; 3131 crop.top = dh - crop.bottom; 3132 crop.bottom = dh - tmp; 3133 tmp = crop.right; 3134 crop.right = dw - crop.left; 3135 crop.left = dw - tmp; 3136 } else if (rot == Surface.ROTATION_270) { 3137 final int tmp = crop.top; 3138 crop.top = crop.left; 3139 crop.left = dh - crop.bottom; 3140 crop.bottom = crop.right; 3141 crop.right = dh - tmp; 3142 } 3143 } 3144 3145 void onSeamlessRotationTimeout() { 3146 // Used to indicate the layout is needed. 3147 mTmpWindow = null; 3148 3149 forAllWindows(w -> { 3150 if (!w.mSeamlesslyRotated) { 3151 return; 3152 } 3153 mTmpWindow = w; 3154 w.setDisplayLayoutNeeded(); 3155 mService.markForSeamlessRotation(w, false); 3156 }, true /* traverseTopToBottom */); 3157 3158 if (mTmpWindow != null) { 3159 mService.mWindowPlacerLocked.performSurfacePlacement(); 3160 } 3161 } 3162 3163 void setExitingTokensHasVisible(boolean hasVisible) { 3164 for (int i = mExitingTokens.size() - 1; i >= 0; i--) { 3165 mExitingTokens.get(i).hasVisible = hasVisible; 3166 } 3167 3168 // Initialize state of exiting applications. 3169 mTaskStackContainers.setExitingTokensHasVisible(hasVisible); 3170 } 3171 3172 void removeExistingTokensIfPossible() { 3173 for (int i = mExitingTokens.size() - 1; i >= 0; i--) { 3174 final WindowToken token = mExitingTokens.get(i); 3175 if (!token.hasVisible) { 3176 mExitingTokens.remove(i); 3177 } 3178 } 3179 3180 // Time to remove any exiting applications? 3181 mTaskStackContainers.removeExistingAppTokensIfPossible(); 3182 } 3183 3184 @Override 3185 void onDescendantOverrideConfigurationChanged() { 3186 setLayoutNeeded(); 3187 mService.requestTraversal(); 3188 } 3189 3190 static final class TaskForResizePointSearchResult { 3191 boolean searchDone; 3192 Task taskForResize; 3193 3194 void reset() { 3195 searchDone = false; 3196 taskForResize = null; 3197 } 3198 } 3199 3200 private static final class ApplySurfaceChangesTransactionState { 3201 boolean displayHasContent; 3202 boolean obscured; 3203 boolean syswin; 3204 boolean focusDisplayed; 3205 float preferredRefreshRate; 3206 int preferredModeId; 3207 3208 void reset() { 3209 displayHasContent = false; 3210 obscured = false; 3211 syswin = false; 3212 focusDisplayed = false; 3213 preferredRefreshRate = 0; 3214 preferredModeId = 0; 3215 } 3216 } 3217 3218 private static final class ScreenshotApplicationState { 3219 WindowState appWin; 3220 int maxLayer; 3221 int minLayer; 3222 boolean screenshotReady; 3223 3224 void reset(boolean screenshotReady) { 3225 appWin = null; 3226 maxLayer = 0; 3227 minLayer = 0; 3228 this.screenshotReady = screenshotReady; 3229 minLayer = (screenshotReady) ? 0 : Integer.MAX_VALUE; 3230 } 3231 } 3232 3233 /** 3234 * Base class for any direct child window container of {@link #DisplayContent} need to inherit 3235 * from. This is mainly a pass through class that allows {@link #DisplayContent} to have 3236 * homogeneous children type which is currently required by sub-classes of 3237 * {@link WindowContainer} class. 3238 */ 3239 static class DisplayChildWindowContainer<E extends WindowContainer> extends WindowContainer<E> { 3240 3241 int size() { 3242 return mChildren.size(); 3243 } 3244 3245 E get(int index) { 3246 return mChildren.get(index); 3247 } 3248 3249 @Override 3250 boolean fillsParent() { 3251 return true; 3252 } 3253 3254 @Override 3255 boolean isVisible() { 3256 return true; 3257 } 3258 } 3259 3260 /** 3261 * Window container class that contains all containers on this display relating to Apps. 3262 * I.e Activities. 3263 */ 3264 private final class TaskStackContainers extends DisplayChildWindowContainer<TaskStack> { 3265 3266 /** 3267 * Adds the stack to this container. 3268 * @see WindowManagerService#addStackToDisplay(int, int, boolean) 3269 */ 3270 void addStackToDisplay(TaskStack stack, boolean onTop) { 3271 if (stack.mStackId == HOME_STACK_ID) { 3272 if (mHomeStack != null) { 3273 throw new IllegalArgumentException("attachStack: HOME_STACK_ID (0) not first."); 3274 } 3275 mHomeStack = stack; 3276 } 3277 addChild(stack, onTop); 3278 stack.onDisplayChanged(DisplayContent.this); 3279 } 3280 3281 /** Removes the stack from its container and prepare for changing the parent. */ 3282 void removeStackFromDisplay(TaskStack stack) { 3283 removeChild(stack); 3284 stack.onRemovedFromDisplay(); 3285 } 3286 3287 private void addChild(TaskStack stack, boolean toTop) { 3288 final int addIndex = findPositionForStack(toTop ? mChildren.size() : 0, stack, 3289 true /* adding */); 3290 addChild(stack, addIndex); 3291 setLayoutNeeded(); 3292 } 3293 3294 @Override 3295 void positionChildAt(int position, TaskStack child, boolean includingParents) { 3296 if (StackId.isAlwaysOnTop(child.mStackId) && position != POSITION_TOP) { 3297 // This stack is always-on-top, override the default behavior. 3298 Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + this + " to bottom"); 3299 3300 // Moving to its current position, as we must call super but we don't want to 3301 // perform any meaningful action. 3302 final int currentPosition = mChildren.indexOf(child); 3303 super.positionChildAt(currentPosition, child, false /* includingParents */); 3304 return; 3305 } 3306 3307 final int targetPosition = findPositionForStack(position, child, false /* adding */); 3308 super.positionChildAt(targetPosition, child, includingParents); 3309 3310 setLayoutNeeded(); 3311 } 3312 3313 /** 3314 * When stack is added or repositioned, find a proper position for it. 3315 * This will make sure that pinned stack always stays on top. 3316 * @param requestedPosition Position requested by caller. 3317 * @param stack Stack to be added or positioned. 3318 * @param adding Flag indicates whether we're adding a new stack or positioning an existing. 3319 * @return The proper position for the stack. 3320 */ 3321 private int findPositionForStack(int requestedPosition, TaskStack stack, boolean adding) { 3322 final int topChildPosition = mChildren.size() - 1; 3323 boolean toTop = requestedPosition == POSITION_TOP; 3324 toTop |= adding ? requestedPosition >= topChildPosition + 1 3325 : requestedPosition >= topChildPosition; 3326 int targetPosition = requestedPosition; 3327 3328 if (toTop && stack.mStackId != PINNED_STACK_ID 3329 && getStackById(PINNED_STACK_ID) != null) { 3330 // The pinned stack is always the top most stack (always-on-top) when it is present. 3331 TaskStack topStack = mChildren.get(topChildPosition); 3332 if (topStack.mStackId != PINNED_STACK_ID) { 3333 throw new IllegalStateException("Pinned stack isn't top stack??? " + mChildren); 3334 } 3335 3336 // So, stack is moved just below the pinned stack. 3337 // When we're adding a new stack the target is the current pinned stack position. 3338 // When we're positioning an existing stack the target is the position below pinned 3339 // stack, because WindowContainer#positionAt() first removes element and then adds 3340 // it to specified place. 3341 targetPosition = adding ? topChildPosition : topChildPosition - 1; 3342 } 3343 3344 return targetPosition; 3345 } 3346 3347 @Override 3348 boolean forAllWindows(ToBooleanFunction<WindowState> callback, 3349 boolean traverseTopToBottom) { 3350 if (traverseTopToBottom) { 3351 if (super.forAllWindows(callback, traverseTopToBottom)) { 3352 return true; 3353 } 3354 if (forAllExitingAppTokenWindows(callback, traverseTopToBottom)) { 3355 return true; 3356 } 3357 } else { 3358 if (forAllExitingAppTokenWindows(callback, traverseTopToBottom)) { 3359 return true; 3360 } 3361 if (super.forAllWindows(callback, traverseTopToBottom)) { 3362 return true; 3363 } 3364 } 3365 return false; 3366 } 3367 3368 private boolean forAllExitingAppTokenWindows(ToBooleanFunction<WindowState> callback, 3369 boolean traverseTopToBottom) { 3370 // For legacy reasons we process the TaskStack.mExitingAppTokens first here before the 3371 // app tokens. 3372 // TODO: Investigate if we need to continue to do this or if we can just process them 3373 // in-order. 3374 if (traverseTopToBottom) { 3375 for (int i = mChildren.size() - 1; i >= 0; --i) { 3376 final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens; 3377 for (int j = appTokens.size() - 1; j >= 0; --j) { 3378 if (appTokens.get(j).forAllWindowsUnchecked(callback, 3379 traverseTopToBottom)) { 3380 return true; 3381 } 3382 } 3383 } 3384 } else { 3385 final int count = mChildren.size(); 3386 for (int i = 0; i < count; ++i) { 3387 final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens; 3388 final int appTokensCount = appTokens.size(); 3389 for (int j = 0; j < appTokensCount; j++) { 3390 if (appTokens.get(j).forAllWindowsUnchecked(callback, 3391 traverseTopToBottom)) { 3392 return true; 3393 } 3394 } 3395 } 3396 } 3397 return false; 3398 } 3399 3400 void setExitingTokensHasVisible(boolean hasVisible) { 3401 for (int i = mChildren.size() - 1; i >= 0; --i) { 3402 final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens; 3403 for (int j = appTokens.size() - 1; j >= 0; --j) { 3404 appTokens.get(j).hasVisible = hasVisible; 3405 } 3406 } 3407 } 3408 3409 void removeExistingAppTokensIfPossible() { 3410 for (int i = mChildren.size() - 1; i >= 0; --i) { 3411 final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens; 3412 for (int j = appTokens.size() - 1; j >= 0; --j) { 3413 final AppWindowToken token = appTokens.get(j); 3414 if (!token.hasVisible && !mService.mClosingApps.contains(token) 3415 && (!token.mIsExiting || token.isEmpty())) { 3416 // Make sure there is no animation running on this token, so any windows 3417 // associated with it will be removed as soon as their animations are 3418 // complete. 3419 token.mAppAnimator.clearAnimation(); 3420 token.mAppAnimator.animating = false; 3421 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 3422 "performLayout: App token exiting now removed" + token); 3423 token.removeIfPossible(); 3424 } 3425 } 3426 } 3427 } 3428 3429 @Override 3430 int getOrientation() { 3431 if (isStackVisible(DOCKED_STACK_ID) || isStackVisible(FREEFORM_WORKSPACE_STACK_ID)) { 3432 // Apps and their containers are not allowed to specify an orientation while the 3433 // docked or freeform stack is visible...except for the home stack/task if the 3434 // docked stack is minimized and it actually set something. 3435 if (mHomeStack != null && mHomeStack.isVisible() 3436 && mDividerControllerLocked.isMinimizedDock()) { 3437 final int orientation = mHomeStack.getOrientation(); 3438 if (orientation != SCREEN_ORIENTATION_UNSET) { 3439 return orientation; 3440 } 3441 } 3442 return SCREEN_ORIENTATION_UNSPECIFIED; 3443 } 3444 3445 final int orientation = super.getOrientation(); 3446 if (orientation != SCREEN_ORIENTATION_UNSET 3447 && orientation != SCREEN_ORIENTATION_BEHIND) { 3448 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, 3449 "App is requesting an orientation, return " + orientation); 3450 return orientation; 3451 } 3452 3453 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, 3454 "No app is requesting an orientation, return " + mLastOrientation); 3455 // The next app has not been requested to be visible, so we keep the current orientation 3456 // to prevent freezing/unfreezing the display too early. 3457 return mLastOrientation; 3458 } 3459 } 3460 3461 /** 3462 * Window container class that contains all containers on this display that are not related to 3463 * Apps. E.g. status bar. 3464 */ 3465 private final class NonAppWindowContainers extends DisplayChildWindowContainer<WindowToken> { 3466 /** 3467 * Compares two child window tokens returns -1 if the first is lesser than the second in 3468 * terms of z-order and 1 otherwise. 3469 */ 3470 private final Comparator<WindowToken> mWindowComparator = (token1, token2) -> 3471 // Tokens with higher base layer are z-ordered on-top. 3472 mService.mPolicy.getWindowLayerFromTypeLw(token1.windowType, 3473 token1.mOwnerCanManageAppTokens) 3474 < mService.mPolicy.getWindowLayerFromTypeLw(token2.windowType, 3475 token2.mOwnerCanManageAppTokens) ? -1 : 1; 3476 3477 private final Predicate<WindowState> mGetOrientingWindow = w -> { 3478 if (!w.isVisibleLw() || !w.mPolicyVisibilityAfterAnim) { 3479 return false; 3480 } 3481 final int req = w.mAttrs.screenOrientation; 3482 if(req == SCREEN_ORIENTATION_UNSPECIFIED || req == SCREEN_ORIENTATION_BEHIND 3483 || req == SCREEN_ORIENTATION_UNSET) { 3484 return false; 3485 } 3486 return true; 3487 }; 3488 3489 private final String mName; 3490 NonAppWindowContainers(String name) { 3491 mName = name; 3492 } 3493 3494 void addChild(WindowToken token) { 3495 addChild(token, mWindowComparator); 3496 } 3497 3498 @Override 3499 int getOrientation() { 3500 final WindowManagerPolicy policy = mService.mPolicy; 3501 // Find a window requesting orientation. 3502 final WindowState win = getWindow(mGetOrientingWindow); 3503 3504 if (win != null) { 3505 final int req = win.mAttrs.screenOrientation; 3506 if (policy.isKeyguardHostWindow(win.mAttrs)) { 3507 mLastKeyguardForcedOrientation = req; 3508 if (mService.mKeyguardGoingAway) { 3509 // Keyguard can't affect the orientation if it is going away... 3510 mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED; 3511 return SCREEN_ORIENTATION_UNSET; 3512 } 3513 } 3514 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, win + " forcing orientation to " + req); 3515 return (mLastWindowForcedOrientation = req); 3516 } 3517 3518 mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED; 3519 3520 if (policy.isKeyguardShowingAndNotOccluded()) { 3521 return mLastKeyguardForcedOrientation; 3522 } 3523 3524 return SCREEN_ORIENTATION_UNSET; 3525 } 3526 3527 @Override 3528 String getName() { 3529 return mName; 3530 } 3531 } 3532 3533 /** 3534 * Interface to screenshot into various types, i.e. {@link Bitmap} and {@link GraphicBuffer}. 3535 */ 3536 @FunctionalInterface 3537 private interface Screenshoter<E> { 3538 E screenshot(Rect sourceCrop, int width, int height, int minLayer, int maxLayer, 3539 boolean useIdentityTransform, int rotation); 3540 } 3541 } 3542