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