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 */ DisplayContent(Display display, WindowManagerService service, WindowLayersController layersController, WallpaperController wallpaperController)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 isReady()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 getDisplayId()764 int getDisplayId() { 765 return mDisplayId; 766 } 767 getWindowToken(IBinder binder)768 WindowToken getWindowToken(IBinder binder) { 769 return mTokenMap.get(binder); 770 } 771 getAppWindowToken(IBinder binder)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 addWindowToken(IBinder binder, WindowToken token)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 removeWindowToken(IBinder binder)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. */ reParentWindowToken(WindowToken token)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 removeAppToken(IBinder binder)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 getDisplay()860 Display getDisplay() { 861 return mDisplay; 862 } 863 getDisplayInfo()864 DisplayInfo getDisplayInfo() { 865 return mDisplayInfo; 866 } 867 getDisplayMetrics()868 DisplayMetrics getDisplayMetrics() { 869 return mDisplayMetrics; 870 } 871 getRotation()872 int getRotation() { 873 return mRotation; 874 } 875 setRotation(int newRotation)876 void setRotation(int newRotation) { 877 mRotation = newRotation; 878 } 879 getLastOrientation()880 int getLastOrientation() { 881 return mLastOrientation; 882 } 883 setLastOrientation(int orientation)884 void setLastOrientation(int orientation) { 885 mLastOrientation = orientation; 886 } 887 getAltOrientation()888 boolean getAltOrientation() { 889 return mAltOrientation; 890 } 891 setAltOrientation(boolean altOrientation)892 void setAltOrientation(boolean altOrientation) { 893 mAltOrientation = altOrientation; 894 } 895 getLastWindowForcedOrientation()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 */ updateRotationUnchecked(boolean inTransaction)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 */ updateDisplayAndOrientation(int uiMode)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 */ computeScreenConfiguration(Configuration config)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 computeCompatSmallestWidth(boolean rotated, int uiMode, int dw, int dh, int displayId)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 reduceCompatConfigWidthSize(int curSize, int rotation, int uiMode, DisplayMetrics dm, int dw, int dh, int displayId)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 computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, int displayId, boolean rotated, int uiMode, int dw, int dh, float density, Configuration outConfig)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 reduceConfigLayout(int curLayout, int rotation, float density, int dw, int dh, int uiMode, int displayId)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 adjustDisplaySizeRanges(DisplayInfo displayInfo, int displayId, int rotation, int uiMode, int dw, int dh)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 getDockedDividerController()1395 DockedStackDividerController getDockedDividerController() { 1396 return mDividerControllerLocked; 1397 } 1398 getPinnedStackController()1399 PinnedStackController getPinnedStackController() { 1400 return mPinnedStackControllerLocked; 1401 } 1402 1403 /** 1404 * Returns true if the specified UID has access to this display. 1405 */ hasAccess(int uid)1406 boolean hasAccess(int uid) { 1407 return mDisplay.hasAccess(uid); 1408 } 1409 isPrivate()1410 boolean isPrivate() { 1411 return (mDisplay.getFlags() & FLAG_PRIVATE) != 0; 1412 } 1413 getHomeStack()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 getStackById(int stackId)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 getStackCount()1432 int getStackCount() { 1433 return mTaskStackContainers.size(); 1434 } 1435 1436 @VisibleForTesting getStaskPosById(int stackId)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 onConfigurationChanged(Configuration newParentConfig)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 */ updateStackBoundsAfterConfigChange(@onNull List<Integer> changedStackList)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 fillsParent()1481 boolean fillsParent() { 1482 return true; 1483 } 1484 1485 @Override isVisible()1486 boolean isVisible() { 1487 return true; 1488 } 1489 1490 @Override onAppTransitionDone()1491 void onAppTransitionDone() { 1492 super.onAppTransitionDone(); 1493 mService.mWindowsChanged = true; 1494 } 1495 1496 @Override forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)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 forAllImeWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)1529 boolean forAllImeWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) { 1530 return mImeWindowsContainers.forAllWindows(callback, traverseTopToBottom); 1531 } 1532 1533 @Override getOrientation()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 updateDisplayInfo()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 initializeDisplayBaseInfo()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 getLogicalDisplayRect(Rect out)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 getLogicalDisplayRect(Rect out, int orientation)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 */ updateBaseDisplayMetricsIfNeeded()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 */ setMaxUiWidth(int width)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. */ updateBaseDisplayMetrics(int baseWidth, int baseHeight, int baseDensity)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 getContentRect(Rect out)1692 void getContentRect(Rect out) { 1693 out.set(mContentRect); 1694 } 1695 addStackToDisplay(int stackId, boolean onTop)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 moveStackToDisplay(TaskStack stack, boolean onTop)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 addChild(DisplayChildWindowContainer child, Comparator<DisplayChildWindowContainer> comparator)1736 protected void addChild(DisplayChildWindowContainer child, 1737 Comparator<DisplayChildWindowContainer> comparator) { 1738 throw new UnsupportedOperationException("See DisplayChildWindowContainer"); 1739 } 1740 1741 @Override addChild(DisplayChildWindowContainer child, int index)1742 protected void addChild(DisplayChildWindowContainer child, int index) { 1743 throw new UnsupportedOperationException("See DisplayChildWindowContainer"); 1744 } 1745 1746 @Override removeChild(DisplayChildWindowContainer child)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 positionChildAt(int position, DisplayChildWindowContainer child, boolean includingParents)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 taskIdFromPoint(int x, int y)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 */ findTaskForResizePoint(int x, int y)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 setTouchExcludeRegion(Task focusedTask)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 switchUser()1848 void switchUser() { 1849 super.switchUser(); 1850 mService.mWindowsChanged = true; 1851 } 1852 resetAnimationBackgroundAnimator()1853 private void resetAnimationBackgroundAnimator() { 1854 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) { 1855 mTaskStackContainers.get(stackNdx).resetAnimationBackgroundAnimator(); 1856 } 1857 } 1858 animateDimLayers()1859 boolean animateDimLayers() { 1860 return mDimLayerController.animateDimLayers(); 1861 } 1862 resetDimming()1863 private void resetDimming() { 1864 mDimLayerController.resetDimming(); 1865 } 1866 isDimming()1867 boolean isDimming() { 1868 return mDimLayerController.isDimming(); 1869 } 1870 stopDimmingIfNeeded()1871 private void stopDimmingIfNeeded() { 1872 mDimLayerController.stopDimmingIfNeeded(); 1873 } 1874 1875 @Override removeIfPossible()1876 void removeIfPossible() { 1877 if (isAnimating()) { 1878 mDeferredRemoval = true; 1879 return; 1880 } 1881 removeImmediately(); 1882 } 1883 1884 @Override removeImmediately()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 checkCompleteDeferredRemoval()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. */ isRemovalDeferred()1914 boolean isRemovalDeferred() { 1915 return mDeferredRemoval; 1916 } 1917 animateForIme(float interpolatedValue, float animationTarget, float dividerAnimationTarget)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 clearImeAdjustAnimation()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 beginImeAdjustAnimation()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 adjustForImeIfNeeded()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 setInputMethodAnimLayerAdjustment(int adj)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 */ getLayerForAnimationBackground(WindowStateAnimator winAnimator)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 prepareFreezingTaskBounds()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 rotateBounds(int oldRotation, int newRotation, Rect bounds)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 deltaRotation(int oldRotation, int newRotation)2056 static int deltaRotation(int oldRotation, int newRotation) { 2057 int delta = newRotation - oldRotation; 2058 if (delta < 0) delta += 4; 2059 return delta; 2060 } 2061 createRotationMatrix(int rotation, float displayWidth, float displayHeight, Matrix outMatrix)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 createRotationMatrix(int rotation, float rectLeft, float rectTop, float displayWidth, float displayHeight, Matrix outMatrix)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 dump(String prefix, PrintWriter pw)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 toString()2153 public String toString() { 2154 return "Display " + mDisplayId + " info=" + mDisplayInfo + " stacks=" + mChildren; 2155 } 2156 getName()2157 String getName() { 2158 return "Display " + mDisplayId + " name=\"" + mDisplayInfo.name + "\""; 2159 } 2160 2161 /** Checks if stack with provided id is visible on this display. */ isStackVisible(int stackId)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 */ getDockedStackLocked()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 */ getDockedStackIgnoringVisibility()2179 TaskStack getDockedStackIgnoringVisibility() { 2180 return getStackById(DOCKED_STACK_ID); 2181 } 2182 2183 /** Find the visible, touch-deliverable window under the given point */ getTouchableWinAtPointLocked(float xf, float yf)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 canAddToastWindowForUid(int uid)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 scheduleToastWindowsTimeoutIfNeededLocked(WindowState oldFocus, WindowState newFocus)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 findFocusedWindow()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. */ assignWindowLayers(boolean setLayoutNeeded)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. layoutAndAssignWindowLayersIfNeeded()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 */ destroyLeakedSurfaces()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 */ computeImeTarget(boolean updateImeTarget)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 setInputMethodTarget(WindowState target, boolean targetWaitingAnim, int layerAdj)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 getNeedsMenu(WindowState top, WindowManagerPolicy.WindowState bottom)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 setLayoutNeeded()2460 void setLayoutNeeded() { 2461 if (DEBUG_LAYOUT) Slog.w(TAG_WM, "setLayoutNeeded: callers=" + Debug.getCallers(3)); 2462 mLayoutNeeded = true; 2463 } 2464 clearLayoutNeeded()2465 private void clearLayoutNeeded() { 2466 if (DEBUG_LAYOUT) Slog.w(TAG_WM, "clearLayoutNeeded: callers=" + Debug.getCallers(3)); 2467 mLayoutNeeded = false; 2468 } 2469 isLayoutNeeded()2470 boolean isLayoutNeeded() { 2471 return mLayoutNeeded; 2472 } 2473 dumpTokens(PrintWriter pw, boolean dumpAll)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 dumpWindowAnimators(PrintWriter pw, String subPrefix)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 enableSurfaceTrace(FileDescriptor fd)2502 void enableSurfaceTrace(FileDescriptor fd) { 2503 forAllWindows(w -> { 2504 w.mWinAnimator.enableSurfaceTrace(fd); 2505 }, true /* traverseTopToBottom */); 2506 } 2507 disableSurfaceTrace()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 */ startKeyguardExitOnNonAppWindows(boolean onWallpaper, boolean goingToShade)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 checkWaitingForWindows()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 updateWindowsForAnimator(WindowAnimator animator)2588 void updateWindowsForAnimator(WindowAnimator animator) { 2589 mTmpWindowAnimator = animator; 2590 forAllWindows(mUpdateWindowsForAnimator, true /* traverseTopToBottom */); 2591 } 2592 updateWallpaperForAnimator(WindowAnimator animator)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 prepareWindowSurfaces()2610 void prepareWindowSurfaces() { 2611 forAllWindows(mPrepareWindowSurfaces, false /* traverseTopToBottom */); 2612 } 2613 inputMethodClientHasFocus(IInputMethodClient client)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 hasSecureWindowOnScreen()2639 boolean hasSecureWindowOnScreen() { 2640 final WindowState win = getWindow( 2641 w -> w.isOnScreen() && (w.mAttrs.flags & FLAG_SECURE) != 0); 2642 return win != null; 2643 } 2644 updateSystemUiVisibility(int visibility, int globalDiff)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 onWindowFreezeTimeout()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 waitForAllWindowsDrawn()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... applySurfaceChangesTransaction(boolean recoveringMemory)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 performLayout(boolean initial, boolean updateInputWindows)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 */ screenshotApplications(IBinder appToken, int width, int height, boolean includeFullDisplay, float frameScale, Bitmap.Config config, boolean wallpaperOnly, boolean includeDecor)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 screenshotApplicationsToBuffer(IBinder appToken, int width, int height, boolean includeFullDisplay, float frameScale, boolean wallpaperOnly, boolean includeDecor)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 screenshotApplications(IBinder appToken, int width, int height, boolean includeFullDisplay, float frameScale, boolean wallpaperOnly, boolean includeDecor, Screenshoter<E> screenshoter)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()? convertCropForSurfaceFlinger(Rect crop, int rot, int dw, int dh)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 onSeamlessRotationTimeout()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 setExitingTokensHasVisible(boolean hasVisible)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 removeExistingTokensIfPossible()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 onDescendantOverrideConfigurationChanged()3185 void onDescendantOverrideConfigurationChanged() { 3186 setLayoutNeeded(); 3187 mService.requestTraversal(); 3188 } 3189 3190 static final class TaskForResizePointSearchResult { 3191 boolean searchDone; 3192 Task taskForResize; 3193 reset()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 reset()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 reset(boolean screenshotReady)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 size()3241 int size() { 3242 return mChildren.size(); 3243 } 3244 get(int index)3245 E get(int index) { 3246 return mChildren.get(index); 3247 } 3248 3249 @Override fillsParent()3250 boolean fillsParent() { 3251 return true; 3252 } 3253 3254 @Override isVisible()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 */ addStackToDisplay(TaskStack stack, boolean onTop)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. */ removeStackFromDisplay(TaskStack stack)3282 void removeStackFromDisplay(TaskStack stack) { 3283 removeChild(stack); 3284 stack.onRemovedFromDisplay(); 3285 } 3286 addChild(TaskStack stack, boolean toTop)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 positionChildAt(int position, TaskStack child, boolean includingParents)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 */ findPositionForStack(int requestedPosition, TaskStack stack, boolean adding)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 forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)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 forAllExitingAppTokenWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)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 setExitingTokensHasVisible(boolean hasVisible)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 removeExistingAppTokensIfPossible()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 getOrientation()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; NonAppWindowContainers(String name)3490 NonAppWindowContainers(String name) { 3491 mName = name; 3492 } 3493 addChild(WindowToken token)3494 void addChild(WindowToken token) { 3495 addChild(token, mWindowComparator); 3496 } 3497 3498 @Override getOrientation()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 getName()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> { screenshot(Rect sourceCrop, int width, int height, int minLayer, int maxLayer, boolean useIdentityTransform, int rotation)3538 E screenshot(Rect sourceCrop, int width, int height, int minLayer, int maxLayer, 3539 boolean useIdentityTransform, int rotation); 3540 } 3541 } 3542