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 */ DisplayContent(Display display, WindowManagerService service, WindowLayersController layersController, WallpaperController wallpaperController)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 isReady()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 getDisplayId()775 int getDisplayId() { 776 return mDisplayId; 777 } 778 getWindowToken(IBinder binder)779 WindowToken getWindowToken(IBinder binder) { 780 return mTokenMap.get(binder); 781 } 782 getAppWindowToken(IBinder binder)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 addWindowToken(IBinder binder, WindowToken token)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 removeWindowToken(IBinder binder)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. */ reParentWindowToken(WindowToken token)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 removeAppToken(IBinder binder)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 getDisplay()871 Display getDisplay() { 872 return mDisplay; 873 } 874 getDisplayInfo()875 DisplayInfo getDisplayInfo() { 876 return mDisplayInfo; 877 } 878 getDisplayMetrics()879 DisplayMetrics getDisplayMetrics() { 880 return mDisplayMetrics; 881 } 882 getRotation()883 int getRotation() { 884 return mRotation; 885 } 886 setRotation(int newRotation)887 void setRotation(int newRotation) { 888 mRotation = newRotation; 889 } 890 getLastOrientation()891 int getLastOrientation() { 892 return mLastOrientation; 893 } 894 setLastOrientation(int orientation)895 void setLastOrientation(int orientation) { 896 mLastOrientation = orientation; 897 } 898 getAltOrientation()899 boolean getAltOrientation() { 900 return mAltOrientation; 901 } 902 setAltOrientation(boolean altOrientation)903 void setAltOrientation(boolean altOrientation) { 904 mAltOrientation = altOrientation; 905 } 906 getLastWindowForcedOrientation()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 */ updateRotationUnchecked(boolean inTransaction)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 */ updateDisplayAndOrientation(int uiMode)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 */ computeScreenConfiguration(Configuration config)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 computeCompatSmallestWidth(boolean rotated, int uiMode, int dw, int dh, int displayId)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 reduceCompatConfigWidthSize(int curSize, int rotation, int uiMode, DisplayMetrics dm, int dw, int dh, int displayId)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 computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, int displayId, boolean rotated, int uiMode, int dw, int dh, float density, Configuration outConfig)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 reduceConfigLayout(int curLayout, int rotation, float density, int dw, int dh, int uiMode, int displayId)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 adjustDisplaySizeRanges(DisplayInfo displayInfo, int displayId, int rotation, int uiMode, int dw, int dh)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 getDockedDividerController()1420 DockedStackDividerController getDockedDividerController() { 1421 return mDividerControllerLocked; 1422 } 1423 getPinnedStackController()1424 PinnedStackController getPinnedStackController() { 1425 return mPinnedStackControllerLocked; 1426 } 1427 1428 /** 1429 * Returns true if the specified UID has access to this display. 1430 */ hasAccess(int uid)1431 boolean hasAccess(int uid) { 1432 return mDisplay.hasAccess(uid); 1433 } 1434 isPrivate()1435 boolean isPrivate() { 1436 return (mDisplay.getFlags() & FLAG_PRIVATE) != 0; 1437 } 1438 getHomeStack()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 getStackById(int stackId)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 getStackCount()1457 int getStackCount() { 1458 return mTaskStackContainers.size(); 1459 } 1460 1461 @VisibleForTesting getStaskPosById(int stackId)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 onConfigurationChanged(Configuration newParentConfig)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 */ updateStackBoundsAfterConfigChange(@onNull List<Integer> changedStackList)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 fillsParent()1506 boolean fillsParent() { 1507 return true; 1508 } 1509 1510 @Override isVisible()1511 boolean isVisible() { 1512 return true; 1513 } 1514 1515 @Override onAppTransitionDone()1516 void onAppTransitionDone() { 1517 super.onAppTransitionDone(); 1518 mService.mWindowsChanged = true; 1519 } 1520 1521 @Override forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)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 forAllImeWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)1554 boolean forAllImeWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) { 1555 return mImeWindowsContainers.forAllWindows(callback, traverseTopToBottom); 1556 } 1557 1558 @Override getOrientation()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 updateDisplayInfo()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 initializeDisplayBaseInfo()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 getLogicalDisplayRect(Rect out)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 getLogicalDisplayRect(Rect out, int orientation)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 */ updateBaseDisplayMetricsIfNeeded()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 */ setMaxUiWidth(int width)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. */ updateBaseDisplayMetrics(int baseWidth, int baseHeight, int baseDensity)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 getContentRect(Rect out)1717 void getContentRect(Rect out) { 1718 out.set(mContentRect); 1719 } 1720 addStackToDisplay(int stackId, boolean onTop)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 moveStackToDisplay(TaskStack stack, boolean onTop)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 addChild(DisplayChildWindowContainer child, Comparator<DisplayChildWindowContainer> comparator)1761 protected void addChild(DisplayChildWindowContainer child, 1762 Comparator<DisplayChildWindowContainer> comparator) { 1763 throw new UnsupportedOperationException("See DisplayChildWindowContainer"); 1764 } 1765 1766 @Override addChild(DisplayChildWindowContainer child, int index)1767 protected void addChild(DisplayChildWindowContainer child, int index) { 1768 throw new UnsupportedOperationException("See DisplayChildWindowContainer"); 1769 } 1770 1771 @Override removeChild(DisplayChildWindowContainer child)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 positionChildAt(int position, DisplayChildWindowContainer child, boolean includingParents)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 taskIdFromPoint(int x, int y)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 */ findTaskForResizePoint(int x, int y)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 setTouchExcludeRegion(Task focusedTask)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 switchUser()1873 void switchUser() { 1874 super.switchUser(); 1875 mService.mWindowsChanged = true; 1876 } 1877 resetAnimationBackgroundAnimator()1878 private void resetAnimationBackgroundAnimator() { 1879 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) { 1880 mTaskStackContainers.get(stackNdx).resetAnimationBackgroundAnimator(); 1881 } 1882 } 1883 animateDimLayers()1884 boolean animateDimLayers() { 1885 return mDimLayerController.animateDimLayers(); 1886 } 1887 resetDimming()1888 private void resetDimming() { 1889 mDimLayerController.resetDimming(); 1890 } 1891 isDimming()1892 boolean isDimming() { 1893 return mDimLayerController.isDimming(); 1894 } 1895 stopDimmingIfNeeded()1896 private void stopDimmingIfNeeded() { 1897 mDimLayerController.stopDimmingIfNeeded(); 1898 } 1899 1900 @Override removeIfPossible()1901 void removeIfPossible() { 1902 if (isAnimating()) { 1903 mDeferredRemoval = true; 1904 return; 1905 } 1906 removeImmediately(); 1907 } 1908 1909 @Override removeImmediately()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 checkCompleteDeferredRemoval()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. */ isRemovalDeferred()1939 boolean isRemovalDeferred() { 1940 return mDeferredRemoval; 1941 } 1942 animateForIme(float interpolatedValue, float animationTarget, float dividerAnimationTarget)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 clearImeAdjustAnimation()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 beginImeAdjustAnimation()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 adjustForImeIfNeeded()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 setInputMethodAnimLayerAdjustment(int adj)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 */ getLayerForAnimationBackground(WindowStateAnimator winAnimator)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 prepareFreezingTaskBounds()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 rotateBounds(int oldRotation, int newRotation, Rect bounds)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 deltaRotation(int oldRotation, int newRotation)2081 static int deltaRotation(int oldRotation, int newRotation) { 2082 int delta = newRotation - oldRotation; 2083 if (delta < 0) delta += 4; 2084 return delta; 2085 } 2086 createRotationMatrix(int rotation, float displayWidth, float displayHeight, Matrix outMatrix)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 createRotationMatrix(int rotation, float rectLeft, float rectTop, float displayWidth, float displayHeight, Matrix outMatrix)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 dump(String prefix, PrintWriter pw)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 toString()2179 public String toString() { 2180 return "Display " + mDisplayId + " info=" + mDisplayInfo + " stacks=" + mChildren; 2181 } 2182 getName()2183 String getName() { 2184 return "Display " + mDisplayId + " name=\"" + mDisplayInfo.name + "\""; 2185 } 2186 2187 /** Checks if stack with provided id is visible on this display. */ isStackVisible(int stackId)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 */ getDockedStackLocked()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 */ getDockedStackIgnoringVisibility()2205 TaskStack getDockedStackIgnoringVisibility() { 2206 return getStackById(DOCKED_STACK_ID); 2207 } 2208 2209 /** Find the visible, touch-deliverable window under the given point */ getTouchableWinAtPointLocked(float xf, float yf)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 canAddToastWindowForUid(int uid)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 scheduleToastWindowsTimeoutIfNeededLocked(WindowState oldFocus, WindowState newFocus)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 findFocusedWindow()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. */ assignWindowLayers(boolean setLayoutNeeded)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. layoutAndAssignWindowLayersIfNeeded()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 */ destroyLeakedSurfaces()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 */ computeImeTarget(boolean updateImeTarget)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 setInputMethodTarget(WindowState target, boolean targetWaitingAnim, int layerAdj)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 getNeedsMenu(WindowState top, WindowManagerPolicy.WindowState bottom)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 setLayoutNeeded()2486 void setLayoutNeeded() { 2487 if (DEBUG_LAYOUT) Slog.w(TAG_WM, "setLayoutNeeded: callers=" + Debug.getCallers(3)); 2488 mLayoutNeeded = true; 2489 } 2490 clearLayoutNeeded()2491 private void clearLayoutNeeded() { 2492 if (DEBUG_LAYOUT) Slog.w(TAG_WM, "clearLayoutNeeded: callers=" + Debug.getCallers(3)); 2493 mLayoutNeeded = false; 2494 } 2495 isLayoutNeeded()2496 boolean isLayoutNeeded() { 2497 return mLayoutNeeded; 2498 } 2499 dumpTokens(PrintWriter pw, boolean dumpAll)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 dumpWindowAnimators(PrintWriter pw, String subPrefix)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 enableSurfaceTrace(FileDescriptor fd)2528 void enableSurfaceTrace(FileDescriptor fd) { 2529 forAllWindows(w -> { 2530 w.mWinAnimator.enableSurfaceTrace(fd); 2531 }, true /* traverseTopToBottom */); 2532 } 2533 disableSurfaceTrace()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 */ startKeyguardExitOnNonAppWindows(boolean onWallpaper, boolean goingToShade)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 checkWaitingForWindows()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 updateWindowsForAnimator(WindowAnimator animator)2614 void updateWindowsForAnimator(WindowAnimator animator) { 2615 mTmpWindowAnimator = animator; 2616 forAllWindows(mUpdateWindowsForAnimator, true /* traverseTopToBottom */); 2617 } 2618 updateWallpaperForAnimator(WindowAnimator animator)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 prepareWindowSurfaces()2636 void prepareWindowSurfaces() { 2637 forAllWindows(mPrepareWindowSurfaces, false /* traverseTopToBottom */); 2638 } 2639 inputMethodClientHasFocus(IInputMethodClient client)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 hasSecureWindowOnScreen()2665 boolean hasSecureWindowOnScreen() { 2666 final WindowState win = getWindow( 2667 w -> w.isOnScreen() && (w.mAttrs.flags & FLAG_SECURE) != 0); 2668 return win != null; 2669 } 2670 updateSystemUiVisibility(int visibility, int globalDiff)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 onWindowFreezeTimeout()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 waitForAllWindowsDrawn()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... applySurfaceChangesTransaction(boolean recoveringMemory)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 performLayout(boolean initial, boolean updateInputWindows)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 */ screenshotApplications(IBinder appToken, int width, int height, boolean includeFullDisplay, float frameScale, Bitmap.Config config, boolean wallpaperOnly, boolean includeDecor)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 screenshotApplicationsToBuffer(IBinder appToken, int width, int height, boolean includeFullDisplay, float frameScale, boolean wallpaperOnly, boolean includeDecor)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 screenshotApplications(IBinder appToken, int width, int height, boolean includeFullDisplay, float frameScale, boolean wallpaperOnly, boolean includeDecor, Screenshoter<E> screenshoter)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()? convertCropForSurfaceFlinger(Rect crop, int rot, int dw, int dh)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 onSeamlessRotationTimeout()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 setExitingTokensHasVisible(boolean hasVisible)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 removeExistingTokensIfPossible()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 onDescendantOverrideConfigurationChanged()3217 void onDescendantOverrideConfigurationChanged() { 3218 setLayoutNeeded(); 3219 mService.requestTraversal(); 3220 } 3221 okToDisplay()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 okToAnimate()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 reset()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 reset()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 reset(boolean screenshotReady)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 size()3286 int size() { 3287 return mChildren.size(); 3288 } 3289 get(int index)3290 E get(int index) { 3291 return mChildren.get(index); 3292 } 3293 3294 @Override fillsParent()3295 boolean fillsParent() { 3296 return true; 3297 } 3298 3299 @Override isVisible()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 */ addStackToDisplay(TaskStack stack, boolean onTop)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. */ removeStackFromDisplay(TaskStack stack)3327 void removeStackFromDisplay(TaskStack stack) { 3328 removeChild(stack); 3329 stack.onRemovedFromDisplay(); 3330 } 3331 addChild(TaskStack stack, boolean toTop)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 isOnTop()3341 boolean isOnTop() { 3342 // Considered always on top 3343 return true; 3344 } 3345 3346 @Override positionChildAt(int position, TaskStack child, boolean includingParents)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 */ findPositionForStack(int requestedPosition, TaskStack stack, boolean adding)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 forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)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 forAllExitingAppTokenWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)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 setExitingTokensHasVisible(boolean hasVisible)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 removeExistingAppTokensIfPossible()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 getOrientation()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; NonAppWindowContainers(String name)3542 NonAppWindowContainers(String name) { 3543 mName = name; 3544 } 3545 addChild(WindowToken token)3546 void addChild(WindowToken token) { 3547 addChild(token, mWindowComparator); 3548 } 3549 3550 @Override getOrientation()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 getName()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> { screenshot(Rect sourceCrop, int width, int height, int minLayer, int maxLayer, boolean useIdentityTransform, int rotation)3591 E screenshot(Rect sourceCrop, int width, int height, int minLayer, int maxLayer, 3592 boolean useIdentityTransform, int rotation); 3593 } 3594 } 3595