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