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