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