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