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