DisplayContent.java revision 02886a82d876aa5e31a92444fec70208599c509c
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_BOOT; 61import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY; 62import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS; 63import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT; 64import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD; 65import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS; 66import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT; 67import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS; 68import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION; 69import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT; 70import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREEN_ON; 71import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK; 72import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER; 73import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT; 74import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS; 75import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS; 76import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; 77import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 78import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION; 79import static com.android.server.wm.WindowManagerService.H.UPDATE_DOCKED_STACK_DIVIDER; 80import static com.android.server.wm.WindowManagerService.H.WINDOW_HIDE_TIMEOUT; 81import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD; 82import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER; 83import static com.android.server.wm.WindowManagerService.TYPE_LAYER_OFFSET; 84import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES; 85import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_TIMEOUT; 86import static com.android.server.wm.WindowManagerService.dipToPixel; 87import static com.android.server.wm.WindowManagerService.logSurface; 88import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP; 89import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING; 90import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW; 91import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE; 92 93import android.annotation.NonNull; 94import android.app.ActivityManager.StackId; 95import android.content.res.Configuration; 96import android.graphics.Bitmap; 97import android.graphics.Matrix; 98import android.graphics.Rect; 99import android.graphics.RectF; 100import android.graphics.Region; 101import android.graphics.Region.Op; 102import android.hardware.display.DisplayManagerInternal; 103import android.os.Debug; 104import android.os.Handler; 105import android.os.IBinder; 106import android.os.RemoteException; 107import android.os.SystemClock; 108import android.util.DisplayMetrics; 109import android.util.MutableBoolean; 110import android.util.Slog; 111import android.view.Display; 112import android.view.DisplayInfo; 113import android.view.Surface; 114import android.view.SurfaceControl; 115import android.view.WindowManagerPolicy; 116 117import com.android.internal.util.ToBooleanFunction; 118import com.android.internal.view.IInputMethodClient; 119 120import java.io.FileDescriptor; 121import java.io.PrintWriter; 122import java.util.ArrayList; 123import java.util.Comparator; 124import java.util.HashMap; 125import java.util.Iterator; 126import java.util.LinkedList; 127import java.util.List; 128import java.util.function.Consumer; 129import java.util.function.Predicate; 130 131/** 132 * Utility class for keeping track of the WindowStates and other pertinent contents of a 133 * particular Display. 134 * 135 * IMPORTANT: No method from this class should ever be used without holding 136 * WindowManagerService.mWindowMap. 137 */ 138class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowContainer> { 139 private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayContent" : TAG_WM; 140 141 /** Unique identifier of this stack. */ 142 private final int mDisplayId; 143 144 /** The containers below are the only child containers the display can have. */ 145 // Contains all window containers that are related to apps (Activities) 146 private final TaskStackContainers mTaskStackContainers = new TaskStackContainers(); 147 // Contains all non-app window containers that should be displayed above the app containers 148 // (e.g. Status bar) 149 private final NonAppWindowContainers mAboveAppWindowsContainers = 150 new NonAppWindowContainers("mAboveAppWindowsContainers"); 151 // Contains all non-app window containers that should be displayed below the app containers 152 // (e.g. Wallpaper). 153 private final NonAppWindowContainers mBelowAppWindowsContainers = 154 new NonAppWindowContainers("mBelowAppWindowsContainers"); 155 // Contains all IME window containers. Note that the z-ordering of the IME windows will depend 156 // on the IME target. We mainly have this container grouping so we can keep track of all the IME 157 // window containers together and move them in-sync if/when needed. 158 private final NonAppWindowContainers mImeWindowsContainers = 159 new NonAppWindowContainers("mImeWindowsContainers"); 160 161 private WindowState mTmpWindow; 162 private WindowState mTmpWindow2; 163 private WindowAnimator mTmpWindowAnimator; 164 private boolean mTmpRecoveringMemory; 165 private boolean mUpdateImeTarget; 166 private boolean mTmpInitial; 167 168 // Mapping from a token IBinder to a WindowToken object on this display. 169 private final HashMap<IBinder, WindowToken> mTokenMap = new HashMap(); 170 171 int mInitialDisplayWidth = 0; 172 int mInitialDisplayHeight = 0; 173 int mInitialDisplayDensity = 0; 174 int mBaseDisplayWidth = 0; 175 int mBaseDisplayHeight = 0; 176 int mBaseDisplayDensity = 0; 177 boolean mDisplayScalingDisabled; 178 private final DisplayInfo mDisplayInfo = new DisplayInfo(); 179 private final Display mDisplay; 180 private final DisplayMetrics mDisplayMetrics = new DisplayMetrics(); 181 182 Rect mBaseDisplayRect = new Rect(); 183 private Rect mContentRect = new Rect(); 184 185 // Accessed directly by all users. 186 private boolean mLayoutNeeded; 187 int pendingLayoutChanges; 188 // TODO(multi-display): remove some of the usages. 189 boolean isDefaultDisplay; 190 191 /** Window tokens that are in the process of exiting, but still on screen for animations. */ 192 final ArrayList<WindowToken> mExitingTokens = new ArrayList<>(); 193 194 /** A special TaskStack with id==HOME_STACK_ID that moves to the bottom whenever any TaskStack 195 * (except a future lockscreen TaskStack) moves to the top. */ 196 private TaskStack mHomeStack = null; 197 198 /** Detect user tapping outside of current focused task bounds .*/ 199 TaskTapPointerEventListener mTapDetector; 200 201 /** Detect user tapping outside of current focused stack bounds .*/ 202 private Region mTouchExcludeRegion = new Region(); 203 204 /** Save allocating when calculating rects */ 205 private final Rect mTmpRect = new Rect(); 206 private final Rect mTmpRect2 = new Rect(); 207 private final RectF mTmpRectF = new RectF(); 208 private final Matrix mTmpMatrix = new Matrix(); 209 private final Region mTmpRegion = new Region(); 210 211 WindowManagerService mService; 212 213 /** Remove this display when animation on it has completed. */ 214 private boolean mDeferredRemoval; 215 216 final DockedStackDividerController mDividerControllerLocked; 217 final PinnedStackController mPinnedStackControllerLocked; 218 219 DimLayerController mDimLayerController; 220 221 final ArrayList<WindowState> mTapExcludedWindows = new ArrayList<>(); 222 223 private boolean mHaveBootMsg = false; 224 private boolean mHaveApp = false; 225 private boolean mHaveWallpaper = false; 226 private boolean mHaveKeyguard = true; 227 228 private final LinkedList<AppWindowToken> mTmpUpdateAllDrawn = new LinkedList(); 229 230 private final TaskForResizePointSearchResult mTmpTaskForResizePointSearchResult = 231 new TaskForResizePointSearchResult(); 232 private final ApplySurfaceChangesTransactionState mTmpApplySurfaceChangesTransactionState = 233 new ApplySurfaceChangesTransactionState(); 234 private final ScreenshotApplicationState mScreenshotApplicationState = 235 new ScreenshotApplicationState(); 236 237 // True if this display is in the process of being removed. Used to determine if the removal of 238 // the display's direct children should be allowed. 239 private boolean mRemovingDisplay = false; 240 241 private final WindowLayersController mLayersController; 242 WallpaperController mWallpaperController; 243 int mInputMethodAnimLayerAdjustment; 244 245 private final Consumer<WindowState> mUpdateWindowsForAnimator = w -> { 246 WindowStateAnimator winAnimator = w.mWinAnimator; 247 if (winAnimator.hasSurface()) { 248 final boolean wasAnimating = winAnimator.mWasAnimating; 249 final boolean nowAnimating = winAnimator.stepAnimationLocked( 250 mTmpWindowAnimator.mCurrentTime); 251 winAnimator.mWasAnimating = nowAnimating; 252 mTmpWindowAnimator.orAnimating(nowAnimating); 253 254 if (DEBUG_WALLPAPER) Slog.v(TAG, 255 w + ": wasAnimating=" + wasAnimating + ", nowAnimating=" + nowAnimating); 256 257 if (wasAnimating && !winAnimator.mAnimating 258 && mWallpaperController.isWallpaperTarget(w)) { 259 mTmpWindowAnimator.mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE; 260 pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 261 if (DEBUG_LAYOUT_REPEATS) { 262 mService.mWindowPlacerLocked.debugLayoutRepeats( 263 "updateWindowsAndWallpaperLocked 2", pendingLayoutChanges); 264 } 265 } 266 } 267 268 final AppWindowToken atoken = w.mAppToken; 269 if (winAnimator.mDrawState == READY_TO_SHOW) { 270 if (atoken == null || atoken.allDrawn) { 271 if (w.performShowLocked()) { 272 pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM; 273 if (DEBUG_LAYOUT_REPEATS) { 274 mService.mWindowPlacerLocked.debugLayoutRepeats( 275 "updateWindowsAndWallpaperLocked 5", pendingLayoutChanges); 276 } 277 } 278 } 279 } 280 final AppWindowAnimator appAnimator = winAnimator.mAppAnimator; 281 if (appAnimator != null && appAnimator.thumbnail != null) { 282 if (appAnimator.thumbnailTransactionSeq 283 != mTmpWindowAnimator.mAnimTransactionSequence) { 284 appAnimator.thumbnailTransactionSeq = 285 mTmpWindowAnimator.mAnimTransactionSequence; 286 appAnimator.thumbnailLayer = 0; 287 } 288 if (appAnimator.thumbnailLayer < winAnimator.mAnimLayer) { 289 appAnimator.thumbnailLayer = winAnimator.mAnimLayer; 290 } 291 } 292 }; 293 294 private final Consumer<WindowState> mUpdateWallpaperForAnimator = w -> { 295 final WindowStateAnimator winAnimator = w.mWinAnimator; 296 if (winAnimator.mSurfaceController == null || !winAnimator.hasSurface()) { 297 return; 298 } 299 300 final int flags = w.mAttrs.flags; 301 302 // If this window is animating, make a note that we have an animating window and take 303 // care of a request to run a detached wallpaper animation. 304 if (winAnimator.mAnimating) { 305 if (winAnimator.mAnimation != null) { 306 if ((flags & FLAG_SHOW_WALLPAPER) != 0 307 && winAnimator.mAnimation.getDetachWallpaper()) { 308 mTmpWindow = w; 309 } 310 final int color = winAnimator.mAnimation.getBackgroundColor(); 311 if (color != 0) { 312 final TaskStack stack = w.getStack(); 313 if (stack != null) { 314 stack.setAnimationBackground(winAnimator, color); 315 } 316 } 317 } 318 mTmpWindowAnimator.setAnimating(true); 319 } 320 321 // If this window's app token is running a detached wallpaper animation, make a note so 322 // we can ensure the wallpaper is displayed behind it. 323 final AppWindowAnimator appAnimator = winAnimator.mAppAnimator; 324 if (appAnimator != null && appAnimator.animation != null 325 && appAnimator.animating) { 326 if ((flags & FLAG_SHOW_WALLPAPER) != 0 327 && appAnimator.animation.getDetachWallpaper()) { 328 mTmpWindow = w; 329 } 330 331 final int color = appAnimator.animation.getBackgroundColor(); 332 if (color != 0) { 333 final TaskStack stack = w.getStack(); 334 if (stack != null) { 335 stack.setAnimationBackground(winAnimator, color); 336 } 337 } 338 } 339 }; 340 341 private final Consumer<WindowState> mSetInputMethodAnimLayerAdjustment = 342 w -> w.adjustAnimLayer(mInputMethodAnimLayerAdjustment); 343 344 private final Consumer<WindowState> mScheduleToastTimeout = w -> { 345 final int lostFocusUid = mTmpWindow.mOwnerUid; 346 final Handler handler = mService.mH; 347 if (w.mAttrs.type == TYPE_TOAST && w.mOwnerUid == lostFocusUid) { 348 if (!handler.hasMessages(WINDOW_HIDE_TIMEOUT, w)) { 349 handler.sendMessageDelayed(handler.obtainMessage(WINDOW_HIDE_TIMEOUT, w), 350 w.mAttrs.hideTimeoutMilliseconds); 351 } 352 } 353 }; 354 355 private final ToBooleanFunction<WindowState> mFindFocusedWindow = w -> { 356 final AppWindowToken focusedApp = mService.mFocusedApp; 357 if (DEBUG_FOCUS) Slog.v(TAG_WM, "Looking for focus: " + w 358 + ", flags=" + w.mAttrs.flags + ", canReceive=" + w.canReceiveKeys()); 359 360 if (!w.canReceiveKeys()) { 361 return false; 362 } 363 364 final AppWindowToken wtoken = w.mAppToken; 365 366 // If this window's application has been removed, just skip it. 367 if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) { 368 if (DEBUG_FOCUS) Slog.v(TAG_WM, "Skipping " + wtoken + " because " 369 + (wtoken.removed ? "removed" : "sendingToBottom")); 370 return false; 371 } 372 373 if (focusedApp == null) { 374 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp=null" 375 + " using new focus @ " + w); 376 mTmpWindow = w; 377 return true; 378 } 379 380 if (!focusedApp.windowsAreFocusable()) { 381 // Current focused app windows aren't focusable... 382 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp windows not" 383 + " focusable using new focus @ " + w); 384 mTmpWindow = w; 385 return true; 386 } 387 388 // Descend through all of the app tokens and find the first that either matches 389 // win.mAppToken (return win) or mFocusedApp (return null). 390 if (wtoken != null && w.mAttrs.type != TYPE_APPLICATION_STARTING) { 391 if (focusedApp.compareTo(wtoken) > 0) { 392 // App stack below focused app stack. No focus for you!!! 393 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, 394 "findFocusedWindow: Reached focused app=" + focusedApp); 395 mTmpWindow = null; 396 return true; 397 } 398 } 399 400 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: Found new focus @ " + w); 401 mTmpWindow = w; 402 return true; 403 }; 404 405 private final Consumer<WindowState> mPrepareWindowSurfaces = 406 w -> w.mWinAnimator.prepareSurfaceLocked(true); 407 408 private final Consumer<WindowState> mPerformLayout = w -> { 409 // Don't do layout of a window if it is not visible, or soon won't be visible, to avoid 410 // wasting time and funky changes while a window is animating away. 411 final boolean gone = (mTmpWindow != null && mService.mPolicy.canBeHiddenByKeyguardLw(w)) 412 || w.isGoneForLayoutLw(); 413 414 if (DEBUG_LAYOUT && !w.mLayoutAttached) { 415 Slog.v(TAG, "1ST PASS " + w + ": gone=" + gone + " mHaveFrame=" + w.mHaveFrame 416 + " mLayoutAttached=" + w.mLayoutAttached 417 + " screen changed=" + w.isConfigChanged()); 418 final AppWindowToken atoken = w.mAppToken; 419 if (gone) Slog.v(TAG, " GONE: mViewVisibility=" + w.mViewVisibility 420 + " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.hidden 421 + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested) 422 + " parentHidden=" + w.isParentWindowHidden()); 423 else Slog.v(TAG, " VIS: mViewVisibility=" + w.mViewVisibility 424 + " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.hidden 425 + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested) 426 + " parentHidden=" + w.isParentWindowHidden()); 427 } 428 429 // If this view is GONE, then skip it -- keep the current frame, and let the caller know 430 // so they can ignore it if they want. (We do the normal layout for INVISIBLE windows, 431 // since that means "perform layout as normal, just don't display"). 432 if (!gone || !w.mHaveFrame || w.mLayoutNeeded 433 || ((w.isConfigChanged() || w.setReportResizeHints()) 434 && !w.isGoneForLayoutLw() && 435 ((w.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 || 436 (w.mHasSurface && w.mAppToken != null && 437 w.mAppToken.layoutConfigChanges)))) { 438 if (!w.mLayoutAttached) { 439 if (mTmpInitial) { 440 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 441 w.mContentChanged = false; 442 } 443 if (w.mAttrs.type == TYPE_DREAM) { 444 // Don't layout windows behind a dream, so that if it does stuff like hide 445 // the status bar we won't get a bad transition when it goes away. 446 mTmpWindow = w; 447 } 448 w.mLayoutNeeded = false; 449 w.prelayout(); 450 mService.mPolicy.layoutWindowLw(w, null); 451 w.mLayoutSeq = mService.mLayoutSeq; 452 453 // Window frames may have changed. Update dim layer with the new bounds. 454 final Task task = w.getTask(); 455 if (task != null) { 456 mDimLayerController.updateDimLayer(task); 457 } 458 459 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" + w.mFrame 460 + " mContainingFrame=" + w.mContainingFrame 461 + " mDisplayFrame=" + w.mDisplayFrame); 462 } 463 } 464 }; 465 466 private final Consumer<WindowState> mPerformLayoutAttached = w -> { 467 if (w.mLayoutAttached) { 468 if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + w + " mHaveFrame=" + w.mHaveFrame 469 + " mViewVisibility=" + w.mViewVisibility 470 + " mRelayoutCalled=" + w.mRelayoutCalled); 471 // If this view is GONE, then skip it -- keep the current frame, and let the caller 472 // know so they can ignore it if they want. (We do the normal layout for INVISIBLE 473 // windows, since that means "perform layout as normal, just don't display"). 474 if (mTmpWindow != null && mService.mPolicy.canBeHiddenByKeyguardLw(w)) { 475 return; 476 } 477 if ((w.mViewVisibility != GONE && w.mRelayoutCalled) || !w.mHaveFrame 478 || w.mLayoutNeeded) { 479 if (mTmpInitial) { 480 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 481 w.mContentChanged = false; 482 } 483 w.mLayoutNeeded = false; 484 w.prelayout(); 485 mService.mPolicy.layoutWindowLw(w, w.getParentWindow()); 486 w.mLayoutSeq = mService.mLayoutSeq; 487 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" + w.mFrame 488 + " mContainingFrame=" + w.mContainingFrame 489 + " mDisplayFrame=" + w.mDisplayFrame); 490 } 491 } else if (w.mAttrs.type == TYPE_DREAM) { 492 // Don't layout windows behind a dream, so that if it does stuff like hide the 493 // status bar we won't get a bad transition when it goes away. 494 mTmpWindow = mTmpWindow2; 495 } 496 }; 497 498 private final Predicate<WindowState> mComputeImeTargetPredicate = w -> { 499 if (DEBUG_INPUT_METHOD && mUpdateImeTarget) Slog.i(TAG_WM, "Checking window @" + w 500 + " fl=0x" + Integer.toHexString(w.mAttrs.flags)); 501 return w.canBeImeTarget(); 502 }; 503 504 private final Consumer<WindowState> mApplyPostLayoutPolicy = 505 w -> mService.mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs, w.getParentWindow(), 506 mService.mInputMethodTarget); 507 508 private final Consumer<WindowState> mApplySurfaceChangesTransaction = w -> { 509 final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked; 510 final boolean obscuredChanged = w.mObscured != 511 mTmpApplySurfaceChangesTransactionState.obscured; 512 final RootWindowContainer root = mService.mRoot; 513 // Only used if default window 514 final boolean someoneLosingFocus = !mService.mLosingFocus.isEmpty(); 515 516 // Update effect. 517 w.mObscured = mTmpApplySurfaceChangesTransactionState.obscured; 518 if (!mTmpApplySurfaceChangesTransactionState.obscured) { 519 final boolean isDisplayed = w.isDisplayedLw(); 520 521 if (isDisplayed && w.isObscuringDisplay()) { 522 // This window completely covers everything behind it, so we want to leave all 523 // of them as undimmed (for performance reasons). 524 root.mObscuringWindow = w; 525 mTmpApplySurfaceChangesTransactionState.obscured = true; 526 } 527 528 mTmpApplySurfaceChangesTransactionState.displayHasContent |= 529 root.handleNotObscuredLocked(w, 530 mTmpApplySurfaceChangesTransactionState.obscured, 531 mTmpApplySurfaceChangesTransactionState.syswin); 532 533 if (w.mHasSurface && isDisplayed) { 534 final int type = w.mAttrs.type; 535 if (type == TYPE_SYSTEM_DIALOG || type == TYPE_SYSTEM_ERROR 536 || (w.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { 537 mTmpApplySurfaceChangesTransactionState.syswin = true; 538 } 539 if (mTmpApplySurfaceChangesTransactionState.preferredRefreshRate == 0 540 && w.mAttrs.preferredRefreshRate != 0) { 541 mTmpApplySurfaceChangesTransactionState.preferredRefreshRate 542 = w.mAttrs.preferredRefreshRate; 543 } 544 if (mTmpApplySurfaceChangesTransactionState.preferredModeId == 0 545 && w.mAttrs.preferredDisplayModeId != 0) { 546 mTmpApplySurfaceChangesTransactionState.preferredModeId 547 = w.mAttrs.preferredDisplayModeId; 548 } 549 } 550 } 551 552 w.applyDimLayerIfNeeded(); 553 554 if (isDefaultDisplay && obscuredChanged && w.isVisibleLw() 555 && mWallpaperController.isWallpaperTarget(w)) { 556 // This is the wallpaper target and its obscured state changed... make sure the 557 // current wallpaper's visibility has been updated accordingly. 558 mWallpaperController.updateWallpaperVisibility(); 559 } 560 561 w.handleWindowMovedIfNeeded(); 562 563 final WindowStateAnimator winAnimator = w.mWinAnimator; 564 565 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); 566 w.mContentChanged = false; 567 568 // Moved from updateWindowsAndWallpaperLocked(). 569 if (w.mHasSurface) { 570 // Take care of the window being ready to display. 571 final boolean committed = winAnimator.commitFinishDrawingLocked(); 572 if (isDefaultDisplay && committed) { 573 if (w.mAttrs.type == TYPE_DREAM) { 574 // HACK: When a dream is shown, it may at that point hide the lock screen. 575 // So we need to redo the layout to let the phone window manager make this 576 // happen. 577 pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT; 578 if (DEBUG_LAYOUT_REPEATS) { 579 surfacePlacer.debugLayoutRepeats( 580 "dream and commitFinishDrawingLocked true", 581 pendingLayoutChanges); 582 } 583 } 584 if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) { 585 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 586 "First draw done in potential wallpaper target " + w); 587 root.mWallpaperMayChange = true; 588 pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 589 if (DEBUG_LAYOUT_REPEATS) { 590 surfacePlacer.debugLayoutRepeats( 591 "wallpaper and commitFinishDrawingLocked true", 592 pendingLayoutChanges); 593 } 594 } 595 } 596 if (!winAnimator.isAnimationStarting() && !winAnimator.isWaitingForOpening()) { 597 // Updates the shown frame before we set up the surface. This is needed 598 // because the resizing could change the top-left position (in addition to 599 // size) of the window. setSurfaceBoundariesLocked uses mShownPosition to 600 // position the surface. 601 // 602 // If an animation is being started, we can't call this method because the 603 // animation hasn't processed its initial transformation yet, but in general 604 // we do want to update the position if the window is animating. 605 winAnimator.computeShownFrameLocked(); 606 } 607 winAnimator.setSurfaceBoundariesLocked(mTmpRecoveringMemory /* recoveringMemory */); 608 } 609 610 final AppWindowToken atoken = w.mAppToken; 611 if (atoken != null) { 612 final boolean updateAllDrawn = atoken.updateDrawnWindowStates(w); 613 if (updateAllDrawn && !mTmpUpdateAllDrawn.contains(atoken)) { 614 mTmpUpdateAllDrawn.add(atoken); 615 } 616 } 617 618 if (isDefaultDisplay && someoneLosingFocus && w == mService.mCurrentFocus 619 && w.isDisplayedLw()) { 620 mTmpApplySurfaceChangesTransactionState.focusDisplayed = true; 621 } 622 623 w.updateResizingWindowIfNeeded(); 624 }; 625 626 /** 627 * @param display May not be null. 628 * @param service You know. 629 * @param layersController window layer controller used to assign layer to the windows on this 630 * display. 631 * @param wallpaperController wallpaper windows controller used to adjust the positioning of the 632 * wallpaper windows in the window list. 633 */ 634 DisplayContent(Display display, WindowManagerService service, 635 WindowLayersController layersController, WallpaperController wallpaperController) { 636 mDisplay = display; 637 mDisplayId = display.getDisplayId(); 638 mLayersController = layersController; 639 mWallpaperController = wallpaperController; 640 display.getDisplayInfo(mDisplayInfo); 641 display.getMetrics(mDisplayMetrics); 642 isDefaultDisplay = mDisplayId == DEFAULT_DISPLAY; 643 mService = service; 644 initializeDisplayBaseInfo(); 645 mDividerControllerLocked = new DockedStackDividerController(service, this); 646 mPinnedStackControllerLocked = new PinnedStackController(service, this); 647 mDimLayerController = new DimLayerController(this); 648 649 // These are the only direct children we should ever have and they are permanent. 650 super.addChild(mBelowAppWindowsContainers, null); 651 super.addChild(mTaskStackContainers, null); 652 super.addChild(mAboveAppWindowsContainers, null); 653 super.addChild(mImeWindowsContainers, null); 654 } 655 656 int getDisplayId() { 657 return mDisplayId; 658 } 659 660 WindowToken getWindowToken(IBinder binder) { 661 return mTokenMap.get(binder); 662 } 663 664 AppWindowToken getAppWindowToken(IBinder binder) { 665 final WindowToken token = getWindowToken(binder); 666 if (token == null) { 667 return null; 668 } 669 return token.asAppWindowToken(); 670 } 671 672 void addWindowToken(IBinder binder, WindowToken token) { 673 final DisplayContent dc = mService.mRoot.getWindowTokenDisplay(token); 674 if (dc != null) { 675 // We currently don't support adding a window token to the display if the display 676 // already has the binder mapped to another token. If there is a use case for supporting 677 // this moving forward we will either need to merge the WindowTokens some how or have 678 // the binder map to a list of window tokens. 679 throw new IllegalArgumentException("Can't map token=" + token + " to display=" + this 680 + " already mapped to display=" + dc + " tokens=" + dc.mTokenMap); 681 } 682 mTokenMap.put(binder, token); 683 684 if (token.asAppWindowToken() == null) { 685 // Add non-app token to container hierarchy on the display. App tokens are added through 686 // the parent container managing them (e.g. Tasks). 687 switch (token.windowType) { 688 case TYPE_WALLPAPER: 689 mBelowAppWindowsContainers.addChild(token); 690 break; 691 case TYPE_INPUT_METHOD: 692 case TYPE_INPUT_METHOD_DIALOG: 693 mImeWindowsContainers.addChild(token); 694 break; 695 default: 696 mAboveAppWindowsContainers.addChild(token); 697 break; 698 } 699 } 700 } 701 702 WindowToken removeWindowToken(IBinder binder) { 703 final WindowToken token = mTokenMap.remove(binder); 704 if (token != null && token.asAppWindowToken() == null) { 705 token.setExiting(); 706 } 707 return token; 708 } 709 710 /** Changes the display the input window token is housed on to this one. */ 711 void reParentWindowToken(WindowToken token) { 712 final DisplayContent prevDc = token.getDisplayContent(); 713 if (prevDc == this) { 714 return; 715 } 716 if (prevDc != null && prevDc.mTokenMap.remove(token.token) != null 717 && token.asAppWindowToken() == null) { 718 // Removed the token from the map, but made sure it's not an app token before removing 719 // from parent. 720 token.getParent().removeChild(token); 721 } 722 723 addWindowToken(token.token, token); 724 } 725 726 void removeAppToken(IBinder binder) { 727 final WindowToken token = removeWindowToken(binder); 728 if (token == null) { 729 Slog.w(TAG_WM, "removeAppToken: Attempted to remove non-existing token: " + binder); 730 return; 731 } 732 733 final AppWindowToken appToken = token.asAppWindowToken(); 734 735 if (appToken == null) { 736 Slog.w(TAG_WM, "Attempted to remove non-App token: " + binder + " token=" + token); 737 return; 738 } 739 740 appToken.onRemovedFromDisplay(); 741 } 742 743 Display getDisplay() { 744 return mDisplay; 745 } 746 747 DisplayInfo getDisplayInfo() { 748 return mDisplayInfo; 749 } 750 751 DisplayMetrics getDisplayMetrics() { 752 return mDisplayMetrics; 753 } 754 755 DockedStackDividerController getDockedDividerController() { 756 return mDividerControllerLocked; 757 } 758 759 PinnedStackController getPinnedStackController() { 760 return mPinnedStackControllerLocked; 761 } 762 763 /** 764 * Returns true if the specified UID has access to this display. 765 */ 766 boolean hasAccess(int uid) { 767 return mDisplay.hasAccess(uid); 768 } 769 770 boolean isPrivate() { 771 return (mDisplay.getFlags() & FLAG_PRIVATE) != 0; 772 } 773 774 TaskStack getHomeStack() { 775 if (mHomeStack == null && mDisplayId == DEFAULT_DISPLAY) { 776 Slog.e(TAG_WM, "getHomeStack: Returning null from this=" + this); 777 } 778 return mHomeStack; 779 } 780 781 TaskStack getStackById(int stackId) { 782 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 783 final TaskStack stack = mTaskStackContainers.get(i); 784 if (stack.mStackId == stackId) { 785 return stack; 786 } 787 } 788 return null; 789 } 790 791 @Override 792 void onConfigurationChanged(Configuration newParentConfig) { 793 super.onConfigurationChanged(newParentConfig); 794 795 // The display size information is heavily dependent on the resources in the current 796 // configuration, so we need to reconfigure it every time the configuration changes. 797 // See {@link PhoneWindowManager#setInitialDisplaySize}...sigh... 798 mService.reconfigureDisplayLocked(this); 799 800 getDockedDividerController().onConfigurationChanged(); 801 getPinnedStackController().onConfigurationChanged(); 802 } 803 804 /** 805 * Callback used to trigger bounds update after configuration change and get ids of stacks whose 806 * bounds were updated. 807 */ 808 void updateStackBoundsAfterConfigChange(@NonNull List<Integer> changedStackList) { 809 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 810 final TaskStack stack = mTaskStackContainers.get(i); 811 if (stack.updateBoundsAfterConfigChange()) { 812 changedStackList.add(stack.mStackId); 813 } 814 } 815 } 816 817 @Override 818 boolean fillsParent() { 819 return true; 820 } 821 822 @Override 823 boolean isVisible() { 824 return true; 825 } 826 827 @Override 828 void onAppTransitionDone() { 829 super.onAppTransitionDone(); 830 mService.mWindowsChanged = true; 831 } 832 833 @Override 834 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) { 835 // Special handling so we can process IME windows with #forAllImeWindows above their IME 836 // target, or here in order if there isn't an IME target. 837 if (traverseTopToBottom) { 838 for (int i = mChildren.size() - 1; i >= 0; --i) { 839 final DisplayChildWindowContainer child = mChildren.get(i); 840 if (child == mImeWindowsContainers && mService.mInputMethodTarget != null) { 841 // In this case the Ime windows will be processed above their target so we skip 842 // here. 843 continue; 844 } 845 if (child.forAllWindows(callback, traverseTopToBottom)) { 846 return true; 847 } 848 } 849 } else { 850 final int count = mChildren.size(); 851 for (int i = 0; i < count; i++) { 852 final DisplayChildWindowContainer child = mChildren.get(i); 853 if (child == mImeWindowsContainers && mService.mInputMethodTarget != null) { 854 // In this case the Ime windows will be processed above their target so we skip 855 // here. 856 continue; 857 } 858 if (child.forAllWindows(callback, traverseTopToBottom)) { 859 return true; 860 } 861 } 862 } 863 return false; 864 } 865 866 boolean forAllImeWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) { 867 return mImeWindowsContainers.forAllWindows(callback, traverseTopToBottom); 868 } 869 870 @Override 871 int getOrientation() { 872 final WindowManagerPolicy policy = mService.mPolicy; 873 874 if (mService.mDisplayFrozen) { 875 if (mService.mLastWindowForcedOrientation != SCREEN_ORIENTATION_UNSPECIFIED) { 876 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, 877 "Display is frozen, return " + mService.mLastWindowForcedOrientation); 878 // If the display is frozen, some activities may be in the middle of restarting, and 879 // thus have removed their old window. If the window has the flag to hide the lock 880 // screen, then the lock screen can re-appear and inflict its own orientation on us. 881 // Keep the orientation stable until this all settles down. 882 return mService.mLastWindowForcedOrientation; 883 } else if (policy.isKeyguardLocked()) { 884 // Use the last orientation the while the display is frozen with the keyguard 885 // locked. This could be the keyguard forced orientation or from a SHOW_WHEN_LOCKED 886 // window. We don't want to check the show when locked window directly though as 887 // things aren't stable while the display is frozen, for example the window could be 888 // momentarily unavailable due to activity relaunch. 889 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display is frozen while keyguard locked, " 890 + "return " + mService.mLastOrientation); 891 return mService.mLastOrientation; 892 } 893 } else { 894 final int orientation = mAboveAppWindowsContainers.getOrientation(); 895 if (orientation != SCREEN_ORIENTATION_UNSET) { 896 return orientation; 897 } 898 } 899 900 // Top system windows are not requesting an orientation. Start searching from apps. 901 return mTaskStackContainers.getOrientation(); 902 } 903 904 void updateDisplayInfo() { 905 mDisplay.getDisplayInfo(mDisplayInfo); 906 mDisplay.getMetrics(mDisplayMetrics); 907 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 908 mTaskStackContainers.get(i).updateDisplayInfo(null); 909 } 910 } 911 912 void initializeDisplayBaseInfo() { 913 final DisplayManagerInternal displayManagerInternal = mService.mDisplayManagerInternal; 914 if (displayManagerInternal != null) { 915 // Bootstrap the default logical display from the display manager. 916 final DisplayInfo newDisplayInfo = displayManagerInternal.getDisplayInfo(mDisplayId); 917 if (newDisplayInfo != null) { 918 mDisplayInfo.copyFrom(newDisplayInfo); 919 } 920 } 921 922 mBaseDisplayWidth = mInitialDisplayWidth = mDisplayInfo.logicalWidth; 923 mBaseDisplayHeight = mInitialDisplayHeight = mDisplayInfo.logicalHeight; 924 mBaseDisplayDensity = mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi; 925 mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight); 926 } 927 928 void getLogicalDisplayRect(Rect out) { 929 // Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked. 930 final int orientation = mDisplayInfo.rotation; 931 boolean rotated = (orientation == ROTATION_90 || orientation == ROTATION_270); 932 final int physWidth = rotated ? mBaseDisplayHeight : mBaseDisplayWidth; 933 final int physHeight = rotated ? mBaseDisplayWidth : mBaseDisplayHeight; 934 int width = mDisplayInfo.logicalWidth; 935 int left = (physWidth - width) / 2; 936 int height = mDisplayInfo.logicalHeight; 937 int top = (physHeight - height) / 2; 938 out.set(left, top, left + width, top + height); 939 } 940 941 private void getLogicalDisplayRect(Rect out, int orientation) { 942 getLogicalDisplayRect(out); 943 944 // Rotate the Rect if needed. 945 final int currentRotation = mDisplayInfo.rotation; 946 final int rotationDelta = deltaRotation(currentRotation, orientation); 947 if (rotationDelta == ROTATION_90 || rotationDelta == ROTATION_270) { 948 createRotationMatrix(rotationDelta, mBaseDisplayWidth, mBaseDisplayHeight, mTmpMatrix); 949 mTmpRectF.set(out); 950 mTmpMatrix.mapRect(mTmpRectF); 951 mTmpRectF.round(out); 952 } 953 } 954 955 void getContentRect(Rect out) { 956 out.set(mContentRect); 957 } 958 959 /** 960 * Adds the stack to this display. 961 * @see WindowManagerService#addStackToDisplay(int, int, boolean) 962 */ 963 Rect addStackToDisplay(int stackId, boolean onTop) { 964 boolean attachedToDisplay = false; 965 TaskStack stack = mService.mStackIdToStack.get(stackId); 966 if (stack == null) { 967 if (DEBUG_STACK) Slog.d(TAG_WM, "Create new stackId=" + stackId + " on displayId=" 968 + mDisplayId); 969 970 stack = getStackById(stackId); 971 if (stack != null) { 972 // It's already attached to the display...clear mDeferRemoval and move stack to 973 // appropriate z-order on display as needed. 974 stack.mDeferRemoval = false; 975 // We're not moving the display to front when we're adding stacks, only when 976 // requested to change the position of stack explicitly. 977 mTaskStackContainers.positionChildAt(onTop ? POSITION_TOP : POSITION_BOTTOM, stack, 978 false /* includingParents */); 979 attachedToDisplay = true; 980 } else { 981 stack = new TaskStack(mService, stackId); 982 } 983 984 mService.mStackIdToStack.put(stackId, stack); 985 if (stackId == DOCKED_STACK_ID) { 986 mDividerControllerLocked.notifyDockedStackExistsChanged(true); 987 } 988 } else { 989 final DisplayContent currentDC = stack.getDisplayContent(); 990 if (currentDC != null) { 991 throw new IllegalStateException("Trying to add stackId=" + stackId 992 + "to displayId=" + mDisplayId + ", but it's already attached to displayId=" 993 + currentDC.getDisplayId()); 994 } 995 } 996 997 if (!attachedToDisplay) { 998 mTaskStackContainers.addStackToDisplay(stack, onTop); 999 } 1000 1001 if (stack.getRawFullscreen()) { 1002 return null; 1003 } 1004 final Rect bounds = new Rect(); 1005 stack.getRawBounds(bounds); 1006 return bounds; 1007 } 1008 1009 /** Removes the stack from the display and prepares for changing the parent. */ 1010 private void removeStackFromDisplay(TaskStack stack) { 1011 mTaskStackContainers.removeStackFromDisplay(stack); 1012 } 1013 1014 /** Moves the stack to this display and returns the updated bounds. */ 1015 Rect moveStackToDisplay(TaskStack stack) { 1016 final DisplayContent currentDisplayContent = stack.getDisplayContent(); 1017 if (currentDisplayContent == null) { 1018 throw new IllegalStateException("Trying to move stackId=" + stack.mStackId 1019 + " which is not currently attached to any display"); 1020 } 1021 if (stack.getDisplayContent().getDisplayId() == mDisplayId) { 1022 throw new IllegalArgumentException("Trying to move stackId=" + stack.mStackId 1023 + " to its current displayId=" + mDisplayId); 1024 } 1025 1026 currentDisplayContent.removeStackFromDisplay(stack); 1027 return addStackToDisplay(stack.mStackId, true /* onTop */); 1028 } 1029 1030 @Override 1031 protected void addChild(DisplayChildWindowContainer child, 1032 Comparator<DisplayChildWindowContainer> comparator) { 1033 throw new UnsupportedOperationException("See DisplayChildWindowContainer"); 1034 } 1035 1036 @Override 1037 protected void addChild(DisplayChildWindowContainer child, int index) { 1038 throw new UnsupportedOperationException("See DisplayChildWindowContainer"); 1039 } 1040 1041 @Override 1042 protected void removeChild(DisplayChildWindowContainer child) { 1043 // Only allow removal of direct children from this display if the display is in the process 1044 // of been removed. 1045 if (mRemovingDisplay) { 1046 super.removeChild(child); 1047 return; 1048 } 1049 throw new UnsupportedOperationException("See DisplayChildWindowContainer"); 1050 } 1051 1052 @Override 1053 void positionChildAt(int position, DisplayChildWindowContainer child, boolean includingParents) { 1054 // Children of the display are statically ordered, so the real intention here is to perform 1055 // the operation on the display and not the static direct children. 1056 getParent().positionChildAt(position, this, includingParents); 1057 } 1058 1059 int taskIdFromPoint(int x, int y) { 1060 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) { 1061 final TaskStack stack = mTaskStackContainers.get(stackNdx); 1062 final int taskId = stack.taskIdFromPoint(x, y); 1063 if (taskId != -1) { 1064 return taskId; 1065 } 1066 } 1067 return -1; 1068 } 1069 1070 /** 1071 * Find the task whose outside touch area (for resizing) (x, y) falls within. 1072 * Returns null if the touch doesn't fall into a resizing area. 1073 */ 1074 Task findTaskForResizePoint(int x, int y) { 1075 final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics); 1076 mTmpTaskForResizePointSearchResult.reset(); 1077 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) { 1078 final TaskStack stack = mTaskStackContainers.get(stackNdx); 1079 if (!StackId.isTaskResizeAllowed(stack.mStackId)) { 1080 return null; 1081 } 1082 1083 stack.findTaskForResizePoint(x, y, delta, mTmpTaskForResizePointSearchResult); 1084 if (mTmpTaskForResizePointSearchResult.searchDone) { 1085 return mTmpTaskForResizePointSearchResult.taskForResize; 1086 } 1087 } 1088 return null; 1089 } 1090 1091 void setTouchExcludeRegion(Task focusedTask) { 1092 mTouchExcludeRegion.set(mBaseDisplayRect); 1093 final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics); 1094 mTmpRect2.setEmpty(); 1095 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) { 1096 final TaskStack stack = mTaskStackContainers.get(stackNdx); 1097 stack.setTouchExcludeRegion( 1098 focusedTask, delta, mTouchExcludeRegion, mContentRect, mTmpRect2); 1099 } 1100 // If we removed the focused task above, add it back and only leave its 1101 // outside touch area in the exclusion. TapDectector is not interested in 1102 // any touch inside the focused task itself. 1103 if (!mTmpRect2.isEmpty()) { 1104 mTouchExcludeRegion.op(mTmpRect2, Region.Op.UNION); 1105 } 1106 final WindowState inputMethod = mService.mInputMethodWindow; 1107 if (inputMethod != null && inputMethod.isVisibleLw()) { 1108 // If the input method is visible and the user is typing, we don't want these touch 1109 // events to be intercepted and used to change focus. This would likely cause a 1110 // disappearance of the input method. 1111 inputMethod.getTouchableRegion(mTmpRegion); 1112 mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION); 1113 } 1114 for (int i = mTapExcludedWindows.size() - 1; i >= 0; i--) { 1115 WindowState win = mTapExcludedWindows.get(i); 1116 win.getTouchableRegion(mTmpRegion); 1117 mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION); 1118 } 1119 // TODO(multi-display): Support docked stacks on secondary displays. 1120 if (mDisplayId == DEFAULT_DISPLAY && getDockedStackLocked() != null) { 1121 mDividerControllerLocked.getTouchRegion(mTmpRect); 1122 mTmpRegion.set(mTmpRect); 1123 mTouchExcludeRegion.op(mTmpRegion, Op.UNION); 1124 } 1125 if (mTapDetector != null) { 1126 mTapDetector.setTouchExcludeRegion(mTouchExcludeRegion); 1127 } 1128 } 1129 1130 @Override 1131 void switchUser() { 1132 super.switchUser(); 1133 mService.mWindowsChanged = true; 1134 } 1135 1136 private void resetAnimationBackgroundAnimator() { 1137 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) { 1138 mTaskStackContainers.get(stackNdx).resetAnimationBackgroundAnimator(); 1139 } 1140 } 1141 1142 boolean animateDimLayers() { 1143 return mDimLayerController.animateDimLayers(); 1144 } 1145 1146 private void resetDimming() { 1147 mDimLayerController.resetDimming(); 1148 } 1149 1150 boolean isDimming() { 1151 return mDimLayerController.isDimming(); 1152 } 1153 1154 private void stopDimmingIfNeeded() { 1155 mDimLayerController.stopDimmingIfNeeded(); 1156 } 1157 1158 @Override 1159 void removeIfPossible() { 1160 if (isAnimating()) { 1161 mDeferredRemoval = true; 1162 return; 1163 } 1164 removeImmediately(); 1165 } 1166 1167 @Override 1168 void removeImmediately() { 1169 mRemovingDisplay = true; 1170 try { 1171 super.removeImmediately(); 1172 if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + this); 1173 mDimLayerController.close(); 1174 if (mDisplayId == DEFAULT_DISPLAY) { 1175 mService.unregisterPointerEventListener(mTapDetector); 1176 mService.unregisterPointerEventListener(mService.mMousePositionTracker); 1177 } 1178 } finally { 1179 mRemovingDisplay = false; 1180 } 1181 } 1182 1183 /** Returns true if a removal action is still being deferred. */ 1184 @Override 1185 boolean checkCompleteDeferredRemoval() { 1186 final boolean stillDeferringRemoval = super.checkCompleteDeferredRemoval(); 1187 1188 if (!stillDeferringRemoval && mDeferredRemoval) { 1189 removeImmediately(); 1190 mService.onDisplayRemoved(mDisplayId); 1191 return false; 1192 } 1193 return true; 1194 } 1195 1196 boolean animateForIme(float interpolatedValue, float animationTarget, 1197 float dividerAnimationTarget) { 1198 boolean updated = false; 1199 1200 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 1201 final TaskStack stack = mTaskStackContainers.get(i); 1202 if (stack == null || !stack.isAdjustedForIme()) { 1203 continue; 1204 } 1205 1206 if (interpolatedValue >= 1f && animationTarget == 0f && dividerAnimationTarget == 0f) { 1207 stack.resetAdjustedForIme(true /* adjustBoundsNow */); 1208 updated = true; 1209 } else { 1210 mDividerControllerLocked.mLastAnimationProgress = 1211 mDividerControllerLocked.getInterpolatedAnimationValue(interpolatedValue); 1212 mDividerControllerLocked.mLastDividerProgress = 1213 mDividerControllerLocked.getInterpolatedDividerValue(interpolatedValue); 1214 updated |= stack.updateAdjustForIme( 1215 mDividerControllerLocked.mLastAnimationProgress, 1216 mDividerControllerLocked.mLastDividerProgress, 1217 false /* force */); 1218 } 1219 if (interpolatedValue >= 1f) { 1220 stack.endImeAdjustAnimation(); 1221 } 1222 } 1223 1224 return updated; 1225 } 1226 1227 boolean clearImeAdjustAnimation() { 1228 boolean changed = false; 1229 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 1230 final TaskStack stack = mTaskStackContainers.get(i); 1231 if (stack != null && stack.isAdjustedForIme()) { 1232 stack.resetAdjustedForIme(true /* adjustBoundsNow */); 1233 changed = true; 1234 } 1235 } 1236 return changed; 1237 } 1238 1239 void beginImeAdjustAnimation() { 1240 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 1241 final TaskStack stack = mTaskStackContainers.get(i); 1242 if (stack.isVisible() && stack.isAdjustedForIme()) { 1243 stack.beginImeAdjustAnimation(); 1244 } 1245 } 1246 } 1247 1248 void adjustForImeIfNeeded() { 1249 final WindowState imeWin = mService.mInputMethodWindow; 1250 final boolean imeVisible = imeWin != null && imeWin.isVisibleLw() && imeWin.isDisplayedLw() 1251 && !mDividerControllerLocked.isImeHideRequested(); 1252 final boolean dockVisible = mService.isStackVisibleLocked(DOCKED_STACK_ID); 1253 final TaskStack imeTargetStack = mService.getImeFocusStackLocked(); 1254 final int imeDockSide = (dockVisible && imeTargetStack != null) ? 1255 imeTargetStack.getDockSide() : DOCKED_INVALID; 1256 final boolean imeOnTop = (imeDockSide == DOCKED_TOP); 1257 final boolean imeOnBottom = (imeDockSide == DOCKED_BOTTOM); 1258 final boolean dockMinimized = mDividerControllerLocked.isMinimizedDock(); 1259 final int imeHeight = mService.mPolicy.getInputMethodWindowVisibleHeightLw(); 1260 final boolean imeHeightChanged = imeVisible && 1261 imeHeight != mDividerControllerLocked.getImeHeightAdjustedFor(); 1262 1263 // The divider could be adjusted for IME position, or be thinner than usual, 1264 // or both. There are three possible cases: 1265 // - If IME is visible, and focus is on top, divider is not moved for IME but thinner. 1266 // - If IME is visible, and focus is on bottom, divider is moved for IME and thinner. 1267 // - If IME is not visible, divider is not moved and is normal width. 1268 1269 if (imeVisible && dockVisible && (imeOnTop || imeOnBottom) && !dockMinimized) { 1270 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 1271 final TaskStack stack = mTaskStackContainers.get(i); 1272 final boolean isDockedOnBottom = stack.getDockSide() == DOCKED_BOTTOM; 1273 if (stack.isVisible() && (imeOnBottom || isDockedOnBottom)) { 1274 stack.setAdjustedForIme(imeWin, imeOnBottom && imeHeightChanged); 1275 } else { 1276 stack.resetAdjustedForIme(false); 1277 } 1278 } 1279 mDividerControllerLocked.setAdjustedForIme( 1280 imeOnBottom /*ime*/, true /*divider*/, true /*animate*/, imeWin, imeHeight); 1281 } else { 1282 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 1283 final TaskStack stack = mTaskStackContainers.get(i); 1284 stack.resetAdjustedForIme(!dockVisible); 1285 } 1286 mDividerControllerLocked.setAdjustedForIme( 1287 false /*ime*/, false /*divider*/, dockVisible /*animate*/, imeWin, imeHeight); 1288 } 1289 mPinnedStackControllerLocked.setAdjustedForIme(imeVisible, imeHeight); 1290 } 1291 1292 void setInputMethodAnimLayerAdjustment(int adj) { 1293 if (DEBUG_LAYERS) Slog.v(TAG_WM, "Setting im layer adj to " + adj); 1294 mInputMethodAnimLayerAdjustment = adj; 1295 mImeWindowsContainers.forAllWindows(mSetInputMethodAnimLayerAdjustment, 1296 true /* traverseTopToBottom */); 1297 } 1298 1299 /** 1300 * If a window that has an animation specifying a colored background and the current wallpaper 1301 * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to 1302 * suddenly disappear. 1303 */ 1304 int getLayerForAnimationBackground(WindowStateAnimator winAnimator) { 1305 final WindowState visibleWallpaper = mBelowAppWindowsContainers.getWindow( 1306 w -> w.mIsWallpaper && w.isVisibleNow()); 1307 1308 if (visibleWallpaper != null) { 1309 return visibleWallpaper.mWinAnimator.mAnimLayer; 1310 } 1311 return winAnimator.mAnimLayer; 1312 } 1313 1314 void prepareFreezingTaskBounds() { 1315 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) { 1316 final TaskStack stack = mTaskStackContainers.get(stackNdx); 1317 stack.prepareFreezingTaskBounds(); 1318 } 1319 } 1320 1321 void rotateBounds(int oldRotation, int newRotation, Rect bounds) { 1322 getLogicalDisplayRect(mTmpRect, newRotation); 1323 1324 // Compute a transform matrix to undo the coordinate space transformation, 1325 // and present the window at the same physical position it previously occupied. 1326 final int deltaRotation = deltaRotation(newRotation, oldRotation); 1327 createRotationMatrix(deltaRotation, mTmpRect.width(), mTmpRect.height(), mTmpMatrix); 1328 1329 mTmpRectF.set(bounds); 1330 mTmpMatrix.mapRect(mTmpRectF); 1331 mTmpRectF.round(bounds); 1332 } 1333 1334 static int deltaRotation(int oldRotation, int newRotation) { 1335 int delta = newRotation - oldRotation; 1336 if (delta < 0) delta += 4; 1337 return delta; 1338 } 1339 1340 private static void createRotationMatrix(int rotation, float displayWidth, float displayHeight, 1341 Matrix outMatrix) { 1342 // For rotations without Z-ordering we don't need the target rectangle's position. 1343 createRotationMatrix(rotation, 0 /* rectLeft */, 0 /* rectTop */, displayWidth, 1344 displayHeight, outMatrix); 1345 } 1346 1347 static void createRotationMatrix(int rotation, float rectLeft, float rectTop, 1348 float displayWidth, float displayHeight, Matrix outMatrix) { 1349 switch (rotation) { 1350 case ROTATION_0: 1351 outMatrix.reset(); 1352 break; 1353 case ROTATION_270: 1354 outMatrix.setRotate(270, 0, 0); 1355 outMatrix.postTranslate(0, displayHeight); 1356 outMatrix.postTranslate(rectTop, 0); 1357 break; 1358 case ROTATION_180: 1359 outMatrix.reset(); 1360 break; 1361 case ROTATION_90: 1362 outMatrix.setRotate(90, 0, 0); 1363 outMatrix.postTranslate(displayWidth, 0); 1364 outMatrix.postTranslate(-rectTop, rectLeft); 1365 break; 1366 } 1367 } 1368 1369 public void dump(String prefix, PrintWriter pw) { 1370 pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId); 1371 final String subPrefix = " " + prefix; 1372 pw.print(subPrefix); pw.print("init="); pw.print(mInitialDisplayWidth); pw.print("x"); 1373 pw.print(mInitialDisplayHeight); pw.print(" "); pw.print(mInitialDisplayDensity); 1374 pw.print("dpi"); 1375 if (mInitialDisplayWidth != mBaseDisplayWidth 1376 || mInitialDisplayHeight != mBaseDisplayHeight 1377 || mInitialDisplayDensity != mBaseDisplayDensity) { 1378 pw.print(" base="); 1379 pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight); 1380 pw.print(" "); pw.print(mBaseDisplayDensity); pw.print("dpi"); 1381 } 1382 if (mDisplayScalingDisabled) { 1383 pw.println(" noscale"); 1384 } 1385 pw.print(" cur="); 1386 pw.print(mDisplayInfo.logicalWidth); 1387 pw.print("x"); pw.print(mDisplayInfo.logicalHeight); 1388 pw.print(" app="); 1389 pw.print(mDisplayInfo.appWidth); 1390 pw.print("x"); pw.print(mDisplayInfo.appHeight); 1391 pw.print(" rng="); pw.print(mDisplayInfo.smallestNominalAppWidth); 1392 pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight); 1393 pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth); 1394 pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight); 1395 pw.println(subPrefix + "deferred=" + mDeferredRemoval 1396 + " mLayoutNeeded=" + mLayoutNeeded); 1397 1398 pw.println(); 1399 pw.println(prefix + "Application tokens in top down Z order:"); 1400 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) { 1401 final TaskStack stack = mTaskStackContainers.get(stackNdx); 1402 stack.dump(prefix + " ", pw); 1403 } 1404 1405 pw.println(); 1406 if (!mExitingTokens.isEmpty()) { 1407 pw.println(); 1408 pw.println(" Exiting tokens:"); 1409 for (int i = mExitingTokens.size() - 1; i >= 0; i--) { 1410 final WindowToken token = mExitingTokens.get(i); 1411 pw.print(" Exiting #"); pw.print(i); 1412 pw.print(' '); pw.print(token); 1413 pw.println(':'); 1414 token.dump(pw, " "); 1415 } 1416 } 1417 pw.println(); 1418 mDimLayerController.dump(prefix, pw); 1419 pw.println(); 1420 mDividerControllerLocked.dump(prefix, pw); 1421 pw.println(); 1422 mPinnedStackControllerLocked.dump(prefix, pw); 1423 1424 if (mInputMethodAnimLayerAdjustment != 0) { 1425 pw.println(subPrefix 1426 + "mInputMethodAnimLayerAdjustment=" + mInputMethodAnimLayerAdjustment); 1427 } 1428 } 1429 1430 @Override 1431 public String toString() { 1432 return "Display " + mDisplayId + " info=" + mDisplayInfo + " stacks=" + mChildren; 1433 } 1434 1435 String getName() { 1436 return "Display " + mDisplayId + " name=\"" + mDisplayInfo.name + "\""; 1437 } 1438 1439 /** 1440 * @return The docked stack, but only if it is visible, and {@code null} otherwise. 1441 */ 1442 TaskStack getDockedStackLocked() { 1443 final TaskStack stack = mService.mStackIdToStack.get(DOCKED_STACK_ID); 1444 return (stack != null && stack.isVisible()) ? stack : null; 1445 } 1446 1447 /** 1448 * Like {@link #getDockedStackLocked}, but also returns the docked stack if it's currently not 1449 * visible. 1450 */ 1451 TaskStack getDockedStackIgnoringVisibility() { 1452 return mService.mStackIdToStack.get(DOCKED_STACK_ID); 1453 } 1454 1455 /** Find the visible, touch-deliverable window under the given point */ 1456 WindowState getTouchableWinAtPointLocked(float xf, float yf) { 1457 final int x = (int) xf; 1458 final int y = (int) yf; 1459 final WindowState touchedWin = getWindow(w -> { 1460 final int flags = w.mAttrs.flags; 1461 if (!w.isVisibleLw()) { 1462 return false; 1463 } 1464 if ((flags & FLAG_NOT_TOUCHABLE) != 0) { 1465 return false; 1466 } 1467 1468 w.getVisibleBounds(mTmpRect); 1469 if (!mTmpRect.contains(x, y)) { 1470 return false; 1471 } 1472 1473 w.getTouchableRegion(mTmpRegion); 1474 1475 final int touchFlags = flags & (FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL); 1476 return mTmpRegion.contains(x, y) || touchFlags == 0; 1477 }); 1478 1479 return touchedWin; 1480 } 1481 1482 boolean canAddToastWindowForUid(int uid) { 1483 // We allow one toast window per UID being shown at a time. 1484 final WindowState win = getWindow(w -> 1485 w.mAttrs.type == TYPE_TOAST && w.mOwnerUid == uid && !w.mPermanentlyHidden 1486 && !w.mWindowRemovalAllowed); 1487 return win == null; 1488 } 1489 1490 void scheduleToastWindowsTimeoutIfNeededLocked(WindowState oldFocus, WindowState newFocus) { 1491 if (oldFocus == null || (newFocus != null && newFocus.mOwnerUid == oldFocus.mOwnerUid)) { 1492 return; 1493 } 1494 1495 // Used to communicate the old focus to the callback method. 1496 mTmpWindow = oldFocus; 1497 1498 forAllWindows(mScheduleToastTimeout, false /* traverseTopToBottom */); 1499 } 1500 1501 WindowState findFocusedWindow() { 1502 mTmpWindow = null; 1503 1504 forAllWindows(mFindFocusedWindow, true /* traverseTopToBottom */); 1505 1506 if (mTmpWindow == null) { 1507 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: No focusable windows."); 1508 return null; 1509 } 1510 return mTmpWindow; 1511 } 1512 1513 /** Updates the layer assignment of windows on this display. */ 1514 void assignWindowLayers(boolean setLayoutNeeded) { 1515 mLayersController.assignWindowLayers(this); 1516 if (setLayoutNeeded) { 1517 setLayoutNeeded(); 1518 } 1519 } 1520 1521 void layoutAndAssignWindowLayersIfNeeded() { 1522 mService.mWindowsChanged = true; 1523 setLayoutNeeded(); 1524 1525 if (!mService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 1526 false /*updateInputWindows*/)) { 1527 assignWindowLayers(false /* setLayoutNeeded */); 1528 } 1529 1530 mService.mInputMonitor.setUpdateInputWindowsNeededLw(); 1531 mService.mWindowPlacerLocked.performSurfacePlacement(); 1532 mService.mInputMonitor.updateInputWindowsLw(false /*force*/); 1533 } 1534 1535 /** Returns true if a leaked surface was destroyed */ 1536 boolean destroyLeakedSurfaces() { 1537 // Used to indicate that a surface was leaked. 1538 mTmpWindow = null; 1539 forAllWindows(w -> { 1540 final WindowStateAnimator wsa = w.mWinAnimator; 1541 if (wsa.mSurfaceController == null) { 1542 return; 1543 } 1544 if (!mService.mSessions.contains(wsa.mSession)) { 1545 Slog.w(TAG_WM, "LEAKED SURFACE (session doesn't exist): " 1546 + w + " surface=" + wsa.mSurfaceController 1547 + " token=" + w.mToken 1548 + " pid=" + w.mSession.mPid 1549 + " uid=" + w.mSession.mUid); 1550 wsa.destroySurface(); 1551 mService.mForceRemoves.add(w); 1552 mTmpWindow = w; 1553 } else if (w.mAppToken != null && w.mAppToken.clientHidden) { 1554 Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): " 1555 + w + " surface=" + wsa.mSurfaceController 1556 + " token=" + w.mAppToken 1557 + " saved=" + w.hasSavedSurface()); 1558 if (SHOW_TRANSACTIONS) logSurface(w, "LEAK DESTROY", false); 1559 wsa.destroySurface(); 1560 mTmpWindow = w; 1561 } 1562 }, false /* traverseTopToBottom */); 1563 1564 return mTmpWindow != null; 1565 } 1566 1567 /** 1568 * Determine and return the window that should be the IME target. 1569 * @param updateImeTarget If true the system IME target will be updated to match what we found. 1570 * @return The window that should be used as the IME target or null if there isn't any. 1571 */ 1572 WindowState computeImeTarget(boolean updateImeTarget) { 1573 if (mService.mInputMethodWindow == null) { 1574 // There isn't an IME so there shouldn't be a target...That was easy! 1575 if (updateImeTarget) { 1576 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " 1577 + mService.mInputMethodTarget + " to null since mInputMethodWindow is null"); 1578 setInputMethodTarget(null, mService.mInputMethodTargetWaitingAnim, 0); 1579 } 1580 return null; 1581 } 1582 1583 // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the 1584 // same display. Or even when the current IME/target are not on the same screen as the next 1585 // IME/target. For now only look for input windows on the main screen. 1586 mUpdateImeTarget = updateImeTarget; 1587 WindowState target = getWindow(mComputeImeTargetPredicate); 1588 1589 1590 // Yet more tricksyness! If this window is a "starting" window, we do actually want 1591 // to be on top of it, but it is not -really- where input will go. So look down below 1592 // for a real window to target... 1593 if (target != null && target.mAttrs.type == TYPE_APPLICATION_STARTING) { 1594 final AppWindowToken token = target.mAppToken; 1595 if (token != null) { 1596 final WindowState betterTarget = token.getImeTargetBelowWindow(target); 1597 if (betterTarget != null) { 1598 target = betterTarget; 1599 } 1600 } 1601 } 1602 1603 if (DEBUG_INPUT_METHOD && updateImeTarget) Slog.v(TAG_WM, 1604 "Proposed new IME target: " + target); 1605 1606 // Now, a special case -- if the last target's window is in the process of exiting, and is 1607 // above the new target, keep on the last target to avoid flicker. Consider for example a 1608 // Dialog with the IME shown: when the Dialog is dismissed, we want to keep the IME above it 1609 // until it is completely gone so it doesn't drop behind the dialog or its full-screen 1610 // scrim. 1611 final WindowState curTarget = mService.mInputMethodTarget; 1612 if (curTarget != null && curTarget.isDisplayedLw() && curTarget.isClosing() 1613 && (target == null 1614 || curTarget.mWinAnimator.mAnimLayer > target.mWinAnimator.mAnimLayer)) { 1615 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Current target higher, not changing"); 1616 return curTarget; 1617 } 1618 1619 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Desired input method target=" + target 1620 + " updateImeTarget=" + updateImeTarget); 1621 1622 if (target == null) { 1623 if (updateImeTarget) { 1624 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget 1625 + " to null." + (SHOW_STACK_CRAWLS ? " Callers=" 1626 + Debug.getCallers(4) : "")); 1627 setInputMethodTarget(null, mService.mInputMethodTargetWaitingAnim, 0); 1628 } 1629 1630 return null; 1631 } 1632 1633 if (updateImeTarget) { 1634 AppWindowToken token = curTarget == null ? null : curTarget.mAppToken; 1635 if (token != null) { 1636 1637 // Now some fun for dealing with window animations that modify the Z order. We need 1638 // to look at all windows below the current target that are in this app, finding the 1639 // highest visible one in layering. 1640 WindowState highestTarget = null; 1641 if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) { 1642 highestTarget = token.getHighestAnimLayerWindow(curTarget); 1643 } 1644 1645 if (highestTarget != null) { 1646 final AppTransition appTransition = mService.mAppTransition; 1647 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, appTransition + " " + highestTarget 1648 + " animating=" + highestTarget.mWinAnimator.isAnimationSet() 1649 + " layer=" + highestTarget.mWinAnimator.mAnimLayer 1650 + " new layer=" + target.mWinAnimator.mAnimLayer); 1651 1652 if (appTransition.isTransitionSet()) { 1653 // If we are currently setting up for an animation, hold everything until we 1654 // can find out what will happen. 1655 setInputMethodTarget(highestTarget, true, mInputMethodAnimLayerAdjustment); 1656 return highestTarget; 1657 } else if (highestTarget.mWinAnimator.isAnimationSet() && 1658 highestTarget.mWinAnimator.mAnimLayer > target.mWinAnimator.mAnimLayer) { 1659 // If the window we are currently targeting is involved with an animation, 1660 // and it is on top of the next target we will be over, then hold off on 1661 // moving until that is done. 1662 setInputMethodTarget(highestTarget, true, mInputMethodAnimLayerAdjustment); 1663 return highestTarget; 1664 } 1665 } 1666 } 1667 1668 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget + " to " 1669 + target + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : "")); 1670 setInputMethodTarget(target, false, target.mAppToken != null 1671 ? target.mAppToken.mAppAnimator.animLayerAdjustment : 0); 1672 } 1673 1674 return target; 1675 } 1676 1677 private void setInputMethodTarget(WindowState target, boolean targetWaitingAnim, int layerAdj) { 1678 if (target == mService.mInputMethodTarget 1679 && mService.mInputMethodTargetWaitingAnim == targetWaitingAnim 1680 && mInputMethodAnimLayerAdjustment == layerAdj) { 1681 return; 1682 } 1683 1684 mService.mInputMethodTarget = target; 1685 mService.mInputMethodTargetWaitingAnim = targetWaitingAnim; 1686 setInputMethodAnimLayerAdjustment(layerAdj); 1687 assignWindowLayers(false /* setLayoutNeeded */); 1688 } 1689 1690 boolean getNeedsMenu(WindowState top, WindowManagerPolicy.WindowState bottom) { 1691 if (top.mAttrs.needsMenuKey != NEEDS_MENU_UNSET) { 1692 return top.mAttrs.needsMenuKey == NEEDS_MENU_SET_TRUE; 1693 } 1694 1695 // Used to indicate we have reached the first window in the range we are interested in. 1696 mTmpWindow = null; 1697 1698 // TODO: Figure-out a more efficient way to do this. 1699 final WindowState candidate = getWindow(w -> { 1700 if (w == top) { 1701 // Reached the first window in the range we are interested in. 1702 mTmpWindow = w; 1703 } 1704 if (mTmpWindow == null) { 1705 return false; 1706 } 1707 1708 if (w.mAttrs.needsMenuKey != NEEDS_MENU_UNSET) { 1709 return true; 1710 } 1711 // If we reached the bottom of the range of windows we are considering, 1712 // assume no menu is needed. 1713 if (w == bottom) { 1714 return true; 1715 } 1716 return false; 1717 }); 1718 1719 return candidate != null && candidate.mAttrs.needsMenuKey == NEEDS_MENU_SET_TRUE; 1720 } 1721 1722 void setLayoutNeeded() { 1723 if (DEBUG_LAYOUT) Slog.w(TAG_WM, "setLayoutNeeded: callers=" + Debug.getCallers(3)); 1724 mLayoutNeeded = true; 1725 } 1726 1727 private void clearLayoutNeeded() { 1728 if (DEBUG_LAYOUT) Slog.w(TAG_WM, "clearLayoutNeeded: callers=" + Debug.getCallers(3)); 1729 mLayoutNeeded = false; 1730 } 1731 1732 boolean isLayoutNeeded() { 1733 return mLayoutNeeded; 1734 } 1735 1736 void dumpTokens(PrintWriter pw, boolean dumpAll) { 1737 if (mTokenMap.isEmpty()) { 1738 return; 1739 } 1740 pw.println(" Display #" + mDisplayId); 1741 final Iterator<WindowToken> it = mTokenMap.values().iterator(); 1742 while (it.hasNext()) { 1743 final WindowToken token = it.next(); 1744 pw.print(" "); 1745 pw.print(token); 1746 if (dumpAll) { 1747 pw.println(':'); 1748 token.dump(pw, " "); 1749 } else { 1750 pw.println(); 1751 } 1752 } 1753 } 1754 1755 void dumpWindowAnimators(PrintWriter pw, String subPrefix) { 1756 final int[] index = new int[1]; 1757 forAllWindows(w -> { 1758 final WindowStateAnimator wAnim = w.mWinAnimator; 1759 pw.println(subPrefix + "Window #" + index[0] + ": " + wAnim); 1760 index[0] = index[0] + 1; 1761 }, false /* traverseTopToBottom */); 1762 } 1763 1764 void enableSurfaceTrace(FileDescriptor fd) { 1765 forAllWindows(w -> { 1766 w.mWinAnimator.enableSurfaceTrace(fd); 1767 }, true /* traverseTopToBottom */); 1768 } 1769 1770 void disableSurfaceTrace() { 1771 forAllWindows(w -> { 1772 w.mWinAnimator.disableSurfaceTrace(); 1773 }, true /* traverseTopToBottom */); 1774 } 1775 1776 /** 1777 * Starts the Keyguard exit animation on all windows that don't belong to an app token. 1778 */ 1779 void startKeyguardExitOnNonAppWindows(boolean onWallpaper, boolean goingToShade) { 1780 final WindowManagerPolicy policy = mService.mPolicy; 1781 forAllWindows(w -> { 1782 if (w.mAppToken == null && policy.canBeHiddenByKeyguardLw(w)) { 1783 w.mWinAnimator.setAnimation( 1784 policy.createHiddenByKeyguardExit(onWallpaper, goingToShade)); 1785 } 1786 }, true /* traverseTopToBottom */); 1787 } 1788 1789 boolean checkWaitingForWindows() { 1790 1791 mHaveBootMsg = false; 1792 mHaveApp = false; 1793 mHaveWallpaper = false; 1794 mHaveKeyguard = true; 1795 1796 final WindowState visibleWindow = getWindow(w -> { 1797 if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) { 1798 return true; 1799 } 1800 if (w.isDrawnLw()) { 1801 if (w.mAttrs.type == TYPE_BOOT_PROGRESS) { 1802 mHaveBootMsg = true; 1803 } else if (w.mAttrs.type == TYPE_APPLICATION 1804 || w.mAttrs.type == TYPE_DRAWN_APPLICATION) { 1805 mHaveApp = true; 1806 } else if (w.mAttrs.type == TYPE_WALLPAPER) { 1807 mHaveWallpaper = true; 1808 } else if (w.mAttrs.type == TYPE_STATUS_BAR) { 1809 mHaveKeyguard = mService.mPolicy.isKeyguardDrawnLw(); 1810 } 1811 } 1812 return false; 1813 }); 1814 1815 if (visibleWindow != null) { 1816 // We have a visible window. 1817 return true; 1818 } 1819 1820 // if the wallpaper service is disabled on the device, we're never going to have 1821 // wallpaper, don't bother waiting for it 1822 boolean wallpaperEnabled = mService.mContext.getResources().getBoolean( 1823 com.android.internal.R.bool.config_enableWallpaperService) 1824 && !mService.mOnlyCore; 1825 1826 if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG_WM, 1827 "******** booted=" + mService.mSystemBooted 1828 + " msg=" + mService.mShowingBootMessages 1829 + " haveBoot=" + mHaveBootMsg + " haveApp=" + mHaveApp 1830 + " haveWall=" + mHaveWallpaper + " wallEnabled=" + wallpaperEnabled 1831 + " haveKeyguard=" + mHaveKeyguard); 1832 1833 // If we are turning on the screen to show the boot message, don't do it until the boot 1834 // message is actually displayed. 1835 if (!mService.mSystemBooted && !mHaveBootMsg) { 1836 return true; 1837 } 1838 1839 // If we are turning on the screen after the boot is completed normally, don't do so until 1840 // we have the application and wallpaper. 1841 if (mService.mSystemBooted 1842 && ((!mHaveApp && !mHaveKeyguard) || (wallpaperEnabled && !mHaveWallpaper))) { 1843 return true; 1844 } 1845 1846 return false; 1847 } 1848 1849 void updateWindowsForAnimator(WindowAnimator animator) { 1850 mTmpWindowAnimator = animator; 1851 forAllWindows(mUpdateWindowsForAnimator, true /* traverseTopToBottom */); 1852 } 1853 1854 void updateWallpaperForAnimator(WindowAnimator animator) { 1855 resetAnimationBackgroundAnimator(); 1856 1857 // Used to indicate a detached wallpaper. 1858 mTmpWindow = null; 1859 mTmpWindowAnimator = animator; 1860 1861 forAllWindows(mUpdateWallpaperForAnimator, true /* traverseTopToBottom */); 1862 1863 if (animator.mWindowDetachedWallpaper != mTmpWindow) { 1864 if (DEBUG_WALLPAPER) Slog.v(TAG, "Detached wallpaper changed from " 1865 + animator.mWindowDetachedWallpaper + " to " + mTmpWindow); 1866 animator.mWindowDetachedWallpaper = mTmpWindow; 1867 animator.mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE; 1868 } 1869 } 1870 1871 void prepareWindowSurfaces() { 1872 forAllWindows(mPrepareWindowSurfaces, false /* traverseTopToBottom */); 1873 } 1874 1875 boolean inputMethodClientHasFocus(IInputMethodClient client) { 1876 final WindowState imFocus = computeImeTarget(false /* updateImeTarget */); 1877 if (imFocus == null) { 1878 return false; 1879 } 1880 1881 if (DEBUG_INPUT_METHOD) { 1882 Slog.i(TAG_WM, "Desired input method target: " + imFocus); 1883 Slog.i(TAG_WM, "Current focus: " + mService.mCurrentFocus); 1884 Slog.i(TAG_WM, "Last focus: " + mService.mLastFocus); 1885 } 1886 1887 final IInputMethodClient imeClient = imFocus.mSession.mClient; 1888 1889 if (DEBUG_INPUT_METHOD) { 1890 Slog.i(TAG_WM, "IM target client: " + imeClient); 1891 if (imeClient != null) { 1892 Slog.i(TAG_WM, "IM target client binder: " + imeClient.asBinder()); 1893 Slog.i(TAG_WM, "Requesting client binder: " + client.asBinder()); 1894 } 1895 } 1896 1897 return imeClient != null && imeClient.asBinder() == client.asBinder(); 1898 } 1899 1900 boolean hasSecureWindowOnScreen() { 1901 final WindowState win = getWindow( 1902 w -> w.isOnScreen() && (w.mAttrs.flags & FLAG_SECURE) != 0); 1903 return win != null; 1904 } 1905 1906 void updateSystemUiVisibility(int visibility, int globalDiff) { 1907 forAllWindows(w -> { 1908 try { 1909 final int curValue = w.mSystemUiVisibility; 1910 final int diff = (curValue ^ visibility) & globalDiff; 1911 final int newValue = (curValue & ~diff) | (visibility & diff); 1912 if (newValue != curValue) { 1913 w.mSeq++; 1914 w.mSystemUiVisibility = newValue; 1915 } 1916 if (newValue != curValue || w.mAttrs.hasSystemUiListeners) { 1917 w.mClient.dispatchSystemUiVisibilityChanged(w.mSeq, 1918 visibility, newValue, diff); 1919 } 1920 } catch (RemoteException e) { 1921 // so sorry 1922 } 1923 }, true /* traverseTopToBottom */); 1924 } 1925 1926 void onWindowFreezeTimeout() { 1927 Slog.w(TAG_WM, "Window freeze timeout expired."); 1928 mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT; 1929 1930 forAllWindows(w -> { 1931 if (!w.mOrientationChanging) { 1932 return; 1933 } 1934 w.mOrientationChanging = false; 1935 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 1936 - mService.mDisplayFreezeTime); 1937 Slog.w(TAG_WM, "Force clearing orientation change: " + w); 1938 }, true /* traverseTopToBottom */); 1939 mService.mWindowPlacerLocked.performSurfacePlacement(); 1940 } 1941 1942 void waitForAllWindowsDrawn() { 1943 final WindowManagerPolicy policy = mService.mPolicy; 1944 forAllWindows(w -> { 1945 final boolean keyguard = policy.isKeyguardHostWindow(w.mAttrs); 1946 if (w.isVisibleLw() && (w.mAppToken != null || keyguard)) { 1947 w.mWinAnimator.mDrawState = DRAW_PENDING; 1948 // Force add to mResizingWindows. 1949 w.mLastContentInsets.set(-1, -1, -1, -1); 1950 mService.mWaitingForDrawn.add(w); 1951 } 1952 }, true /* traverseTopToBottom */); 1953 } 1954 1955 // TODO: Super crazy long method that should be broken down... 1956 boolean applySurfaceChangesTransaction(boolean recoveringMemory) { 1957 1958 final int dw = mDisplayInfo.logicalWidth; 1959 final int dh = mDisplayInfo.logicalHeight; 1960 final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked; 1961 1962 mTmpUpdateAllDrawn.clear(); 1963 1964 int repeats = 0; 1965 do { 1966 repeats++; 1967 if (repeats > 6) { 1968 Slog.w(TAG, "Animation repeat aborted after too many iterations"); 1969 clearLayoutNeeded(); 1970 break; 1971 } 1972 1973 if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("On entry to LockedInner", 1974 pendingLayoutChanges); 1975 1976 // TODO(multi-display): For now adjusting wallpaper only on primary display to avoid 1977 // the wallpaper window jumping across displays. 1978 // Remove check for default display when there will be support for multiple wallpaper 1979 // targets (on different displays). 1980 if (isDefaultDisplay && (pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) { 1981 mWallpaperController.adjustWallpaperWindows(this); 1982 } 1983 1984 if (isDefaultDisplay && (pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) { 1985 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); 1986 if (mService.updateOrientationFromAppTokensLocked(true, mDisplayId)) { 1987 setLayoutNeeded(); 1988 mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, mDisplayId).sendToTarget(); 1989 } 1990 } 1991 1992 if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_LAYOUT) != 0) { 1993 setLayoutNeeded(); 1994 } 1995 1996 // FIRST LOOP: Perform a layout, if needed. 1997 if (repeats < LAYOUT_REPEAT_THRESHOLD) { 1998 performLayout(repeats == 1, false /* updateInputWindows */); 1999 } else { 2000 Slog.w(TAG, "Layout repeat skipped after too many iterations"); 2001 } 2002 2003 // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think it is animating. 2004 pendingLayoutChanges = 0; 2005 2006 if (isDefaultDisplay) { 2007 mService.mPolicy.beginPostLayoutPolicyLw(dw, dh); 2008 forAllWindows(mApplyPostLayoutPolicy, true /* traverseTopToBottom */); 2009 pendingLayoutChanges |= mService.mPolicy.finishPostLayoutPolicyLw(); 2010 if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats( 2011 "after finishPostLayoutPolicyLw", pendingLayoutChanges); 2012 } 2013 } while (pendingLayoutChanges != 0); 2014 2015 mTmpApplySurfaceChangesTransactionState.reset(); 2016 resetDimming(); 2017 2018 mTmpRecoveringMemory = recoveringMemory; 2019 forAllWindows(mApplySurfaceChangesTransaction, true /* traverseTopToBottom */); 2020 2021 mService.mDisplayManagerInternal.setDisplayProperties(mDisplayId, 2022 mTmpApplySurfaceChangesTransactionState.displayHasContent, 2023 mTmpApplySurfaceChangesTransactionState.preferredRefreshRate, 2024 mTmpApplySurfaceChangesTransactionState.preferredModeId, 2025 true /* inTraversal, must call performTraversalInTrans... below */); 2026 2027 stopDimmingIfNeeded(); 2028 2029 while (!mTmpUpdateAllDrawn.isEmpty()) { 2030 final AppWindowToken atoken = mTmpUpdateAllDrawn.removeLast(); 2031 // See if any windows have been drawn, so they (and others associated with them) 2032 // can now be shown. 2033 atoken.updateAllDrawn(this); 2034 } 2035 2036 return mTmpApplySurfaceChangesTransactionState.focusDisplayed; 2037 } 2038 2039 void performLayout(boolean initial, boolean updateInputWindows) { 2040 if (!isLayoutNeeded()) { 2041 return; 2042 } 2043 clearLayoutNeeded(); 2044 2045 final int dw = mDisplayInfo.logicalWidth; 2046 final int dh = mDisplayInfo.logicalHeight; 2047 2048 if (DEBUG_LAYOUT) { 2049 Slog.v(TAG, "-------------------------------------"); 2050 Slog.v(TAG, "performLayout: needed=" + isLayoutNeeded() + " dw=" + dw + " dh=" + dh); 2051 } 2052 2053 mService.mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mService.mRotation, 2054 getConfiguration().uiMode); 2055 if (isDefaultDisplay) { 2056 // Not needed on non-default displays. 2057 mService.mSystemDecorLayer = mService.mPolicy.getSystemDecorLayerLw(); 2058 mService.mScreenRect.set(0, 0, dw, dh); 2059 } 2060 2061 mService.mPolicy.getContentRectLw(mContentRect); 2062 2063 int seq = mService.mLayoutSeq + 1; 2064 if (seq < 0) seq = 0; 2065 mService.mLayoutSeq = seq; 2066 2067 // Used to indicate that we have processed the dream window and all additional windows are 2068 // behind it. 2069 mTmpWindow = null; 2070 mTmpInitial = initial; 2071 2072 // First perform layout of any root windows (not attached to another window). 2073 forAllWindows(mPerformLayout, true /* traverseTopToBottom */); 2074 2075 // Used to indicate that we have processed the dream window and all additional attached 2076 // windows are behind it. 2077 mTmpWindow2 = mTmpWindow; 2078 mTmpWindow = null; 2079 2080 // Now perform layout of attached windows, which usually depend on the position of the 2081 // window they are attached to. XXX does not deal with windows that are attached to windows 2082 // that are themselves attached. 2083 forAllWindows(mPerformLayoutAttached, true /* traverseTopToBottom */); 2084 2085 // Window frames may have changed. Tell the input dispatcher about it. 2086 mService.mInputMonitor.layoutInputConsumers(dw, dh); 2087 mService.mInputMonitor.setUpdateInputWindowsNeededLw(); 2088 if (updateInputWindows) { 2089 mService.mInputMonitor.updateInputWindowsLw(false /*force*/); 2090 } 2091 2092 mService.mPolicy.finishLayoutLw(); 2093 mService.mH.sendEmptyMessage(UPDATE_DOCKED_STACK_DIVIDER); 2094 } 2095 2096 /** 2097 * Takes a snapshot of the display. In landscape mode this grabs the whole screen. 2098 * In portrait mode, it grabs the full screenshot. 2099 * 2100 * @param width the width of the target bitmap 2101 * @param height the height of the target bitmap 2102 * @param includeFullDisplay true if the screen should not be cropped before capture 2103 * @param frameScale the scale to apply to the frame, only used when width = -1 and height = -1 2104 * @param config of the output bitmap 2105 * @param wallpaperOnly true if only the wallpaper layer should be included in the screenshot 2106 * @param includeDecor whether to include window decors, like the status or navigation bar 2107 * background of the window 2108 * @param toAshmem whether to convert the resulting bitmap to ashmem; this should be set to 2109 * true if the Bitmap is sent over binder, and false otherwise 2110 */ 2111 Bitmap screenshotApplications(IBinder appToken, int width, int height, 2112 boolean includeFullDisplay, float frameScale, Bitmap.Config config, 2113 boolean wallpaperOnly, boolean includeDecor, boolean toAshmem) { 2114 int dw = mDisplayInfo.logicalWidth; 2115 int dh = mDisplayInfo.logicalHeight; 2116 if (dw == 0 || dh == 0) { 2117 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken 2118 + ": returning null. logical widthxheight=" + dw + "x" + dh); 2119 return null; 2120 } 2121 2122 Bitmap bm = null; 2123 2124 mScreenshotApplicationState.reset(appToken == null && !wallpaperOnly); 2125 final Rect frame = new Rect(); 2126 final Rect stackBounds = new Rect(); 2127 2128 boolean includeImeInScreenshot; 2129 synchronized(mService.mWindowMap) { 2130 final AppWindowToken imeTargetAppToken = mService.mInputMethodTarget != null 2131 ? mService.mInputMethodTarget.mAppToken : null; 2132 // We only include the Ime in the screenshot if the app we are screenshoting is the IME 2133 // target and isn't in multi-window mode. We don't screenshot the IME in multi-window 2134 // mode because the frame of the IME might not overlap with that of the app. 2135 // E.g. IME target app at the top in split-screen mode and the IME at the bottom 2136 // overlapping with the bottom app. 2137 includeImeInScreenshot = imeTargetAppToken != null 2138 && imeTargetAppToken.appToken != null 2139 && imeTargetAppToken.appToken.asBinder() == appToken 2140 && !mService.mInputMethodTarget.isInMultiWindowMode(); 2141 } 2142 2143 final int aboveAppLayer = (mService.mPolicy.windowTypeToLayerLw(TYPE_APPLICATION) + 1) 2144 * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET; 2145 final MutableBoolean mutableIncludeFullDisplay = new MutableBoolean(includeFullDisplay); 2146 synchronized(mService.mWindowMap) { 2147 // Figure out the part of the screen that is actually the app. 2148 mScreenshotApplicationState.appWin = null; 2149 forAllWindows(w -> { 2150 if (!w.mHasSurface) { 2151 return false; 2152 } 2153 if (w.mLayer >= aboveAppLayer) { 2154 return false; 2155 } 2156 if (wallpaperOnly && !w.mIsWallpaper) { 2157 return false; 2158 } 2159 if (w.mIsImWindow) { 2160 if (!includeImeInScreenshot) { 2161 return false; 2162 } 2163 } else if (w.mIsWallpaper) { 2164 // If this is the wallpaper layer and we're only looking for the wallpaper layer 2165 // then the target window state is this one. 2166 if (wallpaperOnly) { 2167 mScreenshotApplicationState.appWin = w; 2168 } 2169 2170 if (mScreenshotApplicationState.appWin == null) { 2171 // We have not ran across the target window yet, so it is probably behind 2172 // the wallpaper. This can happen when the keyguard is up and all windows 2173 // are moved behind the wallpaper. We don't want to include the wallpaper 2174 // layer in the screenshot as it will cover-up the layer of the target 2175 // window. 2176 return false; 2177 } 2178 // Fall through. The target window is in front of the wallpaper. For this 2179 // case we want to include the wallpaper layer in the screenshot because 2180 // the target window might have some transparent areas. 2181 } else if (appToken != null) { 2182 if (w.mAppToken == null || w.mAppToken.token != appToken) { 2183 // This app window is of no interest if it is not associated with the 2184 // screenshot app. 2185 return false; 2186 } 2187 mScreenshotApplicationState.appWin = w; 2188 } 2189 2190 // Include this window. 2191 2192 final WindowStateAnimator winAnim = w.mWinAnimator; 2193 int layer = winAnim.mSurfaceController.getLayer(); 2194 if (mScreenshotApplicationState.maxLayer < layer) { 2195 mScreenshotApplicationState.maxLayer = layer; 2196 } 2197 if (mScreenshotApplicationState.minLayer > layer) { 2198 mScreenshotApplicationState.minLayer = layer; 2199 } 2200 2201 // Don't include wallpaper in bounds calculation 2202 if (includeDecor && !stackBounds.isEmpty()) { 2203 frame.set(stackBounds); 2204 } else if (includeDecor) { 2205 mutableIncludeFullDisplay.value = true; 2206 } else if (!mutableIncludeFullDisplay.value && !w.mIsWallpaper) { 2207 final Rect wf = w.mFrame; 2208 final Rect cr = w.mContentInsets; 2209 int left = wf.left + cr.left; 2210 int top = wf.top + cr.top; 2211 int right = wf.right - cr.right; 2212 int bottom = wf.bottom - cr.bottom; 2213 frame.union(left, top, right, bottom); 2214 w.getVisibleBounds(stackBounds); 2215 if (!Rect.intersects(frame, stackBounds)) { 2216 // Set frame empty if there's no intersection. 2217 frame.setEmpty(); 2218 } 2219 } 2220 2221 final boolean foundTargetWs = 2222 (w.mAppToken != null && w.mAppToken.token == appToken) 2223 || (mScreenshotApplicationState.appWin != null && wallpaperOnly); 2224 if (foundTargetWs && w.isDisplayedLw() && winAnim.getShown()) { 2225 mScreenshotApplicationState.screenshotReady = true; 2226 } 2227 2228 if (w.isObscuringDisplay()){ 2229 return true; 2230 } 2231 return false; 2232 }, true /* traverseTopToBottom */); 2233 2234 final WindowState appWin = mScreenshotApplicationState.appWin; 2235 final boolean screenshotReady = mScreenshotApplicationState.screenshotReady; 2236 final int maxLayer = mScreenshotApplicationState.maxLayer; 2237 final int minLayer = mScreenshotApplicationState.minLayer; 2238 2239 if (appToken != null && appWin == null) { 2240 // Can't find a window to snapshot. 2241 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, 2242 "Screenshot: Couldn't find a surface matching " + appToken); 2243 return null; 2244 } 2245 2246 if (!screenshotReady) { 2247 Slog.i(TAG_WM, "Failed to capture screenshot of " + appToken + 2248 " appWin=" + (appWin == null ? "null" : (appWin + " drawState=" + 2249 appWin.mWinAnimator.mDrawState))); 2250 return null; 2251 } 2252 2253 // Screenshot is ready to be taken. Everything from here below will continue 2254 // through the bottom of the loop and return a value. We only stay in the loop 2255 // because we don't want to release the mWindowMap lock until the screenshot is 2256 // taken. 2257 2258 if (maxLayer == 0) { 2259 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken 2260 + ": returning null maxLayer=" + maxLayer); 2261 return null; 2262 } 2263 2264 if (!mutableIncludeFullDisplay.value) { 2265 // Constrain frame to the screen size. 2266 if (!frame.intersect(0, 0, dw, dh)) { 2267 frame.setEmpty(); 2268 } 2269 } else { 2270 // Caller just wants entire display. 2271 frame.set(0, 0, dw, dh); 2272 } 2273 if (frame.isEmpty()) { 2274 return null; 2275 } 2276 2277 if (width < 0) { 2278 width = (int) (frame.width() * frameScale); 2279 } 2280 if (height < 0) { 2281 height = (int) (frame.height() * frameScale); 2282 } 2283 2284 // Tell surface flinger what part of the image to crop. Take the top 2285 // right part of the application, and crop the larger dimension to fit. 2286 Rect crop = new Rect(frame); 2287 if (width / (float) frame.width() < height / (float) frame.height()) { 2288 int cropWidth = (int)((float)width / (float)height * frame.height()); 2289 crop.right = crop.left + cropWidth; 2290 } else { 2291 int cropHeight = (int)((float)height / (float)width * frame.width()); 2292 crop.bottom = crop.top + cropHeight; 2293 } 2294 2295 // The screenshot API does not apply the current screen rotation. 2296 int rot = mDisplay.getRotation(); 2297 2298 if (rot == ROTATION_90 || rot == ROTATION_270) { 2299 rot = (rot == ROTATION_90) ? ROTATION_270 : ROTATION_90; 2300 } 2301 2302 // Surfaceflinger is not aware of orientation, so convert our logical 2303 // crop to surfaceflinger's portrait orientation. 2304 convertCropForSurfaceFlinger(crop, rot, dw, dh); 2305 2306 if (DEBUG_SCREENSHOT) { 2307 Slog.i(TAG_WM, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to " 2308 + maxLayer + " appToken=" + appToken); 2309 forAllWindows(w -> { 2310 final WindowSurfaceController controller = w.mWinAnimator.mSurfaceController; 2311 Slog.i(TAG_WM, w + ": " + w.mLayer 2312 + " animLayer=" + w.mWinAnimator.mAnimLayer 2313 + " surfaceLayer=" + ((controller == null) 2314 ? "null" : controller.getLayer())); 2315 }, false /* traverseTopToBottom */); 2316 } 2317 2318 final ScreenRotationAnimation screenRotationAnimation = 2319 mService.mAnimator.getScreenRotationAnimationLocked(DEFAULT_DISPLAY); 2320 final boolean inRotation = screenRotationAnimation != null && 2321 screenRotationAnimation.isAnimating(); 2322 if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG_WM, 2323 "Taking screenshot while rotating"); 2324 2325 // We force pending transactions to flush before taking 2326 // the screenshot by pushing an empty synchronous transaction. 2327 SurfaceControl.openTransaction(); 2328 SurfaceControl.closeTransactionSync(); 2329 2330 bm = SurfaceControl.screenshot(crop, width, height, minLayer, maxLayer, 2331 inRotation, rot); 2332 if (bm == null) { 2333 Slog.w(TAG_WM, "Screenshot failure taking screenshot for (" + dw + "x" + dh 2334 + ") to layer " + maxLayer); 2335 return null; 2336 } 2337 } 2338 2339 if (DEBUG_SCREENSHOT) { 2340 // TEST IF IT's ALL BLACK 2341 int[] buffer = new int[bm.getWidth() * bm.getHeight()]; 2342 bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight()); 2343 boolean allBlack = true; 2344 final int firstColor = buffer[0]; 2345 for (int i = 0; i < buffer.length; i++) { 2346 if (buffer[i] != firstColor) { 2347 allBlack = false; 2348 break; 2349 } 2350 } 2351 if (allBlack) { 2352 final WindowState appWin = mScreenshotApplicationState.appWin; 2353 final int maxLayer = mScreenshotApplicationState.maxLayer; 2354 final int minLayer = mScreenshotApplicationState.minLayer; 2355 Slog.i(TAG_WM, "Screenshot " + appWin + " was monochrome(" + 2356 Integer.toHexString(firstColor) + ")! mSurfaceLayer=" + 2357 (appWin != null ? 2358 appWin.mWinAnimator.mSurfaceController.getLayer() : "null") + 2359 " minLayer=" + minLayer + " maxLayer=" + maxLayer); 2360 } 2361 } 2362 2363 // Create a copy of the screenshot that is immutable and backed in ashmem. 2364 // This greatly reduces the overhead of passing the bitmap between processes. 2365 if (toAshmem) { 2366 Bitmap ret = bm.createAshmemBitmap(config); 2367 bm.recycle(); 2368 return ret; 2369 } else { 2370 return bm; 2371 } 2372 } 2373 2374 // TODO: Can this use createRotationMatrix()? 2375 private static void convertCropForSurfaceFlinger(Rect crop, int rot, int dw, int dh) { 2376 if (rot == Surface.ROTATION_90) { 2377 final int tmp = crop.top; 2378 crop.top = dw - crop.right; 2379 crop.right = crop.bottom; 2380 crop.bottom = dw - crop.left; 2381 crop.left = tmp; 2382 } else if (rot == Surface.ROTATION_180) { 2383 int tmp = crop.top; 2384 crop.top = dh - crop.bottom; 2385 crop.bottom = dh - tmp; 2386 tmp = crop.right; 2387 crop.right = dw - crop.left; 2388 crop.left = dw - tmp; 2389 } else if (rot == Surface.ROTATION_270) { 2390 final int tmp = crop.top; 2391 crop.top = crop.left; 2392 crop.left = dh - crop.bottom; 2393 crop.bottom = crop.right; 2394 crop.right = dh - tmp; 2395 } 2396 } 2397 2398 void onSeamlessRotationTimeout() { 2399 // Used to indicate the layout is needed. 2400 mTmpWindow = null; 2401 2402 forAllWindows(w -> { 2403 if (!w.mSeamlesslyRotated) { 2404 return; 2405 } 2406 mTmpWindow = w; 2407 w.setDisplayLayoutNeeded(); 2408 mService.markForSeamlessRotation(w, false); 2409 }, true /* traverseTopToBottom */); 2410 2411 if (mTmpWindow != null) { 2412 mService.mWindowPlacerLocked.performSurfacePlacement(); 2413 } 2414 } 2415 2416 static final class TaskForResizePointSearchResult { 2417 boolean searchDone; 2418 Task taskForResize; 2419 2420 void reset() { 2421 searchDone = false; 2422 taskForResize = null; 2423 } 2424 } 2425 2426 private static final class ApplySurfaceChangesTransactionState { 2427 boolean displayHasContent; 2428 boolean obscured; 2429 boolean syswin; 2430 boolean focusDisplayed; 2431 float preferredRefreshRate; 2432 int preferredModeId; 2433 2434 void reset() { 2435 displayHasContent = false; 2436 obscured = false; 2437 syswin = false; 2438 focusDisplayed = false; 2439 preferredRefreshRate = 0; 2440 preferredModeId = 0; 2441 } 2442 } 2443 2444 private static final class ScreenshotApplicationState { 2445 WindowState appWin; 2446 int maxLayer; 2447 int minLayer; 2448 boolean screenshotReady; 2449 2450 void reset(boolean screenshotReady) { 2451 appWin = null; 2452 maxLayer = 0; 2453 minLayer = 0; 2454 this.screenshotReady = screenshotReady; 2455 minLayer = (screenshotReady) ? 0 : Integer.MAX_VALUE; 2456 } 2457 } 2458 2459 /** 2460 * Base class for any direct child window container of {@link #DisplayContent} need to inherit 2461 * from. This is mainly a pass through class that allows {@link #DisplayContent} to have 2462 * homogeneous children type which is currently required by sub-classes of 2463 * {@link WindowContainer} class. 2464 */ 2465 static class DisplayChildWindowContainer<E extends WindowContainer> extends WindowContainer<E> { 2466 2467 int size() { 2468 return mChildren.size(); 2469 } 2470 2471 E get(int index) { 2472 return mChildren.get(index); 2473 } 2474 2475 @Override 2476 boolean fillsParent() { 2477 return true; 2478 } 2479 2480 @Override 2481 boolean isVisible() { 2482 return true; 2483 } 2484 } 2485 2486 /** 2487 * Window container class that contains all containers on this display relating to Apps. 2488 * I.e Activities. 2489 */ 2490 private final class TaskStackContainers extends DisplayChildWindowContainer<TaskStack> { 2491 2492 /** 2493 * Adds the stack to this container. 2494 * @see WindowManagerService#addStackToDisplay(int, int, boolean) 2495 */ 2496 void addStackToDisplay(TaskStack stack, boolean onTop) { 2497 if (stack.mStackId == HOME_STACK_ID) { 2498 if (mHomeStack != null) { 2499 throw new IllegalArgumentException("attachStack: HOME_STACK_ID (0) not first."); 2500 } 2501 mHomeStack = stack; 2502 } 2503 addChild(stack, onTop); 2504 stack.onDisplayChanged(DisplayContent.this); 2505 } 2506 2507 /** Removes the stack from its container and prepare for changing the parent. */ 2508 void removeStackFromDisplay(TaskStack stack) { 2509 removeChild(stack); 2510 stack.onRemovedFromDisplay(); 2511 } 2512 2513 private void addChild(TaskStack stack, boolean toTop) { 2514 final int addIndex = findPositionForStack(toTop ? mChildren.size() : 0, stack, 2515 true /* adding */); 2516 addChild(stack, addIndex); 2517 setLayoutNeeded(); 2518 } 2519 2520 @Override 2521 void positionChildAt(int position, TaskStack child, boolean includingParents) { 2522 if (StackId.isAlwaysOnTop(child.mStackId) && position != POSITION_TOP) { 2523 // This stack is always-on-top, override the default behavior. 2524 Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + this + " to bottom"); 2525 2526 // Moving to its current position, as we must call super but we don't want to 2527 // perform any meaningful action. 2528 final int currentPosition = mChildren.indexOf(child); 2529 super.positionChildAt(currentPosition, child, false /* includingParents */); 2530 return; 2531 } 2532 2533 final int targetPosition = findPositionForStack(position, child, false /* adding */); 2534 super.positionChildAt(targetPosition, child, includingParents); 2535 2536 setLayoutNeeded(); 2537 } 2538 2539 /** 2540 * When stack is added or repositioned, find a proper position for it. 2541 * This will make sure that pinned stack always stays on top. 2542 * @param requestedPosition Position requested by caller. 2543 * @param stack Stack to be added or positioned. 2544 * @param adding Flag indicates whether we're adding a new stack or positioning an existing. 2545 * @return The proper position for the stack. 2546 */ 2547 private int findPositionForStack(int requestedPosition, TaskStack stack, boolean adding) { 2548 final int topChildPosition = mChildren.size() - 1; 2549 boolean toTop = requestedPosition == POSITION_TOP; 2550 toTop |= adding ? requestedPosition >= topChildPosition + 1 2551 : requestedPosition >= topChildPosition; 2552 int targetPosition = requestedPosition; 2553 2554 if (toTop 2555 && mService.isStackVisibleLocked(PINNED_STACK_ID) 2556 && stack.mStackId != PINNED_STACK_ID) { 2557 // The pinned stack is always the top most stack (always-on-top) when it is visible. 2558 TaskStack topStack = mChildren.get(topChildPosition); 2559 if (topStack.mStackId != PINNED_STACK_ID) { 2560 throw new IllegalStateException("Pinned stack isn't top stack??? " + mChildren); 2561 } 2562 2563 // So, stack is moved just below the pinned stack. 2564 // When we're adding a new stack the target is the current pinned stack position. 2565 // When we're positioning an existing stack the target is the position below pinned 2566 // stack, because WindowContainer#positionAt() first removes element and then adds it 2567 // to specified place. 2568 targetPosition = adding ? topChildPosition : topChildPosition - 1; 2569 } 2570 2571 return targetPosition; 2572 } 2573 2574 @Override 2575 boolean forAllWindows(ToBooleanFunction<WindowState> callback, 2576 boolean traverseTopToBottom) { 2577 if (traverseTopToBottom) { 2578 if (super.forAllWindows(callback, traverseTopToBottom)) { 2579 return true; 2580 } 2581 if (forAllExitingAppTokenWindows(callback, traverseTopToBottom)) { 2582 return true; 2583 } 2584 } else { 2585 if (forAllExitingAppTokenWindows(callback, traverseTopToBottom)) { 2586 return true; 2587 } 2588 if (super.forAllWindows(callback, traverseTopToBottom)) { 2589 return true; 2590 } 2591 } 2592 return false; 2593 } 2594 2595 private boolean forAllExitingAppTokenWindows(ToBooleanFunction<WindowState> callback, 2596 boolean traverseTopToBottom) { 2597 // For legacy reasons we process the TaskStack.mExitingAppTokens first here before the 2598 // app tokens. 2599 // TODO: Investigate if we need to continue to do this or if we can just process them 2600 // in-order. 2601 if (traverseTopToBottom) { 2602 for (int i = mChildren.size() - 1; i >= 0; --i) { 2603 final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens; 2604 for (int j = appTokens.size() - 1; j >= 0; --j) { 2605 if (appTokens.get(j).forAllWindowsUnchecked(callback, 2606 traverseTopToBottom)) { 2607 return true; 2608 } 2609 } 2610 } 2611 } else { 2612 final int count = mChildren.size(); 2613 for (int i = 0; i < count; ++i) { 2614 final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens; 2615 final int appTokensCount = appTokens.size(); 2616 for (int j = 0; j < appTokensCount; j++) { 2617 if (appTokens.get(j).forAllWindowsUnchecked(callback, 2618 traverseTopToBottom)) { 2619 return true; 2620 } 2621 } 2622 } 2623 } 2624 return false; 2625 } 2626 2627 @Override 2628 int getOrientation() { 2629 if (mService.isStackVisibleLocked(DOCKED_STACK_ID) 2630 || mService.isStackVisibleLocked(FREEFORM_WORKSPACE_STACK_ID)) { 2631 // Apps and their containers are not allowed to specify an orientation while the 2632 // docked or freeform stack is visible...except for the home stack/task if the 2633 // docked stack is minimized and it actually set something. 2634 if (mHomeStack != null && mHomeStack.isVisible() 2635 && mDividerControllerLocked.isMinimizedDock()) { 2636 final int orientation = mHomeStack.getOrientation(); 2637 if (orientation != SCREEN_ORIENTATION_UNSET) { 2638 return orientation; 2639 } 2640 } 2641 return SCREEN_ORIENTATION_UNSPECIFIED; 2642 } 2643 2644 final int orientation = super.getOrientation(); 2645 if (orientation != SCREEN_ORIENTATION_UNSET 2646 && orientation != SCREEN_ORIENTATION_BEHIND) { 2647 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, 2648 "App is requesting an orientation, return " + orientation); 2649 return orientation; 2650 } 2651 2652 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, 2653 "No app is requesting an orientation, return " + mService.mLastOrientation); 2654 // The next app has not been requested to be visible, so we keep the current orientation 2655 // to prevent freezing/unfreezing the display too early. 2656 return mService.mLastOrientation; 2657 } 2658 } 2659 2660 /** 2661 * Window container class that contains all containers on this display that are not related to 2662 * Apps. E.g. status bar. 2663 */ 2664 private final class NonAppWindowContainers extends DisplayChildWindowContainer<WindowToken> { 2665 /** 2666 * Compares two child window tokens returns -1 if the first is lesser than the second in 2667 * terms of z-order and 1 otherwise. 2668 */ 2669 private final Comparator<WindowToken> mWindowComparator = (token1, token2) -> 2670 // Tokens with higher base layer are z-ordered on-top. 2671 mService.mPolicy.windowTypeToLayerLw(token1.windowType) 2672 < mService.mPolicy.windowTypeToLayerLw(token2.windowType) ? -1 : 1; 2673 2674 private final Predicate<WindowState> mGetOrientingWindow = w -> { 2675 if (!w.isVisibleLw() || !w.mPolicyVisibilityAfterAnim) { 2676 return false; 2677 } 2678 final int req = w.mAttrs.screenOrientation; 2679 if(req == SCREEN_ORIENTATION_UNSPECIFIED || req == SCREEN_ORIENTATION_BEHIND 2680 || req == SCREEN_ORIENTATION_UNSET) { 2681 return false; 2682 } 2683 return true; 2684 }; 2685 2686 private final String mName; 2687 NonAppWindowContainers(String name) { 2688 mName = name; 2689 } 2690 2691 void addChild(WindowToken token) { 2692 addChild(token, mWindowComparator); 2693 } 2694 2695 @Override 2696 int getOrientation() { 2697 final WindowManagerPolicy policy = mService.mPolicy; 2698 // Find a window requesting orientation. 2699 final WindowState win = getWindow(mGetOrientingWindow); 2700 2701 if (win != null) { 2702 final int req = win.mAttrs.screenOrientation; 2703 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, win + " forcing orientation to " + req); 2704 if (policy.isKeyguardHostWindow(win.mAttrs)) { 2705 mService.mLastKeyguardForcedOrientation = req; 2706 } 2707 return (mService.mLastWindowForcedOrientation = req); 2708 } 2709 2710 mService.mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED; 2711 2712 if (policy.isKeyguardShowingAndNotOccluded()) { 2713 return mService.mLastKeyguardForcedOrientation; 2714 } 2715 2716 return SCREEN_ORIENTATION_UNSET; 2717 } 2718 2719 @Override 2720 String getName() { 2721 return mName; 2722 } 2723 } 2724} 2725