DisplayContent.java revision 5d7e7f136e349e6cde86943dd03e7edd9ec92e6e
1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server.wm; 18 19import static android.app.ActivityManager.StackId.DOCKED_STACK_ID; 20import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID; 21import static android.app.ActivityManager.StackId.HOME_STACK_ID; 22import static android.app.ActivityManager.StackId.PINNED_STACK_ID; 23import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND; 24import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET; 25import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 26import static android.view.Display.DEFAULT_DISPLAY; 27import static android.view.Display.FLAG_PRIVATE; 28import static android.view.Surface.ROTATION_0; 29import static android.view.Surface.ROTATION_180; 30import static android.view.Surface.ROTATION_270; 31import static android.view.Surface.ROTATION_90; 32import static android.view.View.GONE; 33import static android.view.WindowManager.DOCKED_BOTTOM; 34import static android.view.WindowManager.DOCKED_INVALID; 35import static android.view.WindowManager.DOCKED_TOP; 36import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 37import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; 38import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; 39import static android.view.WindowManager.LayoutParams.FLAG_SECURE; 40import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; 41import static android.view.WindowManager.LayoutParams.NEEDS_MENU_SET_TRUE; 42import static android.view.WindowManager.LayoutParams.NEEDS_MENU_UNSET; 43import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; 44import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; 45import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; 46import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS; 47import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION; 48import static android.view.WindowManager.LayoutParams.TYPE_DREAM; 49import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; 50import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; 51import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; 52import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG; 53import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR; 54import static android.view.WindowManager.LayoutParams.TYPE_TOAST; 55import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; 56import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; 57import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG; 58import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 59import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 60import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT; 61import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY; 62import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS; 63import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT; 64import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD; 65import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS; 66import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT; 67import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS; 68import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION; 69import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT; 70import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREEN_ON; 71import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK; 72import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER; 73import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT; 74import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS; 75import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS; 76import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; 77import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 78import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION; 79import static com.android.server.wm.WindowManagerService.H.UPDATE_DOCKED_STACK_DIVIDER; 80import static com.android.server.wm.WindowManagerService.H.WINDOW_HIDE_TIMEOUT; 81import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD; 82import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER; 83import static com.android.server.wm.WindowManagerService.TYPE_LAYER_OFFSET; 84import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES; 85import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_TIMEOUT; 86import static com.android.server.wm.WindowManagerService.dipToPixel; 87import static com.android.server.wm.WindowManagerService.logSurface; 88import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP; 89import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING; 90import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW; 91import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE; 92 93import android.annotation.NonNull; 94import android.app.ActivityManager.StackId; 95import android.content.res.Configuration; 96import android.graphics.Bitmap; 97import android.graphics.Matrix; 98import android.graphics.Rect; 99import android.graphics.RectF; 100import android.graphics.Region; 101import android.graphics.Region.Op; 102import android.hardware.display.DisplayManagerInternal; 103import android.os.Debug; 104import android.os.Handler; 105import android.os.IBinder; 106import android.os.RemoteException; 107import android.os.SystemClock; 108import android.util.DisplayMetrics; 109import android.util.Slog; 110import android.view.Display; 111import android.view.DisplayInfo; 112import android.view.Surface; 113import android.view.SurfaceControl; 114import android.view.WindowManagerPolicy; 115 116import com.android.internal.util.ToBooleanFunction; 117import com.android.internal.view.IInputMethodClient; 118 119import java.io.FileDescriptor; 120import java.io.PrintWriter; 121import java.util.ArrayList; 122import java.util.Comparator; 123import java.util.HashMap; 124import java.util.Iterator; 125import java.util.LinkedList; 126import java.util.List; 127import java.util.function.Consumer; 128import java.util.function.Predicate; 129 130/** 131 * Utility class for keeping track of the WindowStates and other pertinent contents of a 132 * particular Display. 133 * 134 * IMPORTANT: No method from this class should ever be used without holding 135 * WindowManagerService.mWindowMap. 136 */ 137class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowContainer> { 138 private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayContent" : TAG_WM; 139 140 /** Unique identifier of this stack. */ 141 private final int mDisplayId; 142 143 /** The containers below are the only child containers the display can have. */ 144 // Contains all window containers that are related to apps (Activities) 145 private final TaskStackContainers mTaskStackContainers = new TaskStackContainers(); 146 // Contains all non-app window containers that should be displayed above the app containers 147 // (e.g. Status bar) 148 private final NonAppWindowContainers mAboveAppWindowsContainers = 149 new NonAppWindowContainers("mAboveAppWindowsContainers"); 150 // Contains all non-app window containers that should be displayed below the app containers 151 // (e.g. Wallpaper). 152 private final NonAppWindowContainers mBelowAppWindowsContainers = 153 new NonAppWindowContainers("mBelowAppWindowsContainers"); 154 // Contains all IME window containers. Note that the z-ordering of the IME windows will depend 155 // on the IME target. We mainly have this container grouping so we can keep track of all the IME 156 // window containers together and move them in-sync if/when needed. 157 private final NonAppWindowContainers mImeWindowsContainers = 158 new NonAppWindowContainers("mImeWindowsContainers"); 159 160 private WindowState mTmpWindow; 161 private WindowState mTmpWindow2; 162 private WindowAnimator mTmpWindowAnimator; 163 private boolean mTmpRecoveringMemory; 164 private boolean mUpdateImeTarget; 165 private boolean mTmpInitial; 166 167 // Mapping from a token IBinder to a WindowToken object on this display. 168 private final HashMap<IBinder, WindowToken> mTokenMap = new HashMap(); 169 170 int mInitialDisplayWidth = 0; 171 int mInitialDisplayHeight = 0; 172 int mInitialDisplayDensity = 0; 173 int mBaseDisplayWidth = 0; 174 int mBaseDisplayHeight = 0; 175 int mBaseDisplayDensity = 0; 176 boolean mDisplayScalingDisabled; 177 private final DisplayInfo mDisplayInfo = new DisplayInfo(); 178 private final Display mDisplay; 179 private final DisplayMetrics mDisplayMetrics = new DisplayMetrics(); 180 181 Rect mBaseDisplayRect = new Rect(); 182 private Rect mContentRect = new Rect(); 183 184 // Accessed directly by all users. 185 private boolean mLayoutNeeded; 186 int pendingLayoutChanges; 187 // TODO(multi-display): remove some of the usages. 188 boolean isDefaultDisplay; 189 190 /** Window tokens that are in the process of exiting, but still on screen for animations. */ 191 final ArrayList<WindowToken> mExitingTokens = new ArrayList<>(); 192 193 /** A special TaskStack with id==HOME_STACK_ID that moves to the bottom whenever any TaskStack 194 * (except a future lockscreen TaskStack) moves to the top. */ 195 private TaskStack mHomeStack = null; 196 197 /** Detect user tapping outside of current focused task bounds .*/ 198 TaskTapPointerEventListener mTapDetector; 199 200 /** Detect user tapping outside of current focused stack bounds .*/ 201 private Region mTouchExcludeRegion = new Region(); 202 203 /** Save allocating when calculating rects */ 204 private final Rect mTmpRect = new Rect(); 205 private final Rect mTmpRect2 = new Rect(); 206 private final RectF mTmpRectF = new RectF(); 207 private final Matrix mTmpMatrix = new Matrix(); 208 private final Region mTmpRegion = new Region(); 209 210 WindowManagerService mService; 211 212 /** Remove this display when animation on it has completed. */ 213 private boolean mDeferredRemoval; 214 215 final DockedStackDividerController mDividerControllerLocked; 216 final PinnedStackController mPinnedStackControllerLocked; 217 218 DimLayerController mDimLayerController; 219 220 final ArrayList<WindowState> mTapExcludedWindows = new ArrayList<>(); 221 222 private boolean mHaveBootMsg = false; 223 private boolean mHaveApp = false; 224 private boolean mHaveWallpaper = false; 225 private boolean mHaveKeyguard = true; 226 227 private final LinkedList<AppWindowToken> mTmpUpdateAllDrawn = new LinkedList(); 228 229 private final TaskForResizePointSearchResult mTmpTaskForResizePointSearchResult = 230 new TaskForResizePointSearchResult(); 231 private final ApplySurfaceChangesTransactionState mTmpApplySurfaceChangesTransactionState = 232 new ApplySurfaceChangesTransactionState(); 233 private final ScreenshotApplicationState mScreenshotApplicationState = 234 new ScreenshotApplicationState(); 235 236 // True if this display is in the process of being removed. Used to determine if the removal of 237 // the display's direct children should be allowed. 238 private boolean mRemovingDisplay = false; 239 240 private final WindowLayersController mLayersController; 241 WallpaperController mWallpaperController; 242 int mInputMethodAnimLayerAdjustment; 243 244 private final Consumer<WindowState> mUpdateWindowsForAnimator = w -> { 245 WindowStateAnimator winAnimator = w.mWinAnimator; 246 if (winAnimator.hasSurface()) { 247 final boolean wasAnimating = winAnimator.mWasAnimating; 248 final boolean nowAnimating = winAnimator.stepAnimationLocked( 249 mTmpWindowAnimator.mCurrentTime); 250 winAnimator.mWasAnimating = nowAnimating; 251 mTmpWindowAnimator.orAnimating(nowAnimating); 252 253 if (DEBUG_WALLPAPER) Slog.v(TAG, 254 w + ": wasAnimating=" + wasAnimating + ", nowAnimating=" + nowAnimating); 255 256 if (wasAnimating && !winAnimator.mAnimating 257 && mWallpaperController.isWallpaperTarget(w)) { 258 mTmpWindowAnimator.mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE; 259 pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 260 if (DEBUG_LAYOUT_REPEATS) { 261 mService.mWindowPlacerLocked.debugLayoutRepeats( 262 "updateWindowsAndWallpaperLocked 2", pendingLayoutChanges); 263 } 264 } 265 } 266 267 final AppWindowToken atoken = w.mAppToken; 268 if (winAnimator.mDrawState == READY_TO_SHOW) { 269 if (atoken == null || atoken.allDrawn) { 270 if (w.performShowLocked()) { 271 pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM; 272 if (DEBUG_LAYOUT_REPEATS) { 273 mService.mWindowPlacerLocked.debugLayoutRepeats( 274 "updateWindowsAndWallpaperLocked 5", pendingLayoutChanges); 275 } 276 } 277 } 278 } 279 final AppWindowAnimator appAnimator = winAnimator.mAppAnimator; 280 if (appAnimator != null && appAnimator.thumbnail != null) { 281 if (appAnimator.thumbnailTransactionSeq 282 != mTmpWindowAnimator.mAnimTransactionSequence) { 283 appAnimator.thumbnailTransactionSeq = 284 mTmpWindowAnimator.mAnimTransactionSequence; 285 appAnimator.thumbnailLayer = 0; 286 } 287 if (appAnimator.thumbnailLayer < winAnimator.mAnimLayer) { 288 appAnimator.thumbnailLayer = winAnimator.mAnimLayer; 289 } 290 } 291 }; 292 293 private final Consumer<WindowState> mUpdateWallpaperForAnimator = w -> { 294 final WindowStateAnimator winAnimator = w.mWinAnimator; 295 if (winAnimator.mSurfaceController == null || !winAnimator.hasSurface()) { 296 return; 297 } 298 299 final int flags = w.mAttrs.flags; 300 301 // If this window is animating, make a note that we have an animating window and take 302 // care of a request to run a detached wallpaper animation. 303 if (winAnimator.mAnimating) { 304 if (winAnimator.mAnimation != null) { 305 if ((flags & FLAG_SHOW_WALLPAPER) != 0 306 && winAnimator.mAnimation.getDetachWallpaper()) { 307 mTmpWindow = w; 308 } 309 final int color = winAnimator.mAnimation.getBackgroundColor(); 310 if (color != 0) { 311 final TaskStack stack = w.getStack(); 312 if (stack != null) { 313 stack.setAnimationBackground(winAnimator, color); 314 } 315 } 316 } 317 mTmpWindowAnimator.setAnimating(true); 318 } 319 320 // If this window's app token is running a detached wallpaper animation, make a note so 321 // we can ensure the wallpaper is displayed behind it. 322 final AppWindowAnimator appAnimator = winAnimator.mAppAnimator; 323 if (appAnimator != null && appAnimator.animation != null 324 && appAnimator.animating) { 325 if ((flags & FLAG_SHOW_WALLPAPER) != 0 326 && appAnimator.animation.getDetachWallpaper()) { 327 mTmpWindow = w; 328 } 329 330 final int color = appAnimator.animation.getBackgroundColor(); 331 if (color != 0) { 332 final TaskStack stack = w.getStack(); 333 if (stack != null) { 334 stack.setAnimationBackground(winAnimator, color); 335 } 336 } 337 } 338 }; 339 340 private final Consumer<WindowState> mSetInputMethodAnimLayerAdjustment = 341 w -> w.adjustAnimLayer(mInputMethodAnimLayerAdjustment); 342 343 private final Consumer<WindowState> mScheduleToastTimeout = w -> { 344 final int lostFocusUid = mTmpWindow.mOwnerUid; 345 final Handler handler = mService.mH; 346 if (w.mAttrs.type == TYPE_TOAST && w.mOwnerUid == lostFocusUid) { 347 if (!handler.hasMessages(WINDOW_HIDE_TIMEOUT, w)) { 348 handler.sendMessageDelayed(handler.obtainMessage(WINDOW_HIDE_TIMEOUT, w), 349 w.mAttrs.hideTimeoutMilliseconds); 350 } 351 } 352 }; 353 354 private final ToBooleanFunction<WindowState> mFindFocusedWindow = w -> { 355 final AppWindowToken focusedApp = mService.mFocusedApp; 356 if (DEBUG_FOCUS) Slog.v(TAG_WM, "Looking for focus: " + w 357 + ", flags=" + w.mAttrs.flags + ", canReceive=" + w.canReceiveKeys()); 358 359 if (!w.canReceiveKeys()) { 360 return false; 361 } 362 363 final AppWindowToken wtoken = w.mAppToken; 364 365 // If this window's application has been removed, just skip it. 366 if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) { 367 if (DEBUG_FOCUS) Slog.v(TAG_WM, "Skipping " + wtoken + " because " 368 + (wtoken.removed ? "removed" : "sendingToBottom")); 369 return false; 370 } 371 372 if (focusedApp == null) { 373 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp=null" 374 + " using new focus @ " + w); 375 mTmpWindow = w; 376 return true; 377 } 378 379 if (!focusedApp.windowsAreFocusable()) { 380 // Current focused app windows aren't focusable... 381 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp windows not" 382 + " focusable using new focus @ " + w); 383 mTmpWindow = w; 384 return true; 385 } 386 387 // Descend through all of the app tokens and find the first that either matches 388 // win.mAppToken (return win) or mFocusedApp (return null). 389 if (wtoken != null && w.mAttrs.type != TYPE_APPLICATION_STARTING) { 390 if (focusedApp.compareTo(wtoken) > 0) { 391 // App stack below focused app stack. No focus for you!!! 392 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, 393 "findFocusedWindow: Reached focused app=" + focusedApp); 394 mTmpWindow = null; 395 return true; 396 } 397 } 398 399 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: Found new focus @ " + w); 400 mTmpWindow = w; 401 return true; 402 }; 403 404 private final Consumer<WindowState> mPrepareWindowSurfaces = 405 w -> w.mWinAnimator.prepareSurfaceLocked(true); 406 407 private final Consumer<WindowState> mPerformLayout = w -> { 408 // Don't do layout of a window if it is not visible, or soon won't be visible, to avoid 409 // wasting time and funky changes while a window is animating away. 410 final boolean gone = (mTmpWindow != null && mService.mPolicy.canBeHiddenByKeyguardLw(w)) 411 || w.isGoneForLayoutLw(); 412 413 if (DEBUG_LAYOUT && !w.mLayoutAttached) { 414 Slog.v(TAG, "1ST PASS " + w + ": gone=" + gone + " mHaveFrame=" + w.mHaveFrame 415 + " mLayoutAttached=" + w.mLayoutAttached 416 + " screen changed=" + w.isConfigChanged()); 417 final AppWindowToken atoken = w.mAppToken; 418 if (gone) Slog.v(TAG, " GONE: mViewVisibility=" + w.mViewVisibility 419 + " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.hidden 420 + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested) 421 + " parentHidden=" + w.isParentWindowHidden()); 422 else Slog.v(TAG, " VIS: mViewVisibility=" + w.mViewVisibility 423 + " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.hidden 424 + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested) 425 + " parentHidden=" + w.isParentWindowHidden()); 426 } 427 428 // If this view is GONE, then skip it -- keep the current frame, and let the caller know 429 // so they can ignore it if they want. (We do the normal layout for INVISIBLE windows, 430 // since that means "perform layout as normal, just don't display"). 431 if (!gone || !w.mHaveFrame || w.mLayoutNeeded 432 || ((w.isConfigChanged() || w.setReportResizeHints()) 433 && !w.isGoneForLayoutLw() && 434 ((w.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 || 435 (w.mHasSurface && w.mAppToken != null && 436 w.mAppToken.layoutConfigChanges)))) { 437 if (!w.mLayoutAttached) { 438 if (mTmpInitial) { 439 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 440 w.mContentChanged = false; 441 } 442 if (w.mAttrs.type == TYPE_DREAM) { 443 // Don't layout windows behind a dream, so that if it does stuff like hide 444 // the status bar we won't get a bad transition when it goes away. 445 mTmpWindow = w; 446 } 447 w.mLayoutNeeded = false; 448 w.prelayout(); 449 mService.mPolicy.layoutWindowLw(w, null); 450 w.mLayoutSeq = mService.mLayoutSeq; 451 452 // Window frames may have changed. Update dim layer with the new bounds. 453 final Task task = w.getTask(); 454 if (task != null) { 455 mDimLayerController.updateDimLayer(task); 456 } 457 458 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" + w.mFrame 459 + " mContainingFrame=" + w.mContainingFrame 460 + " mDisplayFrame=" + w.mDisplayFrame); 461 } 462 } 463 }; 464 465 private final Consumer<WindowState> mPerformLayoutAttached = w -> { 466 if (w.mLayoutAttached) { 467 if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + w + " mHaveFrame=" + w.mHaveFrame 468 + " mViewVisibility=" + w.mViewVisibility 469 + " mRelayoutCalled=" + w.mRelayoutCalled); 470 // If this view is GONE, then skip it -- keep the current frame, and let the caller 471 // know so they can ignore it if they want. (We do the normal layout for INVISIBLE 472 // windows, since that means "perform layout as normal, just don't display"). 473 if (mTmpWindow != null && mService.mPolicy.canBeHiddenByKeyguardLw(w)) { 474 return; 475 } 476 if ((w.mViewVisibility != GONE && w.mRelayoutCalled) || !w.mHaveFrame 477 || w.mLayoutNeeded) { 478 if (mTmpInitial) { 479 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 480 w.mContentChanged = false; 481 } 482 w.mLayoutNeeded = false; 483 w.prelayout(); 484 mService.mPolicy.layoutWindowLw(w, w.getParentWindow()); 485 w.mLayoutSeq = mService.mLayoutSeq; 486 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" + w.mFrame 487 + " mContainingFrame=" + w.mContainingFrame 488 + " mDisplayFrame=" + w.mDisplayFrame); 489 } 490 } else if (w.mAttrs.type == TYPE_DREAM) { 491 // Don't layout windows behind a dream, so that if it does stuff like hide the 492 // status bar we won't get a bad transition when it goes away. 493 mTmpWindow = mTmpWindow2; 494 } 495 }; 496 497 private final Predicate<WindowState> mComputeImeTargetPredicate = w -> { 498 if (DEBUG_INPUT_METHOD && mUpdateImeTarget) Slog.i(TAG_WM, "Checking window @" + w 499 + " fl=0x" + Integer.toHexString(w.mAttrs.flags)); 500 return w.canBeImeTarget(); 501 }; 502 503 private final Consumer<WindowState> mApplyPostLayoutPolicy = 504 w -> mService.mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs, w.getParentWindow(), 505 mService.mInputMethodTarget); 506 507 private final Consumer<WindowState> mApplySurfaceChangesTransaction = w -> { 508 final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked; 509 final boolean obscuredChanged = w.mObscured != 510 mTmpApplySurfaceChangesTransactionState.obscured; 511 final RootWindowContainer root = mService.mRoot; 512 // Only used if default window 513 final boolean someoneLosingFocus = !mService.mLosingFocus.isEmpty(); 514 515 // Update effect. 516 w.mObscured = mTmpApplySurfaceChangesTransactionState.obscured; 517 if (!mTmpApplySurfaceChangesTransactionState.obscured) { 518 final boolean isDisplayed = w.isDisplayedLw(); 519 520 if (isDisplayed && w.isObscuringDisplay()) { 521 // This window completely covers everything behind it, so we want to leave all 522 // of them as undimmed (for performance reasons). 523 root.mObscuringWindow = w; 524 mTmpApplySurfaceChangesTransactionState.obscured = true; 525 } 526 527 mTmpApplySurfaceChangesTransactionState.displayHasContent |= 528 root.handleNotObscuredLocked(w, 529 mTmpApplySurfaceChangesTransactionState.obscured, 530 mTmpApplySurfaceChangesTransactionState.syswin); 531 532 if (w.mHasSurface && isDisplayed) { 533 final int type = w.mAttrs.type; 534 if (type == TYPE_SYSTEM_DIALOG || type == TYPE_SYSTEM_ERROR 535 || (w.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { 536 mTmpApplySurfaceChangesTransactionState.syswin = true; 537 } 538 if (mTmpApplySurfaceChangesTransactionState.preferredRefreshRate == 0 539 && w.mAttrs.preferredRefreshRate != 0) { 540 mTmpApplySurfaceChangesTransactionState.preferredRefreshRate 541 = w.mAttrs.preferredRefreshRate; 542 } 543 if (mTmpApplySurfaceChangesTransactionState.preferredModeId == 0 544 && w.mAttrs.preferredDisplayModeId != 0) { 545 mTmpApplySurfaceChangesTransactionState.preferredModeId 546 = w.mAttrs.preferredDisplayModeId; 547 } 548 } 549 } 550 551 w.applyDimLayerIfNeeded(); 552 553 if (isDefaultDisplay && obscuredChanged && w.isVisibleLw() 554 && mWallpaperController.isWallpaperTarget(w)) { 555 // This is the wallpaper target and its obscured state changed... make sure the 556 // current wallpaper's visibility has been updated accordingly. 557 mWallpaperController.updateWallpaperVisibility(); 558 } 559 560 w.handleWindowMovedIfNeeded(); 561 562 final WindowStateAnimator winAnimator = w.mWinAnimator; 563 564 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); 565 w.mContentChanged = false; 566 567 // Moved from updateWindowsAndWallpaperLocked(). 568 if (w.mHasSurface) { 569 // Take care of the window being ready to display. 570 final boolean committed = winAnimator.commitFinishDrawingLocked(); 571 if (isDefaultDisplay && committed) { 572 if (w.mAttrs.type == TYPE_DREAM) { 573 // HACK: When a dream is shown, it may at that point hide the lock screen. 574 // So we need to redo the layout to let the phone window manager make this 575 // happen. 576 pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT; 577 if (DEBUG_LAYOUT_REPEATS) { 578 surfacePlacer.debugLayoutRepeats( 579 "dream and commitFinishDrawingLocked true", 580 pendingLayoutChanges); 581 } 582 } 583 if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) { 584 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 585 "First draw done in potential wallpaper target " + w); 586 root.mWallpaperMayChange = true; 587 pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 588 if (DEBUG_LAYOUT_REPEATS) { 589 surfacePlacer.debugLayoutRepeats( 590 "wallpaper and commitFinishDrawingLocked true", 591 pendingLayoutChanges); 592 } 593 } 594 } 595 if (!winAnimator.isAnimationStarting() && !winAnimator.isWaitingForOpening()) { 596 // Updates the shown frame before we set up the surface. This is needed 597 // because the resizing could change the top-left position (in addition to 598 // size) of the window. setSurfaceBoundariesLocked uses mShownPosition to 599 // position the surface. 600 // 601 // If an animation is being started, we can't call this method because the 602 // animation hasn't processed its initial transformation yet, but in general 603 // we do want to update the position if the window is animating. 604 winAnimator.computeShownFrameLocked(); 605 } 606 winAnimator.setSurfaceBoundariesLocked(mTmpRecoveringMemory /* recoveringMemory */); 607 } 608 609 final AppWindowToken atoken = w.mAppToken; 610 if (atoken != null) { 611 final boolean updateAllDrawn = atoken.updateDrawnWindowStates(w); 612 if (updateAllDrawn && !mTmpUpdateAllDrawn.contains(atoken)) { 613 mTmpUpdateAllDrawn.add(atoken); 614 } 615 } 616 617 if (isDefaultDisplay && someoneLosingFocus && w == mService.mCurrentFocus 618 && w.isDisplayedLw()) { 619 mTmpApplySurfaceChangesTransactionState.focusDisplayed = true; 620 } 621 622 w.updateResizingWindowIfNeeded(); 623 }; 624 625 /** 626 * @param display May not be null. 627 * @param service You know. 628 * @param layersController window layer controller used to assign layer to the windows on this 629 * display. 630 * @param wallpaperController wallpaper windows controller used to adjust the positioning of the 631 * wallpaper windows in the window list. 632 */ 633 DisplayContent(Display display, WindowManagerService service, 634 WindowLayersController layersController, WallpaperController wallpaperController) { 635 mDisplay = display; 636 mDisplayId = display.getDisplayId(); 637 mLayersController = layersController; 638 mWallpaperController = wallpaperController; 639 display.getDisplayInfo(mDisplayInfo); 640 display.getMetrics(mDisplayMetrics); 641 isDefaultDisplay = mDisplayId == DEFAULT_DISPLAY; 642 mService = service; 643 initializeDisplayBaseInfo(); 644 mDividerControllerLocked = new DockedStackDividerController(service, this); 645 mPinnedStackControllerLocked = new PinnedStackController(service, this); 646 mDimLayerController = new DimLayerController(this); 647 648 // These are the only direct children we should ever have and they are permanent. 649 super.addChild(mBelowAppWindowsContainers, null); 650 super.addChild(mTaskStackContainers, null); 651 super.addChild(mAboveAppWindowsContainers, null); 652 super.addChild(mImeWindowsContainers, null); 653 } 654 655 int getDisplayId() { 656 return mDisplayId; 657 } 658 659 WindowToken getWindowToken(IBinder binder) { 660 return mTokenMap.get(binder); 661 } 662 663 AppWindowToken getAppWindowToken(IBinder binder) { 664 final WindowToken token = getWindowToken(binder); 665 if (token == null) { 666 return null; 667 } 668 return token.asAppWindowToken(); 669 } 670 671 void addWindowToken(IBinder binder, WindowToken token) { 672 final DisplayContent dc = mService.mRoot.getWindowTokenDisplay(token); 673 if (dc != null) { 674 // We currently don't support adding a window token to the display if the display 675 // already has the binder mapped to another token. If there is a use case for supporting 676 // this moving forward we will either need to merge the WindowTokens some how or have 677 // the binder map to a list of window tokens. 678 throw new IllegalArgumentException("Can't map token=" + token + " to display=" + this 679 + " already mapped to display=" + dc + " tokens=" + dc.mTokenMap); 680 } 681 mTokenMap.put(binder, token); 682 683 if (token.asAppWindowToken() == null) { 684 // Add non-app token to container hierarchy on the display. App tokens are added through 685 // the parent container managing them (e.g. Tasks). 686 switch (token.windowType) { 687 case TYPE_WALLPAPER: 688 mBelowAppWindowsContainers.addChild(token); 689 break; 690 case TYPE_INPUT_METHOD: 691 case TYPE_INPUT_METHOD_DIALOG: 692 mImeWindowsContainers.addChild(token); 693 break; 694 default: 695 mAboveAppWindowsContainers.addChild(token); 696 break; 697 } 698 } 699 } 700 701 WindowToken removeWindowToken(IBinder binder) { 702 final WindowToken token = mTokenMap.remove(binder); 703 if (token != null && token.asAppWindowToken() == null) { 704 token.setExiting(); 705 } 706 return token; 707 } 708 709 /** Changes the display the input window token is housed on to this one. */ 710 void reParentWindowToken(WindowToken token) { 711 final DisplayContent prevDc = token.getDisplayContent(); 712 if (prevDc == this) { 713 return; 714 } 715 if (prevDc != null && prevDc.mTokenMap.remove(token.token) != null) { 716 switch (token.windowType) { 717 case TYPE_WALLPAPER: 718 prevDc.mBelowAppWindowsContainers.removeChild(token); 719 break; 720 case TYPE_INPUT_METHOD: 721 case TYPE_INPUT_METHOD_DIALOG: 722 prevDc.mImeWindowsContainers.removeChild(token); 723 break; 724 default: 725 prevDc.mAboveAppWindowsContainers.removeChild(token); 726 break; 727 } 728 } 729 730 addWindowToken(token.token, token); 731 } 732 733 void removeAppToken(IBinder binder) { 734 final WindowToken token = removeWindowToken(binder); 735 if (token == null) { 736 Slog.w(TAG_WM, "removeAppToken: Attempted to remove non-existing token: " + binder); 737 return; 738 } 739 740 final AppWindowToken appToken = token.asAppWindowToken(); 741 742 if (appToken == null) { 743 Slog.w(TAG_WM, "Attempted to remove non-App token: " + binder + " token=" + token); 744 return; 745 } 746 747 appToken.onRemovedFromDisplay(); 748 } 749 750 Display getDisplay() { 751 return mDisplay; 752 } 753 754 DisplayInfo getDisplayInfo() { 755 return mDisplayInfo; 756 } 757 758 DisplayMetrics getDisplayMetrics() { 759 return mDisplayMetrics; 760 } 761 762 DockedStackDividerController getDockedDividerController() { 763 return mDividerControllerLocked; 764 } 765 766 PinnedStackController getPinnedStackController() { 767 return mPinnedStackControllerLocked; 768 } 769 770 /** 771 * Returns true if the specified UID has access to this display. 772 */ 773 boolean hasAccess(int uid) { 774 return mDisplay.hasAccess(uid); 775 } 776 777 boolean isPrivate() { 778 return (mDisplay.getFlags() & FLAG_PRIVATE) != 0; 779 } 780 781 TaskStack getHomeStack() { 782 if (mHomeStack == null && mDisplayId == DEFAULT_DISPLAY) { 783 Slog.e(TAG_WM, "getHomeStack: Returning null from this=" + this); 784 } 785 return mHomeStack; 786 } 787 788 TaskStack getStackById(int stackId) { 789 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 790 final TaskStack stack = mTaskStackContainers.get(i); 791 if (stack.mStackId == stackId) { 792 return stack; 793 } 794 } 795 return null; 796 } 797 798 @Override 799 void onConfigurationChanged(Configuration newParentConfig) { 800 super.onConfigurationChanged(newParentConfig); 801 802 // The display size information is heavily dependent on the resources in the current 803 // configuration, so we need to reconfigure it every time the configuration changes. 804 // See {@link PhoneWindowManager#setInitialDisplaySize}...sigh... 805 mService.reconfigureDisplayLocked(this); 806 807 getDockedDividerController().onConfigurationChanged(); 808 getPinnedStackController().onConfigurationChanged(); 809 } 810 811 /** 812 * Callback used to trigger bounds update after configuration change and get ids of stacks whose 813 * bounds were updated. 814 */ 815 void updateStackBoundsAfterConfigChange(@NonNull List<Integer> changedStackList) { 816 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 817 final TaskStack stack = mTaskStackContainers.get(i); 818 if (stack.updateBoundsAfterConfigChange()) { 819 changedStackList.add(stack.mStackId); 820 } 821 } 822 } 823 824 @Override 825 boolean fillsParent() { 826 return true; 827 } 828 829 @Override 830 boolean isVisible() { 831 return true; 832 } 833 834 @Override 835 void onAppTransitionDone() { 836 super.onAppTransitionDone(); 837 mService.mWindowsChanged = true; 838 } 839 840 @Override 841 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) { 842 // Special handling so we can process IME windows with #forAllImeWindows above their IME 843 // target, or here in order if there isn't an IME target. 844 if (traverseTopToBottom) { 845 for (int i = mChildren.size() - 1; i >= 0; --i) { 846 final DisplayChildWindowContainer child = mChildren.get(i); 847 if (child == mImeWindowsContainers && mService.mInputMethodTarget != null) { 848 // In this case the Ime windows will be processed above their target so we skip 849 // here. 850 continue; 851 } 852 if (child.forAllWindows(callback, traverseTopToBottom)) { 853 return true; 854 } 855 } 856 } else { 857 final int count = mChildren.size(); 858 for (int i = 0; i < count; i++) { 859 final DisplayChildWindowContainer child = mChildren.get(i); 860 if (child == mImeWindowsContainers && mService.mInputMethodTarget != null) { 861 // In this case the Ime windows will be processed above their target so we skip 862 // here. 863 continue; 864 } 865 if (child.forAllWindows(callback, traverseTopToBottom)) { 866 return true; 867 } 868 } 869 } 870 return false; 871 } 872 873 boolean forAllImeWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) { 874 return mImeWindowsContainers.forAllWindows(callback, traverseTopToBottom); 875 } 876 877 @Override 878 int getOrientation() { 879 final WindowManagerPolicy policy = mService.mPolicy; 880 881 if (mService.mDisplayFrozen) { 882 if (mService.mLastWindowForcedOrientation != SCREEN_ORIENTATION_UNSPECIFIED) { 883 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, 884 "Display is frozen, return " + mService.mLastWindowForcedOrientation); 885 // If the display is frozen, some activities may be in the middle of restarting, and 886 // thus have removed their old window. If the window has the flag to hide the lock 887 // screen, then the lock screen can re-appear and inflict its own orientation on us. 888 // Keep the orientation stable until this all settles down. 889 return mService.mLastWindowForcedOrientation; 890 } else if (policy.isKeyguardLocked()) { 891 // Use the last orientation the while the display is frozen with the keyguard 892 // locked. This could be the keyguard forced orientation or from a SHOW_WHEN_LOCKED 893 // window. We don't want to check the show when locked window directly though as 894 // things aren't stable while the display is frozen, for example the window could be 895 // momentarily unavailable due to activity relaunch. 896 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display is frozen while keyguard locked, " 897 + "return " + mService.mLastOrientation); 898 return mService.mLastOrientation; 899 } 900 } else { 901 final int orientation = mAboveAppWindowsContainers.getOrientation(); 902 if (orientation != SCREEN_ORIENTATION_UNSET) { 903 return orientation; 904 } 905 } 906 907 // Top system windows are not requesting an orientation. Start searching from apps. 908 return mTaskStackContainers.getOrientation(); 909 } 910 911 void updateDisplayInfo() { 912 mDisplay.getDisplayInfo(mDisplayInfo); 913 mDisplay.getMetrics(mDisplayMetrics); 914 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 915 mTaskStackContainers.get(i).updateDisplayInfo(null); 916 } 917 } 918 919 void initializeDisplayBaseInfo() { 920 final DisplayManagerInternal displayManagerInternal = mService.mDisplayManagerInternal; 921 if (displayManagerInternal != null) { 922 // Bootstrap the default logical display from the display manager. 923 final DisplayInfo newDisplayInfo = displayManagerInternal.getDisplayInfo(mDisplayId); 924 if (newDisplayInfo != null) { 925 mDisplayInfo.copyFrom(newDisplayInfo); 926 } 927 } 928 929 mBaseDisplayWidth = mInitialDisplayWidth = mDisplayInfo.logicalWidth; 930 mBaseDisplayHeight = mInitialDisplayHeight = mDisplayInfo.logicalHeight; 931 mBaseDisplayDensity = mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi; 932 mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight); 933 } 934 935 void getLogicalDisplayRect(Rect out) { 936 // Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked. 937 final int orientation = mDisplayInfo.rotation; 938 boolean rotated = (orientation == ROTATION_90 || orientation == ROTATION_270); 939 final int physWidth = rotated ? mBaseDisplayHeight : mBaseDisplayWidth; 940 final int physHeight = rotated ? mBaseDisplayWidth : mBaseDisplayHeight; 941 int width = mDisplayInfo.logicalWidth; 942 int left = (physWidth - width) / 2; 943 int height = mDisplayInfo.logicalHeight; 944 int top = (physHeight - height) / 2; 945 out.set(left, top, left + width, top + height); 946 } 947 948 private void getLogicalDisplayRect(Rect out, int orientation) { 949 getLogicalDisplayRect(out); 950 951 // Rotate the Rect if needed. 952 final int currentRotation = mDisplayInfo.rotation; 953 final int rotationDelta = deltaRotation(currentRotation, orientation); 954 if (rotationDelta == ROTATION_90 || rotationDelta == ROTATION_270) { 955 createRotationMatrix(rotationDelta, mBaseDisplayWidth, mBaseDisplayHeight, mTmpMatrix); 956 mTmpRectF.set(out); 957 mTmpMatrix.mapRect(mTmpRectF); 958 mTmpRectF.round(out); 959 } 960 } 961 962 void getContentRect(Rect out) { 963 out.set(mContentRect); 964 } 965 966 /** 967 * Adds the stack to this display. 968 * @see WindowManagerService#addStackToDisplay(int, int, boolean) 969 */ 970 Rect addStackToDisplay(int stackId, boolean onTop) { 971 boolean attachedToDisplay = false; 972 TaskStack stack = mService.mStackIdToStack.get(stackId); 973 if (stack == null) { 974 if (DEBUG_STACK) Slog.d(TAG_WM, "Create new stackId=" + stackId + " on displayId=" 975 + mDisplayId); 976 977 stack = getStackById(stackId); 978 if (stack != null) { 979 // It's already attached to the display...clear mDeferRemoval and move stack to 980 // appropriate z-order on display as needed. 981 stack.mDeferRemoval = false; 982 moveStack(stack, onTop); 983 attachedToDisplay = true; 984 } else { 985 stack = new TaskStack(mService, stackId); 986 } 987 988 mService.mStackIdToStack.put(stackId, stack); 989 if (stackId == DOCKED_STACK_ID) { 990 mDividerControllerLocked.notifyDockedStackExistsChanged(true); 991 } 992 } else { 993 final DisplayContent currentDC = stack.getDisplayContent(); 994 if (currentDC != null) { 995 throw new IllegalStateException("Trying to add stackId=" + stackId 996 + "to displayId=" + mDisplayId + ", but it's already attached to displayId=" 997 + currentDC.getDisplayId()); 998 } 999 } 1000 1001 if (!attachedToDisplay) { 1002 mTaskStackContainers.addStackToDisplay(stack, onTop); 1003 } 1004 1005 if (stack.getRawFullscreen()) { 1006 return null; 1007 } 1008 final Rect bounds = new Rect(); 1009 stack.getRawBounds(bounds); 1010 return bounds; 1011 } 1012 1013 /** Removes the stack from the display and prepares for changing the parent. */ 1014 private void removeStackFromDisplay(TaskStack stack) { 1015 mTaskStackContainers.removeStackFromDisplay(stack); 1016 } 1017 1018 /** Moves the stack to this display and returns the updated bounds. */ 1019 Rect moveStackToDisplay(TaskStack stack) { 1020 final DisplayContent currentDisplayContent = stack.getDisplayContent(); 1021 if (currentDisplayContent == null) { 1022 throw new IllegalStateException("Trying to move stackId=" + stack.mStackId 1023 + " which is not currently attached to any display"); 1024 } 1025 if (stack.getDisplayContent().getDisplayId() == mDisplayId) { 1026 throw new IllegalArgumentException("Trying to move stackId=" + stack.mStackId 1027 + " to its current displayId=" + mDisplayId); 1028 } 1029 1030 currentDisplayContent.removeStackFromDisplay(stack); 1031 return addStackToDisplay(stack.mStackId, true /* onTop */); 1032 } 1033 1034 void moveStack(TaskStack stack, boolean toTop) { 1035 mTaskStackContainers.moveStack(stack, toTop); 1036 } 1037 1038 @Override 1039 protected void addChild(DisplayChildWindowContainer child, 1040 Comparator<DisplayChildWindowContainer> comparator) { 1041 throw new UnsupportedOperationException("See DisplayChildWindowContainer"); 1042 } 1043 1044 @Override 1045 protected void addChild(DisplayChildWindowContainer child, int index) { 1046 throw new UnsupportedOperationException("See DisplayChildWindowContainer"); 1047 } 1048 1049 @Override 1050 protected void removeChild(DisplayChildWindowContainer child) { 1051 // Only allow removal of direct children from this display if the display is in the process 1052 // of been removed. 1053 if (mRemovingDisplay) { 1054 super.removeChild(child); 1055 return; 1056 } 1057 throw new UnsupportedOperationException("See DisplayChildWindowContainer"); 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 */ 2108 Bitmap screenshotApplications(IBinder appToken, int width, int height, 2109 boolean includeFullDisplay, float frameScale, Bitmap.Config config, 2110 boolean wallpaperOnly) { 2111 int dw = mDisplayInfo.logicalWidth; 2112 int dh = mDisplayInfo.logicalHeight; 2113 if (dw == 0 || dh == 0) { 2114 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken 2115 + ": returning null. logical widthxheight=" + dw + "x" + dh); 2116 return null; 2117 } 2118 2119 Bitmap bm = null; 2120 2121 mScreenshotApplicationState.reset(appToken == null && !wallpaperOnly); 2122 final Rect frame = new Rect(); 2123 final Rect stackBounds = new Rect(); 2124 2125 boolean includeImeInScreenshot; 2126 synchronized(mService.mWindowMap) { 2127 final AppWindowToken imeTargetAppToken = mService.mInputMethodTarget != null 2128 ? mService.mInputMethodTarget.mAppToken : null; 2129 // We only include the Ime in the screenshot if the app we are screenshoting is the IME 2130 // target and isn't in multi-window mode. We don't screenshot the IME in multi-window 2131 // mode because the frame of the IME might not overlap with that of the app. 2132 // E.g. IME target app at the top in split-screen mode and the IME at the bottom 2133 // overlapping with the bottom app. 2134 includeImeInScreenshot = imeTargetAppToken != null 2135 && imeTargetAppToken.appToken != null 2136 && imeTargetAppToken.appToken.asBinder() == appToken 2137 && !mService.mInputMethodTarget.isInMultiWindowMode(); 2138 } 2139 2140 final int aboveAppLayer = (mService.mPolicy.windowTypeToLayerLw(TYPE_APPLICATION) + 1) 2141 * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET; 2142 2143 synchronized(mService.mWindowMap) { 2144 // Figure out the part of the screen that is actually the app. 2145 mScreenshotApplicationState.appWin = null; 2146 forAllWindows(w -> { 2147 if (!w.mHasSurface) { 2148 return false; 2149 } 2150 if (w.mLayer >= aboveAppLayer) { 2151 return false; 2152 } 2153 if (wallpaperOnly && !w.mIsWallpaper) { 2154 return false; 2155 } 2156 if (w.mIsImWindow) { 2157 if (!includeImeInScreenshot) { 2158 return false; 2159 } 2160 } else if (w.mIsWallpaper) { 2161 // If this is the wallpaper layer and we're only looking for the wallpaper layer 2162 // then the target window state is this one. 2163 if (wallpaperOnly) { 2164 mScreenshotApplicationState.appWin = w; 2165 } 2166 2167 if (mScreenshotApplicationState.appWin == null) { 2168 // We have not ran across the target window yet, so it is probably behind 2169 // the wallpaper. This can happen when the keyguard is up and all windows 2170 // are moved behind the wallpaper. We don't want to include the wallpaper 2171 // layer in the screenshot as it will cover-up the layer of the target 2172 // window. 2173 return false; 2174 } 2175 // Fall through. The target window is in front of the wallpaper. For this 2176 // case we want to include the wallpaper layer in the screenshot because 2177 // the target window might have some transparent areas. 2178 } else if (appToken != null) { 2179 if (w.mAppToken == null || w.mAppToken.token != appToken) { 2180 // This app window is of no interest if it is not associated with the 2181 // screenshot app. 2182 return false; 2183 } 2184 mScreenshotApplicationState.appWin = w; 2185 } 2186 2187 // Include this window. 2188 2189 final WindowStateAnimator winAnim = w.mWinAnimator; 2190 int layer = winAnim.mSurfaceController.getLayer(); 2191 if (mScreenshotApplicationState.maxLayer < layer) { 2192 mScreenshotApplicationState.maxLayer = layer; 2193 } 2194 if (mScreenshotApplicationState.minLayer > layer) { 2195 mScreenshotApplicationState.minLayer = layer; 2196 } 2197 2198 // Don't include wallpaper in bounds calculation 2199 if (!includeFullDisplay && !w.mIsWallpaper) { 2200 final Rect wf = w.mFrame; 2201 final Rect cr = w.mContentInsets; 2202 int left = wf.left + cr.left; 2203 int top = wf.top + cr.top; 2204 int right = wf.right - cr.right; 2205 int bottom = wf.bottom - cr.bottom; 2206 frame.union(left, top, right, bottom); 2207 w.getVisibleBounds(stackBounds); 2208 if (!Rect.intersects(frame, stackBounds)) { 2209 // Set frame empty if there's no intersection. 2210 frame.setEmpty(); 2211 } 2212 } 2213 2214 final boolean foundTargetWs = 2215 (w.mAppToken != null && w.mAppToken.token == appToken) 2216 || (mScreenshotApplicationState.appWin != null && wallpaperOnly); 2217 if (foundTargetWs && w.isDisplayedLw() && winAnim.getShown()) { 2218 mScreenshotApplicationState.screenshotReady = true; 2219 } 2220 2221 if (w.isObscuringDisplay()){ 2222 return true; 2223 } 2224 return false; 2225 }, true /* traverseTopToBottom */); 2226 2227 final WindowState appWin = mScreenshotApplicationState.appWin; 2228 final boolean screenshotReady = mScreenshotApplicationState.screenshotReady; 2229 final int maxLayer = mScreenshotApplicationState.maxLayer; 2230 final int minLayer = mScreenshotApplicationState.minLayer; 2231 2232 if (appToken != null && appWin == null) { 2233 // Can't find a window to snapshot. 2234 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, 2235 "Screenshot: Couldn't find a surface matching " + appToken); 2236 return null; 2237 } 2238 2239 if (!screenshotReady) { 2240 Slog.i(TAG_WM, "Failed to capture screenshot of " + appToken + 2241 " appWin=" + (appWin == null ? "null" : (appWin + " drawState=" + 2242 appWin.mWinAnimator.mDrawState))); 2243 return null; 2244 } 2245 2246 // Screenshot is ready to be taken. Everything from here below will continue 2247 // through the bottom of the loop and return a value. We only stay in the loop 2248 // because we don't want to release the mWindowMap lock until the screenshot is 2249 // taken. 2250 2251 if (maxLayer == 0) { 2252 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken 2253 + ": returning null maxLayer=" + maxLayer); 2254 return null; 2255 } 2256 2257 if (!includeFullDisplay) { 2258 // Constrain frame to the screen size. 2259 if (!frame.intersect(0, 0, dw, dh)) { 2260 frame.setEmpty(); 2261 } 2262 } else { 2263 // Caller just wants entire display. 2264 frame.set(0, 0, dw, dh); 2265 } 2266 if (frame.isEmpty()) { 2267 return null; 2268 } 2269 2270 if (width < 0) { 2271 width = (int) (frame.width() * frameScale); 2272 } 2273 if (height < 0) { 2274 height = (int) (frame.height() * frameScale); 2275 } 2276 2277 // Tell surface flinger what part of the image to crop. Take the top 2278 // right part of the application, and crop the larger dimension to fit. 2279 Rect crop = new Rect(frame); 2280 if (width / (float) frame.width() < height / (float) frame.height()) { 2281 int cropWidth = (int)((float)width / (float)height * frame.height()); 2282 crop.right = crop.left + cropWidth; 2283 } else { 2284 int cropHeight = (int)((float)height / (float)width * frame.width()); 2285 crop.bottom = crop.top + cropHeight; 2286 } 2287 2288 // The screenshot API does not apply the current screen rotation. 2289 int rot = mDisplay.getRotation(); 2290 2291 if (rot == ROTATION_90 || rot == ROTATION_270) { 2292 rot = (rot == ROTATION_90) ? ROTATION_270 : ROTATION_90; 2293 } 2294 2295 // Surfaceflinger is not aware of orientation, so convert our logical 2296 // crop to surfaceflinger's portrait orientation. 2297 convertCropForSurfaceFlinger(crop, rot, dw, dh); 2298 2299 if (DEBUG_SCREENSHOT) { 2300 Slog.i(TAG_WM, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to " 2301 + maxLayer + " appToken=" + appToken); 2302 forAllWindows(w -> { 2303 final WindowSurfaceController controller = w.mWinAnimator.mSurfaceController; 2304 Slog.i(TAG_WM, w + ": " + w.mLayer 2305 + " animLayer=" + w.mWinAnimator.mAnimLayer 2306 + " surfaceLayer=" + ((controller == null) 2307 ? "null" : controller.getLayer())); 2308 }, false /* traverseTopToBottom */); 2309 } 2310 2311 final ScreenRotationAnimation screenRotationAnimation = 2312 mService.mAnimator.getScreenRotationAnimationLocked(DEFAULT_DISPLAY); 2313 final boolean inRotation = screenRotationAnimation != null && 2314 screenRotationAnimation.isAnimating(); 2315 if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG_WM, 2316 "Taking screenshot while rotating"); 2317 2318 // We force pending transactions to flush before taking 2319 // the screenshot by pushing an empty synchronous transaction. 2320 SurfaceControl.openTransaction(); 2321 SurfaceControl.closeTransactionSync(); 2322 2323 bm = SurfaceControl.screenshot(crop, width, height, minLayer, maxLayer, 2324 inRotation, rot); 2325 if (bm == null) { 2326 Slog.w(TAG_WM, "Screenshot failure taking screenshot for (" + dw + "x" + dh 2327 + ") to layer " + maxLayer); 2328 return null; 2329 } 2330 } 2331 2332 if (DEBUG_SCREENSHOT) { 2333 // TEST IF IT's ALL BLACK 2334 int[] buffer = new int[bm.getWidth() * bm.getHeight()]; 2335 bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight()); 2336 boolean allBlack = true; 2337 final int firstColor = buffer[0]; 2338 for (int i = 0; i < buffer.length; i++) { 2339 if (buffer[i] != firstColor) { 2340 allBlack = false; 2341 break; 2342 } 2343 } 2344 if (allBlack) { 2345 final WindowState appWin = mScreenshotApplicationState.appWin; 2346 final int maxLayer = mScreenshotApplicationState.maxLayer; 2347 final int minLayer = mScreenshotApplicationState.minLayer; 2348 Slog.i(TAG_WM, "Screenshot " + appWin + " was monochrome(" + 2349 Integer.toHexString(firstColor) + ")! mSurfaceLayer=" + 2350 (appWin != null ? 2351 appWin.mWinAnimator.mSurfaceController.getLayer() : "null") + 2352 " minLayer=" + minLayer + " maxLayer=" + maxLayer); 2353 } 2354 } 2355 2356 // Create a copy of the screenshot that is immutable and backed in ashmem. 2357 // This greatly reduces the overhead of passing the bitmap between processes. 2358 Bitmap ret = bm.createAshmemBitmap(config); 2359 bm.recycle(); 2360 return ret; 2361 } 2362 2363 // TODO: Can this use createRotationMatrix()? 2364 private static void convertCropForSurfaceFlinger(Rect crop, int rot, int dw, int dh) { 2365 if (rot == Surface.ROTATION_90) { 2366 final int tmp = crop.top; 2367 crop.top = dw - crop.right; 2368 crop.right = crop.bottom; 2369 crop.bottom = dw - crop.left; 2370 crop.left = tmp; 2371 } else if (rot == Surface.ROTATION_180) { 2372 int tmp = crop.top; 2373 crop.top = dh - crop.bottom; 2374 crop.bottom = dh - tmp; 2375 tmp = crop.right; 2376 crop.right = dw - crop.left; 2377 crop.left = dw - tmp; 2378 } else if (rot == Surface.ROTATION_270) { 2379 final int tmp = crop.top; 2380 crop.top = crop.left; 2381 crop.left = dh - crop.bottom; 2382 crop.bottom = crop.right; 2383 crop.right = dh - tmp; 2384 } 2385 } 2386 2387 void onSeamlessRotationTimeout() { 2388 // Used to indicate the layout is needed. 2389 mTmpWindow = null; 2390 2391 forAllWindows(w -> { 2392 if (!w.mSeamlesslyRotated) { 2393 return; 2394 } 2395 mTmpWindow = w; 2396 w.setDisplayLayoutNeeded(); 2397 mService.markForSeamlessRotation(w, false); 2398 }, true /* traverseTopToBottom */); 2399 2400 if (mTmpWindow != null) { 2401 mService.mWindowPlacerLocked.performSurfacePlacement(); 2402 } 2403 } 2404 2405 static final class TaskForResizePointSearchResult { 2406 boolean searchDone; 2407 Task taskForResize; 2408 2409 void reset() { 2410 searchDone = false; 2411 taskForResize = null; 2412 } 2413 } 2414 2415 private static final class ApplySurfaceChangesTransactionState { 2416 boolean displayHasContent; 2417 boolean obscured; 2418 boolean syswin; 2419 boolean focusDisplayed; 2420 float preferredRefreshRate; 2421 int preferredModeId; 2422 2423 void reset() { 2424 displayHasContent = false; 2425 obscured = false; 2426 syswin = false; 2427 focusDisplayed = false; 2428 preferredRefreshRate = 0; 2429 preferredModeId = 0; 2430 } 2431 } 2432 2433 private static final class ScreenshotApplicationState { 2434 WindowState appWin; 2435 int maxLayer; 2436 int minLayer; 2437 boolean screenshotReady; 2438 2439 void reset(boolean screenshotReady) { 2440 appWin = null; 2441 maxLayer = 0; 2442 minLayer = 0; 2443 this.screenshotReady = screenshotReady; 2444 minLayer = (screenshotReady) ? 0 : Integer.MAX_VALUE; 2445 } 2446 } 2447 2448 /** 2449 * Base class for any direct child window container of {@link #DisplayContent} need to inherit 2450 * from. This is mainly a pass through class that allows {@link #DisplayContent} to have 2451 * homogeneous children type which is currently required by sub-classes of 2452 * {@link WindowContainer} class. 2453 */ 2454 static class DisplayChildWindowContainer<E extends WindowContainer> extends WindowContainer<E> { 2455 2456 int size() { 2457 return mChildren.size(); 2458 } 2459 2460 E get(int index) { 2461 return mChildren.get(index); 2462 } 2463 2464 @Override 2465 boolean fillsParent() { 2466 return true; 2467 } 2468 2469 @Override 2470 boolean isVisible() { 2471 return true; 2472 } 2473 } 2474 2475 /** 2476 * Window container class that contains all containers on this display relating to Apps. 2477 * I.e Activities. 2478 */ 2479 private final class TaskStackContainers extends DisplayChildWindowContainer<TaskStack> { 2480 2481 /** 2482 * Adds the stack to this container. 2483 * @see WindowManagerService#addStackToDisplay(int, int, boolean) 2484 */ 2485 void addStackToDisplay(TaskStack stack, boolean onTop) { 2486 if (stack.mStackId == HOME_STACK_ID) { 2487 if (mHomeStack != null) { 2488 throw new IllegalArgumentException("attachStack: HOME_STACK_ID (0) not first."); 2489 } 2490 mHomeStack = stack; 2491 } 2492 addChild(stack, onTop); 2493 stack.onDisplayChanged(DisplayContent.this); 2494 } 2495 2496 /** Removes the stack from its container and prepare for changing the parent. */ 2497 void removeStackFromDisplay(TaskStack stack) { 2498 removeChild(stack); 2499 stack.onRemovedFromDisplay(); 2500 } 2501 2502 void moveStack(TaskStack stack, boolean toTop) { 2503 if (StackId.isAlwaysOnTop(stack.mStackId) && !toTop) { 2504 // This stack is always-on-top silly... 2505 Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + stack + " to bottom"); 2506 return; 2507 } 2508 2509 if (!mChildren.contains(stack)) { 2510 Slog.wtf(TAG_WM, "moving stack that was not added: " + stack, new Throwable()); 2511 } 2512 removeChild(stack); 2513 addChild(stack, toTop); 2514 } 2515 2516 private void addChild(TaskStack stack, boolean toTop) { 2517 int addIndex = toTop ? mChildren.size() : 0; 2518 2519 if (toTop 2520 && mService.isStackVisibleLocked(PINNED_STACK_ID) 2521 && stack.mStackId != PINNED_STACK_ID) { 2522 // The pinned stack is always the top most stack (always-on-top) when it is visible. 2523 // So, stack is moved just below the pinned stack. 2524 addIndex--; 2525 TaskStack topStack = mChildren.get(addIndex); 2526 if (topStack.mStackId != PINNED_STACK_ID) { 2527 throw new IllegalStateException("Pinned stack isn't top stack??? " + mChildren); 2528 } 2529 } 2530 addChild(stack, addIndex); 2531 setLayoutNeeded(); 2532 } 2533 2534 @Override 2535 boolean forAllWindows(ToBooleanFunction<WindowState> callback, 2536 boolean traverseTopToBottom) { 2537 if (traverseTopToBottom) { 2538 if (super.forAllWindows(callback, traverseTopToBottom)) { 2539 return true; 2540 } 2541 if (forAllExitingAppTokenWindows(callback, traverseTopToBottom)) { 2542 return true; 2543 } 2544 } else { 2545 if (forAllExitingAppTokenWindows(callback, traverseTopToBottom)) { 2546 return true; 2547 } 2548 if (super.forAllWindows(callback, traverseTopToBottom)) { 2549 return true; 2550 } 2551 } 2552 return false; 2553 } 2554 2555 private boolean forAllExitingAppTokenWindows(ToBooleanFunction<WindowState> callback, 2556 boolean traverseTopToBottom) { 2557 // For legacy reasons we process the TaskStack.mExitingAppTokens first here before the 2558 // app tokens. 2559 // TODO: Investigate if we need to continue to do this or if we can just process them 2560 // in-order. 2561 if (traverseTopToBottom) { 2562 for (int i = mChildren.size() - 1; i >= 0; --i) { 2563 final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens; 2564 for (int j = appTokens.size() - 1; j >= 0; --j) { 2565 if (appTokens.get(j).forAllWindowsUnchecked(callback, 2566 traverseTopToBottom)) { 2567 return true; 2568 } 2569 } 2570 } 2571 } else { 2572 final int count = mChildren.size(); 2573 for (int i = 0; i < count; ++i) { 2574 final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens; 2575 final int appTokensCount = appTokens.size(); 2576 for (int j = 0; j < appTokensCount; j++) { 2577 if (appTokens.get(j).forAllWindowsUnchecked(callback, 2578 traverseTopToBottom)) { 2579 return true; 2580 } 2581 } 2582 } 2583 } 2584 return false; 2585 } 2586 2587 @Override 2588 int getOrientation() { 2589 if (mService.isStackVisibleLocked(DOCKED_STACK_ID) 2590 || mService.isStackVisibleLocked(FREEFORM_WORKSPACE_STACK_ID)) { 2591 // Apps and their containers are not allowed to specify an orientation while the 2592 // docked or freeform stack is visible...except for the home stack/task if the 2593 // docked stack is minimized and it actually set something. 2594 if (mHomeStack != null && mHomeStack.isVisible() 2595 && mDividerControllerLocked.isMinimizedDock()) { 2596 final int orientation = mHomeStack.getOrientation(); 2597 if (orientation != SCREEN_ORIENTATION_UNSET) { 2598 return orientation; 2599 } 2600 } 2601 return SCREEN_ORIENTATION_UNSPECIFIED; 2602 } 2603 2604 final int orientation = super.getOrientation(); 2605 if (orientation != SCREEN_ORIENTATION_UNSET 2606 && orientation != SCREEN_ORIENTATION_BEHIND) { 2607 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, 2608 "App is requesting an orientation, return " + orientation); 2609 return orientation; 2610 } 2611 2612 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, 2613 "No app is requesting an orientation, return " + mService.mLastOrientation); 2614 // The next app has not been requested to be visible, so we keep the current orientation 2615 // to prevent freezing/unfreezing the display too early. 2616 return mService.mLastOrientation; 2617 } 2618 } 2619 2620 /** 2621 * Window container class that contains all containers on this display that are not related to 2622 * Apps. E.g. status bar. 2623 */ 2624 private final class NonAppWindowContainers extends DisplayChildWindowContainer<WindowToken> { 2625 final LinkedList<WindowState> mTmpWindows = new LinkedList(); 2626 2627 private final ToBooleanFunction<WindowState> mCollectWindowsInOrder = w -> { 2628 int addIndex = mTmpWindows.size(); 2629 for (int i = mTmpWindows.size() - 1; i >= 0; --i) { 2630 final WindowState current = mTmpWindows.get(i); 2631 if (w.mBaseLayer > current.mBaseLayer) { 2632 break; 2633 } 2634 addIndex = i; 2635 } 2636 2637 mTmpWindows.add(addIndex, w); 2638 return false; 2639 }; 2640 2641 /** 2642 * Compares two child window tokens returns -1 if the first is lesser than the second in 2643 * terms of z-order and 1 otherwise. 2644 */ 2645 private final Comparator<WindowToken> mWindowComparator = (token1, token2) -> 2646 // Tokens with higher base layer are z-ordered on-top. 2647 mService.mPolicy.windowTypeToLayerLw(token1.windowType) 2648 < mService.mPolicy.windowTypeToLayerLw(token2.windowType) ? -1 : 1; 2649 2650 private final Predicate<WindowState> mGetOrientingWindow = w -> { 2651 if (!w.isVisibleLw() || !w.mPolicyVisibilityAfterAnim) { 2652 return false; 2653 } 2654 final int req = w.mAttrs.screenOrientation; 2655 if(req == SCREEN_ORIENTATION_UNSPECIFIED || req == SCREEN_ORIENTATION_BEHIND 2656 || req == SCREEN_ORIENTATION_UNSET) { 2657 return false; 2658 } 2659 return true; 2660 }; 2661 2662 private final String mName; 2663 NonAppWindowContainers(String name) { 2664 mName = name; 2665 } 2666 2667 void addChild(WindowToken token) { 2668 addChild(token, mWindowComparator); 2669 } 2670 2671 @Override 2672 boolean forAllWindows(ToBooleanFunction<WindowState> callback, 2673 boolean traverseTopToBottom) { 2674 // Hack to work around WindowToken containing windows of various types there by causing 2675 // the windows not to be returned in visual order if there is another token with a 2676 // window that should be z-order in-between the windows of the first token. This is an 2677 // issue due to the various window types sys-ui adds with its token. 2678 // TODO: Have a separate token for each type of window sys-ui wants to add. Would 2679 // require some changes to sys-ui on the token it uses for window creation vs. just 2680 // using the default token of its process. 2681 mTmpWindows.clear(); 2682 super.forAllWindows(mCollectWindowsInOrder, false /* traverseTopToBottom */); 2683 2684 while(!mTmpWindows.isEmpty()) { 2685 final WindowState current = traverseTopToBottom 2686 ? mTmpWindows.pollLast() : mTmpWindows.pollFirst(); 2687 if (callback.apply(current)) { 2688 return true; 2689 } 2690 } 2691 return false; 2692 } 2693 2694 @Override 2695 int getOrientation() { 2696 final WindowManagerPolicy policy = mService.mPolicy; 2697 // Find a window requesting orientation. 2698 final WindowState win = getWindow(mGetOrientingWindow); 2699 2700 if (win != null) { 2701 final int req = win.mAttrs.screenOrientation; 2702 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, win + " forcing orientation to " + req); 2703 if (policy.isKeyguardHostWindow(win.mAttrs)) { 2704 mService.mLastKeyguardForcedOrientation = req; 2705 } 2706 return (mService.mLastWindowForcedOrientation = req); 2707 } 2708 2709 mService.mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED; 2710 2711 if (policy.isKeyguardShowingAndNotOccluded()) { 2712 return mService.mLastKeyguardForcedOrientation; 2713 } 2714 2715 return SCREEN_ORIENTATION_UNSET; 2716 } 2717 2718 @Override 2719 String getName() { 2720 return mName; 2721 } 2722 } 2723} 2724