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 */ 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 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 807 int getDisplayId() { 808 return mDisplayId; 809 } 810 811 WindowToken getWindowToken(IBinder binder) { 812 return mTokenMap.get(binder); 813 } 814 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 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 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. */ 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 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 903 Display getDisplay() { 904 return mDisplay; 905 } 906 907 DisplayInfo getDisplayInfo() { 908 return mDisplayInfo; 909 } 910 911 DisplayMetrics getDisplayMetrics() { 912 return mDisplayMetrics; 913 } 914 915 int getRotation() { 916 return mRotation; 917 } 918 919 @VisibleForTesting 920 void setRotation(int newRotation) { 921 mRotation = newRotation; 922 } 923 924 int getLastOrientation() { 925 return mLastOrientation; 926 } 927 928 void setLastOrientation(int orientation) { 929 mLastOrientation = orientation; 930 } 931 932 boolean getAltOrientation() { 933 return mAltOrientation; 934 } 935 936 void setAltOrientation(boolean altOrientation) { 937 mAltOrientation = altOrientation; 938 } 939 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 */ 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 */ 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 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 */ 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 1241 WmDisplayCutout calculateDisplayCutoutForRotation(int rotation) { 1242 return mDisplayCutoutCache.getOrCompute(mInitialDisplayCutout, rotation); 1243 } 1244 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 */ 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 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 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 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 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 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 1504 DockedStackDividerController getDockedDividerController() { 1505 return mDividerControllerLocked; 1506 } 1507 1508 PinnedStackController getPinnedStackController() { 1509 return mPinnedStackControllerLocked; 1510 } 1511 1512 /** 1513 * Returns true if the specified UID has access to this display. 1514 */ 1515 boolean hasAccess(int uid) { 1516 return mDisplay.hasAccess(uid); 1517 } 1518 1519 boolean isPrivate() { 1520 return (mDisplay.getFlags() & FLAG_PRIVATE) != 0; 1521 } 1522 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 */ 1530 TaskStack getSplitScreenPrimaryStack() { 1531 TaskStack stack = mTaskStackContainers.getSplitScreenPrimaryStack(); 1532 return (stack != null && stack.isVisible()) ? stack : null; 1533 } 1534 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 */ 1543 TaskStack getSplitScreenPrimaryStackIgnoringVisibility() { 1544 return mTaskStackContainers.getSplitScreenPrimaryStack(); 1545 } 1546 1547 TaskStack getPinnedStack() { 1548 return mTaskStackContainers.getPinnedStack(); 1549 } 1550 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 */ 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 */ 1567 TaskStack getStack(int windowingMode, int activityType) { 1568 return mTaskStackContainers.getStack(windowingMode, activityType); 1569 } 1570 1571 @VisibleForTesting 1572 TaskStack getTopStack() { 1573 return mTaskStackContainers.getTopStack(); 1574 } 1575 1576 ArrayList<Task> getVisibleTasks() { 1577 return mTaskStackContainers.getVisibleTasks(); 1578 } 1579 1580 void onStackWindowingModeChanged(TaskStack stack) { 1581 mTaskStackContainers.onStackWindowingModeChanged(stack); 1582 } 1583 1584 @Override 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 */ 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 1627 boolean fillsParent() { 1628 return true; 1629 } 1630 1631 @Override 1632 boolean isVisible() { 1633 return true; 1634 } 1635 1636 @Override 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 */ 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 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 1685 boolean forAllImeWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) { 1686 return mImeWindowsContainers.forAllWindows(callback, traverseTopToBottom); 1687 } 1688 1689 @Override 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 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 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 */ 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 */ 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. */ 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 1827 void getStableRect(Rect out) { 1828 out.set(mDisplayFrames.mStable); 1829 } 1830 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 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 1856 protected void addChild(DisplayChildWindowContainer child, 1857 Comparator<DisplayChildWindowContainer> comparator) { 1858 throw new UnsupportedOperationException("See DisplayChildWindowContainer"); 1859 } 1860 1861 @Override 1862 protected void addChild(DisplayChildWindowContainer child, int index) { 1863 throw new UnsupportedOperationException("See DisplayChildWindowContainer"); 1864 } 1865 1866 @Override 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 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 1884 void positionStackAt(int position, TaskStack child) { 1885 mTaskStackContainers.positionChildAt(position, child, false /* includingParents */); 1886 layoutAndAssignWindowLayersIfNeeded(); 1887 } 1888 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 */ 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 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 1977 void switchUser() { 1978 super.switchUser(); 1979 mService.mWindowsChanged = true; 1980 } 1981 1982 private void resetAnimationBackgroundAnimator() { 1983 for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) { 1984 mTaskStackContainers.getChildAt(stackNdx).resetAnimationBackgroundAnimator(); 1985 } 1986 } 1987 1988 @Override 1989 void removeIfPossible() { 1990 if (isAnimating()) { 1991 mDeferredRemoval = true; 1992 return; 1993 } 1994 removeImmediately(); 1995 } 1996 1997 @Override 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 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. */ 2032 boolean isRemovalDeferred() { 2033 return mDeferredRemoval; 2034 } 2035 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 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 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 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 */ 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 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 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 2168 static int deltaRotation(int oldRotation, int newRotation) { 2169 int delta = newRotation - oldRotation; 2170 if (delta < 0) delta += 4; 2171 return delta; 2172 } 2173 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 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 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 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 2320 public String toString() { 2321 return "Display " + mDisplayId + " info=" + mDisplayInfo + " stacks=" + mChildren; 2322 } 2323 2324 String getName() { 2325 return "Display " + mDisplayId + " name=\"" + mDisplayInfo.name + "\""; 2326 } 2327 2328 /** Returns true if the stack in the windowing mode is visible. */ 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 */ 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 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 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 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. */ 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. 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 */ 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 */ 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 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 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 2618 void setLayoutNeeded() { 2619 if (DEBUG_LAYOUT) Slog.w(TAG_WM, "setLayoutNeeded: callers=" + Debug.getCallers(3)); 2620 mLayoutNeeded = true; 2621 } 2622 2623 private void clearLayoutNeeded() { 2624 if (DEBUG_LAYOUT) Slog.w(TAG_WM, "clearLayoutNeeded: callers=" + Debug.getCallers(3)); 2625 mLayoutNeeded = false; 2626 } 2627 2628 boolean isLayoutNeeded() { 2629 return mLayoutNeeded; 2630 } 2631 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 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 */ 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 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 2735 void updateWindowsForAnimator(WindowAnimator animator) { 2736 mTmpWindowAnimator = animator; 2737 forAllWindows(mUpdateWindowsForAnimator, true /* traverseTopToBottom */); 2738 } 2739 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 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 2782 boolean hasSecureWindowOnScreen() { 2783 final WindowState win = getWindow( 2784 w -> w.isOnScreen() && (w.mAttrs.flags & FLAG_SECURE) != 0); 2785 return win != null; 2786 } 2787 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 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 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... 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 2925 private void updateBounds() { 2926 calculateBounds(mTmpBounds); 2927 setBounds(mTmpBounds); 2928 } 2929 2930 // Determines the current display bounds based on the current state 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 2945 public void getBounds(Rect out) { 2946 calculateBounds(out); 2947 } 2948 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 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 */ 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()? 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 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 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 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 3140 void onDescendantOverrideConfigurationChanged() { 3141 setLayoutNeeded(); 3142 mService.requestTraversal(); 3143 } 3144 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 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 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 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 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 3209 DisplayChildWindowContainer(WindowManagerService service) { 3210 super(service); 3211 } 3212 3213 @Override 3214 boolean fillsParent() { 3215 return true; 3216 } 3217 3218 @Override 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 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 */ 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 3290 TaskStack getTopStack() { 3291 return mTaskStackContainers.getChildCount() > 0 3292 ? mTaskStackContainers.getChildAt(mTaskStackContainers.getChildCount() - 1) : null; 3293 } 3294 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 3302 TaskStack getPinnedStack() { 3303 return mPinnedStack; 3304 } 3305 3306 TaskStack getSplitScreenPrimaryStack() { 3307 return mSplitScreenPrimaryStack; 3308 } 3309 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 */ 3324 void addStackToDisplay(TaskStack stack, boolean onTop) { 3325 addStackReferenceIfNeeded(stack); 3326 addChild(stack, onTop); 3327 stack.onDisplayChanged(DisplayContent.this); 3328 } 3329 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 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 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 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 3388 protected void removeChild(TaskStack stack) { 3389 super.removeChild(stack); 3390 removeStackReferenceIfNeeded(stack); 3391 } 3392 3393 @Override 3394 boolean isOnTop() { 3395 // Considered always on top 3396 return true; 3397 } 3398 3399 @Override 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 */ 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 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 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 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 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 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 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 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 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 3659 SurfaceControl getSplitScreenDividerAnchor() { 3660 return mSplitScreenDividerAnchor; 3661 } 3662 3663 @Override 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 { 3699 AboveAppWindowContainers(String name, WindowManagerService service) { 3700 super(name, service); 3701 } 3702 3703 @Override 3704 void assignChildLayers(SurfaceControl.Transaction t) { 3705 assignChildLayers(t, null /* imeContainer */); 3706 } 3707 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 3769 NonAppWindowContainers(String name, WindowManagerService service) { 3770 super(service); 3771 mName = name; 3772 } 3773 3774 void addChild(WindowToken token) { 3775 addChild(token, mWindowComparator); 3776 } 3777 3778 @Override 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 3814 String getName() { 3815 return mName; 3816 } 3817 3818 @Override 3819 Dimmer getDimmer() { 3820 return mDimmer; 3821 } 3822 3823 @Override 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 { 3836 NonMagnifiableWindowContainers(String name, WindowManagerService service) { 3837 super(name, service); 3838 } 3839 3840 @Override 3841 void applyMagnificationSpec(Transaction t, MagnificationSpec spec) { 3842 } 3843 }; 3844 3845 SurfaceControl.Builder makeSurface(SurfaceSession s) { 3846 return mService.makeSurfaceBuilder(s) 3847 .setParent(mWindowingLayer); 3848 } 3849 3850 @Override 3851 SurfaceSession getSession() { 3852 return mSession; 3853 } 3854 3855 @Override 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 */ 3875 SurfaceControl.Builder makeOverlay() { 3876 return mService.makeSurfaceBuilder(mSession) 3877 .setParent(mOverlayLayer); 3878 } 3879 3880 /** 3881 * Reparents the given surface to mOverlayLayer. 3882 */ 3883 void reparentToOverlay(Transaction transaction, SurfaceControl surface) { 3884 transaction.reparent(surface, mOverlayLayer.getHandle()); 3885 } 3886 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 3898 void reapplyMagnificationSpec() { 3899 if (mMagnificationSpec != null) { 3900 applyMagnificationSpec(getPendingTransaction(), mMagnificationSpec); 3901 } 3902 } 3903 3904 @Override 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 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 */ 3968 void assignRelativeLayerForImeTargetChild(SurfaceControl.Transaction t, WindowContainer child) { 3969 child.assignRelativeLayer(t, mImeWindowsContainers.getSurfaceControl(), 1); 3970 } 3971 3972 @Override 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 3990 void assignStackOrdering() { 3991 mTaskStackContainers.assignStackOrdering(getPendingTransaction()); 3992 } 3993 3994 /** 3995 * Increment the deferral count to determine whether to update the IME target. 3996 */ 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 */ 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 */ 4019 private boolean canUpdateImeTarget() { 4020 return mDeferUpdateImeTargetCount == 0; 4021 } 4022 } 4023