WindowSurfacePlacer.java revision 363ab98fced07bf7647355367be9e6ef76751450
1package com.android.server.wm; 2 3import static android.app.ActivityManagerInternal.APP_TRANSITION_SAVED_SURFACE; 4import static android.app.ActivityManagerInternal.APP_TRANSITION_STARTING_WINDOW; 5import static android.app.ActivityManagerInternal.APP_TRANSITION_TIMEOUT; 6import static android.app.ActivityManagerInternal.APP_TRANSITION_WINDOWS_DRAWN; 7import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; 8import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; 9import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; 10import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION; 11import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE; 12import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; 13import static android.view.WindowManager.LayoutParams.TYPE_DREAM; 14import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG; 15import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG; 16import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR; 17import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; 18import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; 19import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG; 20import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 21import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 22import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_START; 23import static com.android.server.wm.WindowManagerDebugConfig.DEBUG; 24import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE; 25import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS; 26import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT; 27import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS; 28import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION; 29import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_POWER; 30import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW; 31import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT; 32import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; 33import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT; 34import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE; 35import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS; 36import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS; 37import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; 38import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 39import static com.android.server.wm.WindowManagerService.H.DO_TRAVERSAL; 40import static com.android.server.wm.WindowManagerService.H.NOTIFY_ACTIVITY_DRAWN; 41import static com.android.server.wm.WindowManagerService.H.NOTIFY_APP_TRANSITION_STARTING; 42import static com.android.server.wm.WindowManagerService.H.NOTIFY_STARTING_WINDOW_DRAWN; 43import static com.android.server.wm.WindowManagerService.H.REPORT_LOSING_FOCUS; 44import static com.android.server.wm.WindowManagerService.H.REPORT_WINDOWS_CHANGE; 45import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION; 46import static com.android.server.wm.WindowManagerService.H.UPDATE_DOCKED_STACK_DIVIDER; 47import static com.android.server.wm.WindowManagerService.H.WINDOW_FREEZE_TIMEOUT; 48import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD; 49import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION; 50import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES; 51import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES; 52import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_NONE; 53 54import android.graphics.Bitmap; 55import android.graphics.Canvas; 56import android.graphics.PixelFormat; 57import android.graphics.Rect; 58import android.os.Debug; 59import android.os.PowerManager; 60import android.os.RemoteException; 61import android.os.SystemClock; 62import android.os.Trace; 63import android.provider.Settings; 64import android.util.ArraySet; 65import android.util.Slog; 66import android.view.Display; 67import android.view.DisplayInfo; 68import android.view.Surface; 69import android.view.SurfaceControl; 70import android.view.View; 71import android.view.WindowManager.LayoutParams; 72import android.view.animation.Animation; 73 74import java.io.PrintWriter; 75import java.util.ArrayList; 76 77/** 78 * Positions windows and their surfaces. 79 * 80 * It sets positions of windows by calculating their frames and then applies this by positioning 81 * surfaces according to these frames. Z layer is still assigned withing WindowManagerService. 82 */ 83class WindowSurfacePlacer { 84 private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowSurfacePlacer" : TAG_WM; 85 private final WindowManagerService mService; 86 private final WallpaperController mWallpaperControllerLocked; 87 88 private boolean mInLayout = false; 89 90 /** Only do a maximum of 6 repeated layouts. After that quit */ 91 private int mLayoutRepeatCount; 92 93 static final int SET_UPDATE_ROTATION = 1 << 0; 94 static final int SET_WALLPAPER_MAY_CHANGE = 1 << 1; 95 static final int SET_FORCE_HIDING_CHANGED = 1 << 2; 96 static final int SET_ORIENTATION_CHANGE_COMPLETE = 1 << 3; 97 static final int SET_TURN_ON_SCREEN = 1 << 4; 98 static final int SET_WALLPAPER_ACTION_PENDING = 1 << 5; 99 100 boolean mWallpaperMayChange = false; 101 boolean mOrientationChangeComplete = true; 102 boolean mWallpaperActionPending = false; 103 104 private boolean mWallpaperForceHidingChanged = false; 105 private Object mLastWindowFreezeSource = null; 106 private Session mHoldScreen = null; 107 private boolean mObscured = false; 108 private boolean mSyswin = false; 109 private float mScreenBrightness = -1; 110 private float mButtonBrightness = -1; 111 private long mUserActivityTimeout = -1; 112 private boolean mUpdateRotation = false; 113 private final Rect mTmpStartRect = new Rect(); 114 private final Rect mTmpContentRect = new Rect(); 115 116 // Set to true when the display contains content to show the user. 117 // When false, the display manager may choose to mirror or blank the display. 118 private boolean mDisplayHasContent = false; 119 120 // Only set while traversing the default display based on its content. 121 // Affects the behavior of mirroring on secondary displays. 122 private boolean mObscureApplicationContentOnSecondaryDisplays = false; 123 124 private float mPreferredRefreshRate = 0; 125 126 private int mPreferredModeId = 0; 127 128 private boolean mTraversalScheduled; 129 private int mDeferDepth = 0; 130 131 private boolean mSustainedPerformanceModeEnabled = false; 132 private boolean mSustainedPerformanceModeCurrent = false; 133 134 private static final class LayerAndToken { 135 public int layer; 136 public AppWindowToken token; 137 } 138 private final LayerAndToken mTmpLayerAndToken = new LayerAndToken(); 139 140 private final ArrayList<SurfaceControl> mPendingDestroyingSurfaces = new ArrayList<>(); 141 142 public WindowSurfacePlacer(WindowManagerService service) { 143 mService = service; 144 mWallpaperControllerLocked = mService.mWallpaperControllerLocked; 145 } 146 147 /** 148 * See {@link WindowManagerService#deferSurfaceLayout()} 149 */ 150 void deferLayout() { 151 mDeferDepth++; 152 } 153 154 /** 155 * See {@link WindowManagerService#continueSurfaceLayout()} 156 */ 157 void continueLayout() { 158 mDeferDepth--; 159 if (mDeferDepth <= 0) { 160 performSurfacePlacement(); 161 } 162 } 163 164 final void performSurfacePlacement() { 165 if (mDeferDepth > 0) { 166 return; 167 } 168 int loopCount = 6; 169 do { 170 mTraversalScheduled = false; 171 performSurfacePlacementLoop(); 172 mService.mH.removeMessages(DO_TRAVERSAL); 173 loopCount--; 174 } while (mTraversalScheduled && loopCount > 0); 175 mWallpaperActionPending = false; 176 } 177 178 private void performSurfacePlacementLoop() { 179 if (mInLayout) { 180 if (DEBUG) { 181 throw new RuntimeException("Recursive call!"); 182 } 183 Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers=" 184 + Debug.getCallers(3)); 185 return; 186 } 187 188 if (mService.mWaitingForConfig) { 189 // Our configuration has changed (most likely rotation), but we 190 // don't yet have the complete configuration to report to 191 // applications. Don't do any window layout until we have it. 192 return; 193 } 194 195 if (!mService.mDisplayReady) { 196 // Not yet initialized, nothing to do. 197 return; 198 } 199 200 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout"); 201 mInLayout = true; 202 203 boolean recoveringMemory = false; 204 if (!mService.mForceRemoves.isEmpty()) { 205 recoveringMemory = true; 206 // Wait a little bit for things to settle down, and off we go. 207 while (!mService.mForceRemoves.isEmpty()) { 208 WindowState ws = mService.mForceRemoves.remove(0); 209 Slog.i(TAG, "Force removing: " + ws); 210 mService.removeWindowInnerLocked(ws); 211 } 212 Slog.w(TAG, "Due to memory failure, waiting a bit for next layout"); 213 Object tmp = new Object(); 214 synchronized (tmp) { 215 try { 216 tmp.wait(250); 217 } catch (InterruptedException e) { 218 } 219 } 220 } 221 222 try { 223 performSurfacePlacementInner(recoveringMemory); 224 225 mInLayout = false; 226 227 if (mService.needsLayout()) { 228 if (++mLayoutRepeatCount < 6) { 229 requestTraversal(); 230 } else { 231 Slog.e(TAG, "Performed 6 layouts in a row. Skipping"); 232 mLayoutRepeatCount = 0; 233 } 234 } else { 235 mLayoutRepeatCount = 0; 236 } 237 238 if (mService.mWindowsChanged && !mService.mWindowChangeListeners.isEmpty()) { 239 mService.mH.removeMessages(REPORT_WINDOWS_CHANGE); 240 mService.mH.sendEmptyMessage(REPORT_WINDOWS_CHANGE); 241 } 242 } catch (RuntimeException e) { 243 mInLayout = false; 244 Slog.wtf(TAG, "Unhandled exception while laying out windows", e); 245 } 246 247 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 248 } 249 250 void debugLayoutRepeats(final String msg, int pendingLayoutChanges) { 251 if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) { 252 Slog.v(TAG, "Layouts looping: " + msg + 253 ", mPendingLayoutChanges = 0x" + Integer.toHexString(pendingLayoutChanges)); 254 } 255 } 256 257 // "Something has changed! Let's make it correct now." 258 private void performSurfacePlacementInner(boolean recoveringMemory) { 259 if (DEBUG_WINDOW_TRACE) Slog.v(TAG, "performSurfacePlacementInner: entry. Called by " 260 + Debug.getCallers(3)); 261 262 int i; 263 boolean updateInputWindowsNeeded = false; 264 265 if (mService.mFocusMayChange) { 266 mService.mFocusMayChange = false; 267 updateInputWindowsNeeded = mService.updateFocusedWindowLocked( 268 UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/); 269 } 270 271 // Initialize state of exiting tokens. 272 final int numDisplays = mService.mDisplayContents.size(); 273 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 274 final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx); 275 for (i=displayContent.mExitingTokens.size()-1; i>=0; i--) { 276 displayContent.mExitingTokens.get(i).hasVisible = false; 277 } 278 } 279 280 for (int stackNdx = mService.mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) { 281 // Initialize state of exiting applications. 282 final AppTokenList exitingAppTokens = 283 mService.mStackIdToStack.valueAt(stackNdx).mExitingAppTokens; 284 for (int tokenNdx = exitingAppTokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 285 exitingAppTokens.get(tokenNdx).hasVisible = false; 286 } 287 } 288 289 mHoldScreen = null; 290 mScreenBrightness = -1; 291 mButtonBrightness = -1; 292 mUserActivityTimeout = -1; 293 mObscureApplicationContentOnSecondaryDisplays = false; 294 mSustainedPerformanceModeCurrent = false; 295 mService.mTransactionSequence++; 296 297 final DisplayContent defaultDisplay = mService.getDefaultDisplayContentLocked(); 298 final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo(); 299 final int defaultDw = defaultInfo.logicalWidth; 300 final int defaultDh = defaultInfo.logicalHeight; 301 302 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 303 ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces"); 304 SurfaceControl.openTransaction(); 305 try { 306 applySurfaceChangesTransaction(recoveringMemory, numDisplays, defaultDw, defaultDh); 307 } catch (RuntimeException e) { 308 Slog.wtf(TAG, "Unhandled exception in Window Manager", e); 309 } finally { 310 SurfaceControl.closeTransaction(); 311 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 312 "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces"); 313 } 314 315 final WindowList defaultWindows = defaultDisplay.getWindowList(); 316 317 // If we are ready to perform an app transition, check through 318 // all of the app tokens to be shown and see if they are ready 319 // to go. 320 if (mService.mAppTransition.isReady()) { 321 defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows); 322 if (DEBUG_LAYOUT_REPEATS) 323 debugLayoutRepeats("after handleAppTransitionReadyLocked", 324 defaultDisplay.pendingLayoutChanges); 325 } 326 327 if (!mService.mAnimator.mAppWindowAnimating && mService.mAppTransition.isRunning()) { 328 // We have finished the animation of an app transition. To do 329 // this, we have delayed a lot of operations like showing and 330 // hiding apps, moving apps in Z-order, etc. The app token list 331 // reflects the correct Z-order, but the window list may now 332 // be out of sync with it. So here we will just rebuild the 333 // entire app window list. Fun! 334 defaultDisplay.pendingLayoutChanges |= 335 mService.handleAnimatingStoppedAndTransitionLocked(); 336 if (DEBUG_LAYOUT_REPEATS) 337 debugLayoutRepeats("after handleAnimStopAndXitionLock", 338 defaultDisplay.pendingLayoutChanges); 339 } 340 341 if (mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0 342 && !mService.mAppTransition.isReady()) { 343 // At this point, there was a window with a wallpaper that 344 // was force hiding other windows behind it, but now it 345 // is going away. This may be simple -- just animate 346 // away the wallpaper and its window -- or it may be 347 // hard -- the wallpaper now needs to be shown behind 348 // something that was hidden. 349 defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT; 350 if (DEBUG_LAYOUT_REPEATS) 351 debugLayoutRepeats("after animateAwayWallpaperLocked", 352 defaultDisplay.pendingLayoutChanges); 353 } 354 mWallpaperForceHidingChanged = false; 355 356 if (mWallpaperMayChange) { 357 if (DEBUG_WALLPAPER_LIGHT) 358 Slog.v(TAG, "Wallpaper may change! Adjusting"); 359 defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 360 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("WallpaperMayChange", 361 defaultDisplay.pendingLayoutChanges); 362 } 363 364 if (mService.mFocusMayChange) { 365 mService.mFocusMayChange = false; 366 if (mService.updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, 367 false /*updateInputWindows*/)) { 368 updateInputWindowsNeeded = true; 369 defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM; 370 } 371 } 372 373 if (mService.needsLayout()) { 374 defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT; 375 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded", 376 defaultDisplay.pendingLayoutChanges); 377 } 378 379 for (i = mService.mResizingWindows.size() - 1; i >= 0; i--) { 380 WindowState win = mService.mResizingWindows.get(i); 381 if (win.mAppFreezing) { 382 // Don't remove this window until rotation has completed. 383 continue; 384 } 385 // Discard the saved surface if window size is changed, it can't be reused. 386 if (win.mAppToken != null) { 387 win.mAppToken.destroySavedSurfaces(); 388 } 389 win.reportResized(); 390 mService.mResizingWindows.remove(i); 391 } 392 393 if (DEBUG_ORIENTATION && mService.mDisplayFrozen) Slog.v(TAG, 394 "With display frozen, orientationChangeComplete=" + mOrientationChangeComplete); 395 if (mOrientationChangeComplete) { 396 if (mService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_NONE) { 397 mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_NONE; 398 mService.mLastFinishedFreezeSource = mLastWindowFreezeSource; 399 mService.mH.removeMessages(WINDOW_FREEZE_TIMEOUT); 400 } 401 mService.stopFreezingDisplayLocked(); 402 } 403 404 // Destroy the surface of any windows that are no longer visible. 405 boolean wallpaperDestroyed = false; 406 i = mService.mDestroySurface.size(); 407 if (i > 0) { 408 do { 409 i--; 410 WindowState win = mService.mDestroySurface.get(i); 411 win.mDestroying = false; 412 if (mService.mInputMethodWindow == win) { 413 mService.mInputMethodWindow = null; 414 } 415 if (mWallpaperControllerLocked.isWallpaperTarget(win)) { 416 wallpaperDestroyed = true; 417 } 418 win.destroyOrSaveSurface(); 419 } while (i > 0); 420 mService.mDestroySurface.clear(); 421 } 422 423 // Time to remove any exiting tokens? 424 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 425 final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx); 426 ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens; 427 for (i = exitingTokens.size() - 1; i >= 0; i--) { 428 WindowToken token = exitingTokens.get(i); 429 if (!token.hasVisible) { 430 exitingTokens.remove(i); 431 if (token.windowType == TYPE_WALLPAPER) { 432 mWallpaperControllerLocked.removeWallpaperToken(token); 433 } 434 } 435 } 436 } 437 438 // Time to remove any exiting applications? 439 for (int stackNdx = mService.mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) { 440 // Initialize state of exiting applications. 441 final AppTokenList exitingAppTokens = 442 mService.mStackIdToStack.valueAt(stackNdx).mExitingAppTokens; 443 for (i = exitingAppTokens.size() - 1; i >= 0; i--) { 444 AppWindowToken token = exitingAppTokens.get(i); 445 if (!token.hasVisible && !mService.mClosingApps.contains(token) && 446 (!token.mIsExiting || token.allAppWindows.isEmpty())) { 447 // Make sure there is no animation running on this token, 448 // so any windows associated with it will be removed as 449 // soon as their animations are complete 450 token.mAppAnimator.clearAnimation(); 451 token.mAppAnimator.animating = false; 452 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 453 "performLayout: App token exiting now removed" + token); 454 token.removeAppFromTaskLocked(); 455 } 456 } 457 } 458 459 if (wallpaperDestroyed) { 460 defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 461 defaultDisplay.layoutNeeded = true; 462 } 463 464 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 465 final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx); 466 if (displayContent.pendingLayoutChanges != 0) { 467 displayContent.layoutNeeded = true; 468 } 469 } 470 471 // Finally update all input windows now that the window changes have stabilized. 472 mService.mInputMonitor.updateInputWindowsLw(true /*force*/); 473 474 mService.setHoldScreenLocked(mHoldScreen); 475 if (!mService.mDisplayFrozen) { 476 if (mScreenBrightness < 0 || mScreenBrightness > 1.0f) { 477 mService.mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(-1); 478 } else { 479 mService.mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager( 480 toBrightnessOverride(mScreenBrightness)); 481 } 482 if (mButtonBrightness < 0 483 || mButtonBrightness > 1.0f) { 484 mService.mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(-1); 485 } else { 486 mService.mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager( 487 toBrightnessOverride(mButtonBrightness)); 488 } 489 mService.mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager( 490 mUserActivityTimeout); 491 } 492 493 if (mSustainedPerformanceModeCurrent != mSustainedPerformanceModeEnabled) { 494 mSustainedPerformanceModeEnabled = mSustainedPerformanceModeCurrent; 495 mService.mPowerManagerInternal.powerHint( 496 mService.mPowerManagerInternal.POWER_HINT_SUSTAINED_PERFORMANCE_MODE, 497 (mSustainedPerformanceModeEnabled ? 1 : 0)); 498 } 499 500 if (mService.mTurnOnScreen) { 501 if (mService.mAllowTheaterModeWakeFromLayout 502 || Settings.Global.getInt(mService.mContext.getContentResolver(), 503 Settings.Global.THEATER_MODE_ON, 0) == 0) { 504 if (DEBUG_VISIBILITY || DEBUG_POWER) { 505 Slog.v(TAG, "Turning screen on after layout!"); 506 } 507 mService.mPowerManager.wakeUp(SystemClock.uptimeMillis(), 508 "android.server.wm:TURN_ON"); 509 } 510 mService.mTurnOnScreen = false; 511 } 512 513 if (mUpdateRotation) { 514 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 515 if (mService.updateRotationUncheckedLocked(false)) { 516 mService.mH.sendEmptyMessage(SEND_NEW_CONFIGURATION); 517 } else { 518 mUpdateRotation = false; 519 } 520 } 521 522 if (mService.mWaitingForDrawnCallback != null || 523 (mOrientationChangeComplete && !defaultDisplay.layoutNeeded && 524 !mUpdateRotation)) { 525 mService.checkDrawnWindowsLocked(); 526 } 527 528 final int N = mService.mPendingRemove.size(); 529 if (N > 0) { 530 if (mService.mPendingRemoveTmp.length < N) { 531 mService.mPendingRemoveTmp = new WindowState[N+10]; 532 } 533 mService.mPendingRemove.toArray(mService.mPendingRemoveTmp); 534 mService.mPendingRemove.clear(); 535 DisplayContentList displayList = new DisplayContentList(); 536 for (i = 0; i < N; i++) { 537 WindowState w = mService.mPendingRemoveTmp[i]; 538 mService.removeWindowInnerLocked(w); 539 final DisplayContent displayContent = w.getDisplayContent(); 540 if (displayContent != null && !displayList.contains(displayContent)) { 541 displayList.add(displayContent); 542 } 543 } 544 545 for (DisplayContent displayContent : displayList) { 546 mService.mLayersController.assignLayersLocked(displayContent.getWindowList()); 547 displayContent.layoutNeeded = true; 548 } 549 } 550 551 // Remove all deferred displays stacks, tasks, and activities. 552 for (int displayNdx = mService.mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) { 553 mService.mDisplayContents.valueAt(displayNdx).checkForDeferredActions(); 554 } 555 556 if (updateInputWindowsNeeded) { 557 mService.mInputMonitor.updateInputWindowsLw(false /*force*/); 558 } 559 mService.setFocusTaskRegionLocked(); 560 561 // Check to see if we are now in a state where the screen should 562 // be enabled, because the window obscured flags have changed. 563 mService.enableScreenIfNeededLocked(); 564 565 mService.scheduleAnimationLocked(); 566 mService.mWindowPlacerLocked.destroyPendingSurfaces(); 567 568 if (DEBUG_WINDOW_TRACE) Slog.e(TAG, 569 "performSurfacePlacementInner exit: animating=" + mService.mAnimator.isAnimating()); 570 } 571 572 private void applySurfaceChangesTransaction(boolean recoveringMemory, int numDisplays, 573 int defaultDw, int defaultDh) { 574 if (mService.mWatermark != null) { 575 mService.mWatermark.positionSurface(defaultDw, defaultDh); 576 } 577 if (mService.mStrictModeFlash != null) { 578 mService.mStrictModeFlash.positionSurface(defaultDw, defaultDh); 579 } 580 if (mService.mCircularDisplayMask != null) { 581 mService.mCircularDisplayMask.positionSurface(defaultDw, defaultDh, 582 mService.mRotation); 583 } 584 if (mService.mEmulatorDisplayOverlay != null) { 585 mService.mEmulatorDisplayOverlay.positionSurface(defaultDw, defaultDh, 586 mService.mRotation); 587 } 588 589 boolean focusDisplayed = false; 590 591 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 592 final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx); 593 boolean updateAllDrawn = false; 594 WindowList windows = displayContent.getWindowList(); 595 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 596 final int displayId = displayContent.getDisplayId(); 597 final int dw = displayInfo.logicalWidth; 598 final int dh = displayInfo.logicalHeight; 599 final int innerDw = displayInfo.appWidth; 600 final int innerDh = displayInfo.appHeight; 601 final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY); 602 603 // Reset for each display. 604 mDisplayHasContent = false; 605 mPreferredRefreshRate = 0; 606 mPreferredModeId = 0; 607 608 int repeats = 0; 609 do { 610 repeats++; 611 if (repeats > 6) { 612 Slog.w(TAG, "Animation repeat aborted after too many iterations"); 613 displayContent.layoutNeeded = false; 614 break; 615 } 616 617 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats( 618 "On entry to LockedInner", displayContent.pendingLayoutChanges); 619 620 if ((displayContent.pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0 && 621 mWallpaperControllerLocked.adjustWallpaperWindows()) { 622 mService.mLayersController.assignLayersLocked(windows); 623 displayContent.layoutNeeded = true; 624 } 625 626 if (isDefaultDisplay 627 && (displayContent.pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) { 628 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); 629 if (mService.updateOrientationFromAppTokensLocked(true)) { 630 displayContent.layoutNeeded = true; 631 mService.mH.sendEmptyMessage(SEND_NEW_CONFIGURATION); 632 } 633 } 634 635 if ((displayContent.pendingLayoutChanges & FINISH_LAYOUT_REDO_LAYOUT) != 0) { 636 displayContent.layoutNeeded = true; 637 } 638 639 // FIRST LOOP: Perform a layout, if needed. 640 if (repeats < LAYOUT_REPEAT_THRESHOLD) { 641 performLayoutLockedInner(displayContent, repeats == 1, 642 false /* updateInputWindows */); 643 } else { 644 Slog.w(TAG, "Layout repeat skipped after too many iterations"); 645 } 646 647 // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think 648 // it is animating. 649 displayContent.pendingLayoutChanges = 0; 650 651 if (isDefaultDisplay) { 652 mService.mPolicy.beginPostLayoutPolicyLw(dw, dh); 653 for (int i = windows.size() - 1; i >= 0; i--) { 654 WindowState w = windows.get(i); 655 if (w.mHasSurface) { 656 mService.mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs, 657 w.mAttachedWindow); 658 } 659 } 660 displayContent.pendingLayoutChanges |= 661 mService.mPolicy.finishPostLayoutPolicyLw(); 662 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after finishPostLayoutPolicyLw", 663 displayContent.pendingLayoutChanges); 664 } 665 } while (displayContent.pendingLayoutChanges != 0); 666 667 mObscured = false; 668 mSyswin = false; 669 displayContent.resetDimming(); 670 671 // Only used if default window 672 final boolean someoneLosingFocus = !mService.mLosingFocus.isEmpty(); 673 674 for (int i = windows.size() - 1; i >= 0; i--) { 675 WindowState w = windows.get(i); 676 final Task task = w.getTask(); 677 final boolean obscuredChanged = w.mObscured != mObscured; 678 679 // Update effect. 680 w.mObscured = mObscured; 681 if (!mObscured) { 682 handleNotObscuredLocked(w, displayInfo); 683 } 684 685 w.applyDimLayerIfNeeded(); 686 687 if (isDefaultDisplay && obscuredChanged 688 && mWallpaperControllerLocked.isWallpaperTarget(w) && w.isVisibleLw()) { 689 // This is the wallpaper target and its obscured state 690 // changed... make sure the current wallaper's visibility 691 // has been updated accordingly. 692 mWallpaperControllerLocked.updateWallpaperVisibility(); 693 } 694 695 final WindowStateAnimator winAnimator = w.mWinAnimator; 696 697 // If the window has moved due to its containing content frame changing, then 698 // notify the listeners and optionally animate it. Simply checking a change of 699 // position is not enough, because being move due to dock divider is not a trigger 700 // for animation. 701 if (w.hasMoved()) { 702 // Frame has moved, containing content frame has also moved, and we're not 703 // currently animating... let's do something. 704 final int left = w.mFrame.left; 705 final int top = w.mFrame.top; 706 final boolean adjustedForMinimizedDockOrIme = task != null 707 && (task.mStack.isAdjustedForMinimizedDockedStack() 708 || task.mStack.isAdjustedForIme()); 709 if ((w.mAttrs.privateFlags & PRIVATE_FLAG_NO_MOVE_ANIMATION) == 0 710 && !w.isDragResizing() && !adjustedForMinimizedDockOrIme 711 && (task == null || !w.getTask().mStack.getFreezeMovementAnimations()) 712 && !w.mWinAnimator.mLastHidden) { 713 winAnimator.setMoveAnimation(left, top); 714 } 715 716 //TODO (multidisplay): Accessibility supported only for the default display. 717 if (mService.mAccessibilityController != null 718 && displayId == Display.DEFAULT_DISPLAY) { 719 mService.mAccessibilityController.onSomeWindowResizedOrMovedLocked(); 720 } 721 722 try { 723 w.mClient.moved(left, top); 724 } catch (RemoteException e) { 725 } 726 w.mMovedByResize = false; 727 } 728 729 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); 730 w.mContentChanged = false; 731 732 // Moved from updateWindowsAndWallpaperLocked(). 733 if (w.mHasSurface) { 734 // If we have recently synchronized a previous transaction for this 735 // window ensure we don't push through an unsynchronized one now. 736 winAnimator.deferToPendingTransaction(); 737 738 // Take care of the window being ready to display. 739 final boolean committed = winAnimator.commitFinishDrawingLocked(); 740 if (isDefaultDisplay && committed) { 741 if (w.mAttrs.type == TYPE_DREAM) { 742 // HACK: When a dream is shown, it may at that 743 // point hide the lock screen. So we need to 744 // redo the layout to let the phone window manager 745 // make this happen. 746 displayContent.pendingLayoutChanges |= 747 FINISH_LAYOUT_REDO_LAYOUT; 748 if (DEBUG_LAYOUT_REPEATS) { 749 debugLayoutRepeats("dream and commitFinishDrawingLocked true", 750 displayContent.pendingLayoutChanges); 751 } 752 } 753 if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) { 754 if (DEBUG_WALLPAPER_LIGHT) 755 Slog.v(TAG, "First draw done in potential wallpaper target " + w); 756 mWallpaperMayChange = true; 757 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 758 if (DEBUG_LAYOUT_REPEATS) { 759 debugLayoutRepeats("wallpaper and commitFinishDrawingLocked true", 760 displayContent.pendingLayoutChanges); 761 } 762 } 763 } 764 if (!winAnimator.isAnimationStarting()) { 765 // Updates the shown frame before we set up the surface. This is needed 766 // because the resizing could change the top-left position (in addition to 767 // size) of the window. setSurfaceBoundariesLocked uses mShownPosition to 768 // position the surface. 769 // 770 // If an animation is being started, we can't call this method because the 771 // animation hasn't processed its initial transformation yet, but in general 772 // we do want to update the position if the window is animating. 773 winAnimator.computeShownFrameLocked(); 774 } 775 winAnimator.setSurfaceBoundariesLocked(recoveringMemory); 776 } 777 778 final AppWindowToken atoken = w.mAppToken; 779 if (DEBUG_STARTING_WINDOW && atoken != null && w == atoken.startingWindow) { 780 Slog.d(TAG, "updateWindows: starting " + w 781 + " isOnScreen=" + w.isOnScreen() + " allDrawn=" + atoken.allDrawn 782 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen); 783 } 784 if (atoken != null && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) { 785 if (atoken.lastTransactionSequence != mService.mTransactionSequence) { 786 atoken.lastTransactionSequence = mService.mTransactionSequence; 787 atoken.numInterestingWindows = atoken.numDrawnWindows = 0; 788 atoken.startingDisplayed = false; 789 } 790 if ((w.isOnScreenIgnoringKeyguard() 791 || winAnimator.mAttrType == TYPE_BASE_APPLICATION) 792 && !w.mAnimatingExit && !w.mDestroying) { 793 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) { 794 Slog.v(TAG, "Eval win " + w + ": isDrawn=" 795 + w.isDrawnLw() 796 + ", isAnimationSet=" + winAnimator.isAnimationSet()); 797 if (!w.isDrawnLw()) { 798 Slog.v(TAG, "Not displayed: s=" 799 + winAnimator.mSurfaceController 800 + " pv=" + w.mPolicyVisibility 801 + " mDrawState=" + winAnimator.drawStateToString() 802 + " ah=" + w.mAttachedHidden 803 + " th=" + atoken.hiddenRequested 804 + " a=" + winAnimator.mAnimating); 805 } 806 } 807 if (w != atoken.startingWindow) { 808 if (!w.mAppDied && 809 (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing)) { 810 atoken.numInterestingWindows++; 811 if (w.isDrawnLw()) { 812 atoken.numDrawnWindows++; 813 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) 814 Slog.v(TAG, "tokenMayBeDrawn: " + atoken 815 + " freezingScreen=" 816 + atoken.mAppAnimator.freezingScreen 817 + " mAppFreezing=" + w.mAppFreezing); 818 updateAllDrawn = true; 819 } 820 } 821 } else if (w.isDrawnLw()) { 822 mService.mH.sendEmptyMessage(NOTIFY_STARTING_WINDOW_DRAWN); 823 atoken.startingDisplayed = true; 824 } 825 } 826 } 827 828 if (isDefaultDisplay && someoneLosingFocus && w == mService.mCurrentFocus 829 && w.isDisplayedLw()) { 830 focusDisplayed = true; 831 } 832 833 mService.updateResizingWindows(w); 834 } 835 836 mService.mDisplayManagerInternal.setDisplayProperties(displayId, 837 mDisplayHasContent, 838 mPreferredRefreshRate, 839 mPreferredModeId, 840 true /* inTraversal, must call performTraversalInTrans... below */); 841 842 mService.getDisplayContentLocked(displayId).stopDimmingIfNeeded(); 843 844 if (updateAllDrawn) { 845 updateAllDrawnLocked(displayContent); 846 } 847 } 848 849 if (focusDisplayed) { 850 mService.mH.sendEmptyMessage(REPORT_LOSING_FOCUS); 851 } 852 853 // Give the display manager a chance to adjust properties 854 // like display rotation if it needs to. 855 mService.mDisplayManagerInternal.performTraversalInTransactionFromWindowManager(); 856 } 857 858 boolean isInLayout() { 859 return mInLayout; 860 } 861 862 final void performLayoutLockedInner(final DisplayContent displayContent, 863 boolean initial, boolean updateInputWindows) { 864 if (!displayContent.layoutNeeded) { 865 return; 866 } 867 displayContent.layoutNeeded = false; 868 WindowList windows = displayContent.getWindowList(); 869 boolean isDefaultDisplay = displayContent.isDefaultDisplay; 870 871 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 872 final int dw = displayInfo.logicalWidth; 873 final int dh = displayInfo.logicalHeight; 874 875 if (mService.mInputConsumer != null) { 876 mService.mInputConsumer.layout(dw, dh); 877 } 878 879 if (mService.mWallpaperInputConsumer != null) { 880 mService.mWallpaperInputConsumer.layout(dw, dh); 881 } 882 883 final int N = windows.size(); 884 int i; 885 886 if (DEBUG_LAYOUT) { 887 Slog.v(TAG, "-------------------------------------"); 888 Slog.v(TAG, "performLayout: needed=" 889 + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh); 890 } 891 892 mService.mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mService.mRotation, 893 mService.mCurConfiguration.uiMode); 894 if (isDefaultDisplay) { 895 // Not needed on non-default displays. 896 mService.mSystemDecorLayer = mService.mPolicy.getSystemDecorLayerLw(); 897 mService.mScreenRect.set(0, 0, dw, dh); 898 } 899 900 mService.mPolicy.getContentRectLw(mTmpContentRect); 901 displayContent.resize(mTmpContentRect); 902 903 int seq = mService.mLayoutSeq+1; 904 if (seq < 0) seq = 0; 905 mService.mLayoutSeq = seq; 906 907 boolean behindDream = false; 908 909 // First perform layout of any root windows (not attached 910 // to another window). 911 int topAttached = -1; 912 for (i = N-1; i >= 0; i--) { 913 final WindowState win = windows.get(i); 914 915 // Don't do layout of a window if it is not visible, or 916 // soon won't be visible, to avoid wasting time and funky 917 // changes while a window is animating away. 918 final boolean gone = (behindDream && mService.mPolicy.canBeForceHidden(win, win.mAttrs)) 919 || win.isGoneForLayoutLw(); 920 921 if (DEBUG_LAYOUT && !win.mLayoutAttached) { 922 Slog.v(TAG, "1ST PASS " + win 923 + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame 924 + " mLayoutAttached=" + win.mLayoutAttached 925 + " screen changed=" + win.isConfigChanged()); 926 final AppWindowToken atoken = win.mAppToken; 927 if (gone) Slog.v(TAG, " GONE: mViewVisibility=" 928 + win.mViewVisibility + " mRelayoutCalled=" 929 + win.mRelayoutCalled + " hidden=" 930 + win.mRootToken.hidden + " hiddenRequested=" 931 + (atoken != null && atoken.hiddenRequested) 932 + " mAttachedHidden=" + win.mAttachedHidden); 933 else Slog.v(TAG, " VIS: mViewVisibility=" 934 + win.mViewVisibility + " mRelayoutCalled=" 935 + win.mRelayoutCalled + " hidden=" 936 + win.mRootToken.hidden + " hiddenRequested=" 937 + (atoken != null && atoken.hiddenRequested) 938 + " mAttachedHidden=" + win.mAttachedHidden); 939 } 940 941 // If this view is GONE, then skip it -- keep the current 942 // frame, and let the caller know so they can ignore it 943 // if they want. (We do the normal layout for INVISIBLE 944 // windows, since that means "perform layout as normal, 945 // just don't display"). 946 if (!gone || !win.mHaveFrame || win.mLayoutNeeded 947 || ((win.isConfigChanged() || win.setInsetsChanged()) 948 && !win.isGoneForLayoutLw() && 949 ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 || 950 (win.mHasSurface && win.mAppToken != null && 951 win.mAppToken.layoutConfigChanges)))) { 952 if (!win.mLayoutAttached) { 953 if (initial) { 954 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 955 win.mContentChanged = false; 956 } 957 if (win.mAttrs.type == TYPE_DREAM) { 958 // Don't layout windows behind a dream, so that if it 959 // does stuff like hide the status bar we won't get a 960 // bad transition when it goes away. 961 behindDream = true; 962 } 963 win.mLayoutNeeded = false; 964 win.prelayout(); 965 mService.mPolicy.layoutWindowLw(win, null); 966 win.mLayoutSeq = seq; 967 968 // Window frames may have changed. Update dim layer with the new bounds. 969 final Task task = win.getTask(); 970 if (task != null) { 971 displayContent.mDimLayerController.updateDimLayer(task); 972 } 973 974 if (DEBUG_LAYOUT) Slog.v(TAG, 975 " LAYOUT: mFrame=" 976 + win.mFrame + " mContainingFrame=" 977 + win.mContainingFrame + " mDisplayFrame=" 978 + win.mDisplayFrame); 979 } else { 980 if (topAttached < 0) topAttached = i; 981 } 982 } 983 } 984 985 boolean attachedBehindDream = false; 986 987 // Now perform layout of attached windows, which usually 988 // depend on the position of the window they are attached to. 989 // XXX does not deal with windows that are attached to windows 990 // that are themselves attached. 991 for (i = topAttached; i >= 0; i--) { 992 final WindowState win = windows.get(i); 993 994 if (win.mLayoutAttached) { 995 if (DEBUG_LAYOUT) Slog.v(TAG, 996 "2ND PASS " + win + " mHaveFrame=" + win.mHaveFrame + " mViewVisibility=" 997 + win.mViewVisibility + " mRelayoutCalled=" + win.mRelayoutCalled); 998 // If this view is GONE, then skip it -- keep the current 999 // frame, and let the caller know so they can ignore it 1000 // if they want. (We do the normal layout for INVISIBLE 1001 // windows, since that means "perform layout as normal, 1002 // just don't display"). 1003 if (attachedBehindDream && mService.mPolicy.canBeForceHidden(win, win.mAttrs)) { 1004 continue; 1005 } 1006 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled) 1007 || !win.mHaveFrame || win.mLayoutNeeded) { 1008 if (initial) { 1009 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 1010 win.mContentChanged = false; 1011 } 1012 win.mLayoutNeeded = false; 1013 win.prelayout(); 1014 mService.mPolicy.layoutWindowLw(win, win.mAttachedWindow); 1015 win.mLayoutSeq = seq; 1016 if (DEBUG_LAYOUT) Slog.v(TAG, 1017 " LAYOUT: mFrame=" + win.mFrame + " mContainingFrame=" 1018 + win.mContainingFrame + " mDisplayFrame=" + win.mDisplayFrame); 1019 } 1020 } else if (win.mAttrs.type == TYPE_DREAM) { 1021 // Don't layout windows behind a dream, so that if it 1022 // does stuff like hide the status bar we won't get a 1023 // bad transition when it goes away. 1024 attachedBehindDream = behindDream; 1025 } 1026 } 1027 1028 // Window frames may have changed. Tell the input dispatcher about it. 1029 mService.mInputMonitor.setUpdateInputWindowsNeededLw(); 1030 if (updateInputWindows) { 1031 mService.mInputMonitor.updateInputWindowsLw(false /*force*/); 1032 } 1033 1034 mService.mPolicy.finishLayoutLw(); 1035 mService.mH.sendEmptyMessage(UPDATE_DOCKED_STACK_DIVIDER); 1036 } 1037 1038 /** 1039 * @param windows List of windows on default display. 1040 * @return bitmap indicating if another pass through layout must be made. 1041 */ 1042 private int handleAppTransitionReadyLocked(WindowList windows) { 1043 int appsCount = mService.mOpeningApps.size(); 1044 if (!transitionGoodToGo(appsCount)) { 1045 return 0; 1046 } 1047 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO"); 1048 int transit = mService.mAppTransition.getAppTransition(); 1049 if (mService.mSkipAppTransitionAnimation) { 1050 transit = AppTransition.TRANSIT_UNSET; 1051 } 1052 mService.mSkipAppTransitionAnimation = false; 1053 mService.mNoAnimationNotifyOnTransitionFinished.clear(); 1054 1055 mService.mH.removeMessages(APP_TRANSITION_TIMEOUT); 1056 1057 mService.rebuildAppWindowListLocked(); 1058 1059 mWallpaperMayChange = false; 1060 1061 // The top-most window will supply the layout params, 1062 // and we will determine it below. 1063 LayoutParams animLp = null; 1064 int bestAnimLayer = -1; 1065 boolean fullscreenAnim = false; 1066 boolean voiceInteraction = false; 1067 1068 final WindowState lowerWallpaperTarget = 1069 mWallpaperControllerLocked.getLowerWallpaperTarget(); 1070 final WindowState upperWallpaperTarget = 1071 mWallpaperControllerLocked.getUpperWallpaperTarget(); 1072 1073 boolean openingAppHasWallpaper = false; 1074 boolean closingAppHasWallpaper = false; 1075 final AppWindowToken lowerWallpaperAppToken; 1076 final AppWindowToken upperWallpaperAppToken; 1077 if (lowerWallpaperTarget == null) { 1078 lowerWallpaperAppToken = upperWallpaperAppToken = null; 1079 } else { 1080 lowerWallpaperAppToken = lowerWallpaperTarget.mAppToken; 1081 upperWallpaperAppToken = upperWallpaperTarget.mAppToken; 1082 } 1083 1084 int i; 1085 // Do a first pass through the tokens for two 1086 // things: 1087 // (1) Determine if both the closing and opening 1088 // app token sets are wallpaper targets, in which 1089 // case special animations are needed 1090 // (since the wallpaper needs to stay static 1091 // behind them). 1092 // (2) Find the layout params of the top-most 1093 // application window in the tokens, which is 1094 // what will control the animation theme. 1095 final int closingAppsCount = mService.mClosingApps.size(); 1096 appsCount = closingAppsCount + mService.mOpeningApps.size(); 1097 for (i = 0; i < appsCount; i++) { 1098 final AppWindowToken wtoken; 1099 if (i < closingAppsCount) { 1100 wtoken = mService.mClosingApps.valueAt(i); 1101 if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) { 1102 closingAppHasWallpaper = true; 1103 } 1104 } else { 1105 wtoken = mService.mOpeningApps.valueAt(i - closingAppsCount); 1106 if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) { 1107 openingAppHasWallpaper = true; 1108 } 1109 } 1110 1111 voiceInteraction |= wtoken.voiceInteraction; 1112 1113 if (wtoken.appFullscreen) { 1114 WindowState ws = wtoken.findMainWindow(); 1115 if (ws != null) { 1116 animLp = ws.mAttrs; 1117 bestAnimLayer = ws.mLayer; 1118 fullscreenAnim = true; 1119 } 1120 } else if (!fullscreenAnim) { 1121 WindowState ws = wtoken.findMainWindow(); 1122 if (ws != null) { 1123 if (ws.mLayer > bestAnimLayer) { 1124 animLp = ws.mAttrs; 1125 bestAnimLayer = ws.mLayer; 1126 } 1127 } 1128 } 1129 } 1130 1131 transit = maybeUpdateTransitToWallpaper(transit, openingAppHasWallpaper, 1132 closingAppHasWallpaper, lowerWallpaperTarget, upperWallpaperTarget); 1133 1134 // If all closing windows are obscured, then there is 1135 // no need to do an animation. This is the case, for 1136 // example, when this transition is being done behind 1137 // the lock screen. 1138 if (!mService.mPolicy.allowAppAnimationsLw()) { 1139 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 1140 "Animations disallowed by keyguard or dream."); 1141 animLp = null; 1142 } 1143 1144 processApplicationsAnimatingInPlace(transit); 1145 1146 mTmpLayerAndToken.token = null; 1147 handleClosingApps(transit, animLp, voiceInteraction, mTmpLayerAndToken); 1148 final AppWindowToken topClosingApp = mTmpLayerAndToken.token; 1149 final int topClosingLayer = mTmpLayerAndToken.layer; 1150 1151 final AppWindowToken topOpeningApp = handleOpeningApps(transit, 1152 animLp, voiceInteraction, topClosingLayer); 1153 1154 final AppWindowAnimator openingAppAnimator = (topOpeningApp == null) ? null : 1155 topOpeningApp.mAppAnimator; 1156 final AppWindowAnimator closingAppAnimator = (topClosingApp == null) ? null : 1157 topClosingApp.mAppAnimator; 1158 1159 mService.mAppTransition.goodToGo(openingAppAnimator, closingAppAnimator, 1160 mService.mOpeningApps, mService.mClosingApps); 1161 mService.mAppTransition.postAnimationCallback(); 1162 mService.mAppTransition.clear(); 1163 1164 mService.mOpeningApps.clear(); 1165 mService.mClosingApps.clear(); 1166 1167 // This has changed the visibility of windows, so perform 1168 // a new layout to get them all up-to-date. 1169 mService.getDefaultDisplayContentLocked().layoutNeeded = true; 1170 1171 // TODO(multidisplay): IMEs are only supported on the default display. 1172 if (windows == mService.getDefaultWindowListLocked() 1173 && !mService.moveInputMethodWindowsIfNeededLocked(true)) { 1174 mService.mLayersController.assignLayersLocked(windows); 1175 } 1176 mService.updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, 1177 true /*updateInputWindows*/); 1178 mService.mFocusMayChange = false; 1179 mService.notifyActivityDrawnForKeyguard(); 1180 return FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_CONFIG; 1181 } 1182 1183 private AppWindowToken handleOpeningApps(int transit, LayoutParams animLp, 1184 boolean voiceInteraction, int topClosingLayer) { 1185 AppWindowToken topOpeningApp = null; 1186 final int appsCount = mService.mOpeningApps.size(); 1187 for (int i = 0; i < appsCount; i++) { 1188 AppWindowToken wtoken = mService.mOpeningApps.valueAt(i); 1189 final AppWindowAnimator appAnimator = wtoken.mAppAnimator; 1190 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken); 1191 1192 if (!appAnimator.usingTransferredAnimation) { 1193 appAnimator.clearThumbnail(); 1194 appAnimator.setNullAnimation(); 1195 } 1196 wtoken.inPendingTransaction = false; 1197 1198 if (!mService.setTokenVisibilityLocked( 1199 wtoken, animLp, true, transit, false, voiceInteraction)){ 1200 // This token isn't going to be animating. Add it to the list of tokens to 1201 // be notified of app transition complete since the notification will not be 1202 // sent be the app window animator. 1203 mService.mNoAnimationNotifyOnTransitionFinished.add(wtoken.token); 1204 } 1205 wtoken.updateReportedVisibilityLocked(); 1206 wtoken.waitingToShow = false; 1207 1208 appAnimator.mAllAppWinAnimators.clear(); 1209 final int windowsCount = wtoken.allAppWindows.size(); 1210 for (int j = 0; j < windowsCount; j++) { 1211 appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator); 1212 } 1213 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 1214 ">>> OPEN TRANSACTION handleAppTransitionReadyLocked()"); 1215 SurfaceControl.openTransaction(); 1216 try { 1217 mService.mAnimator.orAnimating(appAnimator.showAllWindowsLocked()); 1218 } finally { 1219 SurfaceControl.closeTransaction(); 1220 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 1221 "<<< CLOSE TRANSACTION handleAppTransitionReadyLocked()"); 1222 } 1223 mService.mAnimator.mAppWindowAnimating |= appAnimator.isAnimating(); 1224 1225 int topOpeningLayer = 0; 1226 if (animLp != null) { 1227 int layer = -1; 1228 for (int j = 0; j < wtoken.windows.size(); j++) { 1229 final WindowState win = wtoken.windows.get(j); 1230 // Clearing the mAnimatingExit flag before entering animation. It will be set to true 1231 // if app window is removed, or window relayout to invisible. We don't want to 1232 // clear it out for windows that get replaced, because the animation depends on 1233 // the flag to remove the replaced window. 1234 // 1235 // We also don't clear the mAnimatingExit flag for windows which have the 1236 // mRemoveOnExit flag. This indicates an explicit remove request has been issued 1237 // by the client. We should let animation proceed and not clear this flag or 1238 // they won't eventually be removed by WindowStateAnimator#finishExit. 1239 if (!win.mWillReplaceWindow && !win.mRemoveOnExit) { 1240 win.mAnimatingExit = false; 1241 } 1242 if (win.mWinAnimator.mAnimLayer > layer) { 1243 layer = win.mWinAnimator.mAnimLayer; 1244 } 1245 } 1246 if (topOpeningApp == null || layer > topOpeningLayer) { 1247 topOpeningApp = wtoken; 1248 topOpeningLayer = layer; 1249 } 1250 } 1251 if (mService.mAppTransition.isNextAppTransitionThumbnailUp()) { 1252 createThumbnailAppAnimator(transit, wtoken, topOpeningLayer, topClosingLayer); 1253 } 1254 } 1255 return topOpeningApp; 1256 } 1257 1258 private void handleClosingApps(int transit, LayoutParams animLp, boolean voiceInteraction, 1259 LayerAndToken layerAndToken) { 1260 final int appsCount; 1261 appsCount = mService.mClosingApps.size(); 1262 for (int i = 0; i < appsCount; i++) { 1263 AppWindowToken wtoken = mService.mClosingApps.valueAt(i); 1264 final AppWindowAnimator appAnimator = wtoken.mAppAnimator; 1265 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken); 1266 appAnimator.clearThumbnail(); 1267 appAnimator.setNullAnimation(); 1268 wtoken.inPendingTransaction = false; 1269 mService.setTokenVisibilityLocked(wtoken, animLp, false, transit, false, 1270 voiceInteraction); 1271 wtoken.updateReportedVisibilityLocked(); 1272 // Force the allDrawn flag, because we want to start 1273 // this guy's animations regardless of whether it's 1274 // gotten drawn. 1275 wtoken.allDrawn = true; 1276 wtoken.deferClearAllDrawn = false; 1277 // Ensure that apps that are mid-starting are also scheduled to have their 1278 // starting windows removed after the animation is complete 1279 if (wtoken.startingWindow != null && !wtoken.startingWindow.mAnimatingExit) { 1280 mService.scheduleRemoveStartingWindowLocked(wtoken); 1281 } 1282 mService.mAnimator.mAppWindowAnimating |= appAnimator.isAnimating(); 1283 1284 if (animLp != null) { 1285 int layer = -1; 1286 for (int j = 0; j < wtoken.windows.size(); j++) { 1287 WindowState win = wtoken.windows.get(j); 1288 if (win.mWinAnimator.mAnimLayer > layer) { 1289 layer = win.mWinAnimator.mAnimLayer; 1290 } 1291 } 1292 if (layerAndToken.token == null || layer > layerAndToken.layer) { 1293 layerAndToken.token = wtoken; 1294 layerAndToken.layer = layer; 1295 } 1296 } 1297 if (mService.mAppTransition.isNextAppTransitionThumbnailDown()) { 1298 createThumbnailAppAnimator(transit, wtoken, 0, layerAndToken.layer); 1299 } 1300 } 1301 } 1302 1303 private boolean transitionGoodToGo(int appsCount) { 1304 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 1305 "Checking " + appsCount + " opening apps (frozen=" 1306 + mService.mDisplayFrozen + " timeout=" 1307 + mService.mAppTransition.isTimeout() + ")..."); 1308 int reason = APP_TRANSITION_TIMEOUT; 1309 if (!mService.mAppTransition.isTimeout()) { 1310 for (int i = 0; i < appsCount; i++) { 1311 AppWindowToken wtoken = mService.mOpeningApps.valueAt(i); 1312 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 1313 "Check opening app=" + wtoken + ": allDrawn=" 1314 + wtoken.allDrawn + " startingDisplayed=" 1315 + wtoken.startingDisplayed + " startingMoved=" 1316 + wtoken.startingMoved + " isRelaunching()=" 1317 + wtoken.isRelaunching()); 1318 1319 if (wtoken.isRelaunching()) { 1320 return false; 1321 } 1322 1323 final boolean drawnBeforeRestoring = wtoken.allDrawn; 1324 wtoken.restoreSavedSurfaces(); 1325 1326 if (!wtoken.allDrawn && !wtoken.startingDisplayed && !wtoken.startingMoved) { 1327 return false; 1328 } 1329 if (wtoken.allDrawn) { 1330 reason = drawnBeforeRestoring ? APP_TRANSITION_WINDOWS_DRAWN 1331 : APP_TRANSITION_SAVED_SURFACE; 1332 } else { 1333 reason = APP_TRANSITION_STARTING_WINDOW; 1334 } 1335 } 1336 1337 // We also need to wait for the specs to be fetched, if needed. 1338 if (mService.mAppTransition.isFetchingAppTransitionsSpecs()) { 1339 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "isFetchingAppTransitionSpecs=true"); 1340 return false; 1341 } 1342 1343 // If the wallpaper is visible, we need to check it's ready too. 1344 boolean wallpaperReady = !mWallpaperControllerLocked.isWallpaperVisible() || 1345 mWallpaperControllerLocked.wallpaperTransitionReady(); 1346 if (wallpaperReady) { 1347 mService.mH.obtainMessage(NOTIFY_APP_TRANSITION_STARTING, reason, 0).sendToTarget(); 1348 return true; 1349 } 1350 return false; 1351 } 1352 mService.mH.obtainMessage(NOTIFY_APP_TRANSITION_STARTING, reason, 0).sendToTarget(); 1353 return true; 1354 } 1355 1356 private int maybeUpdateTransitToWallpaper(int transit, boolean openingAppHasWallpaper, 1357 boolean closingAppHasWallpaper, WindowState lowerWallpaperTarget, 1358 WindowState upperWallpaperTarget) { 1359 // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper 1360 final WindowState wallpaperTarget = mWallpaperControllerLocked.getWallpaperTarget(); 1361 final WindowState oldWallpaper = 1362 mWallpaperControllerLocked.isWallpaperTargetAnimating() 1363 ? null : wallpaperTarget; 1364 final ArraySet<AppWindowToken> openingApps = mService.mOpeningApps; 1365 final ArraySet<AppWindowToken> closingApps = mService.mClosingApps; 1366 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 1367 "New wallpaper target=" + wallpaperTarget 1368 + ", oldWallpaper=" + oldWallpaper 1369 + ", lower target=" + lowerWallpaperTarget 1370 + ", upper target=" + upperWallpaperTarget 1371 + ", openingApps=" + openingApps 1372 + ", closingApps=" + closingApps); 1373 mService.mAnimateWallpaperWithTarget = false; 1374 if (closingAppHasWallpaper && openingAppHasWallpaper) { 1375 if (DEBUG_APP_TRANSITIONS) 1376 Slog.v(TAG, "Wallpaper animation!"); 1377 switch (transit) { 1378 case AppTransition.TRANSIT_ACTIVITY_OPEN: 1379 case AppTransition.TRANSIT_TASK_OPEN: 1380 case AppTransition.TRANSIT_TASK_TO_FRONT: 1381 transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN; 1382 break; 1383 case AppTransition.TRANSIT_ACTIVITY_CLOSE: 1384 case AppTransition.TRANSIT_TASK_CLOSE: 1385 case AppTransition.TRANSIT_TASK_TO_BACK: 1386 transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE; 1387 break; 1388 } 1389 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 1390 "New transit: " + AppTransition.appTransitionToString(transit)); 1391 } else if (oldWallpaper != null && !mService.mOpeningApps.isEmpty() 1392 && !openingApps.contains(oldWallpaper.mAppToken) 1393 && closingApps.contains(oldWallpaper.mAppToken)) { 1394 // We are transitioning from an activity with a wallpaper to one without. 1395 transit = AppTransition.TRANSIT_WALLPAPER_CLOSE; 1396 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 1397 "New transit away from wallpaper: " 1398 + AppTransition.appTransitionToString(transit)); 1399 } else if (wallpaperTarget != null && wallpaperTarget.isVisibleLw() && 1400 openingApps.contains(wallpaperTarget.mAppToken)) { 1401 // We are transitioning from an activity without 1402 // a wallpaper to now showing the wallpaper 1403 transit = AppTransition.TRANSIT_WALLPAPER_OPEN; 1404 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 1405 "New transit into wallpaper: " 1406 + AppTransition.appTransitionToString(transit)); 1407 } else { 1408 mService.mAnimateWallpaperWithTarget = true; 1409 } 1410 return transit; 1411 } 1412 1413 /** 1414 * @param w WindowState this method is applied to. 1415 * @param dispInfo info of the display that the window's obscuring state is checked against. 1416 */ 1417 private void handleNotObscuredLocked(final WindowState w, final DisplayInfo dispInfo) { 1418 final LayoutParams attrs = w.mAttrs; 1419 final int attrFlags = attrs.flags; 1420 final boolean canBeSeen = w.isDisplayedLw(); 1421 final int privateflags = attrs.privateFlags; 1422 1423 if (canBeSeen && w.isObscuringFullscreen(dispInfo)) { 1424 // This window completely covers everything behind it, 1425 // so we want to leave all of them as undimmed (for 1426 // performance reasons). 1427 mObscured = true; 1428 } 1429 1430 if (w.mHasSurface) { 1431 if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) { 1432 mHoldScreen = w.mSession; 1433 } 1434 if (!mSyswin && w.mAttrs.screenBrightness >= 0 1435 && mScreenBrightness < 0) { 1436 mScreenBrightness = w.mAttrs.screenBrightness; 1437 } 1438 if (!mSyswin && w.mAttrs.buttonBrightness >= 0 1439 && mButtonBrightness < 0) { 1440 mButtonBrightness = w.mAttrs.buttonBrightness; 1441 } 1442 if (!mSyswin && w.mAttrs.userActivityTimeout >= 0 1443 && mUserActivityTimeout < 0) { 1444 mUserActivityTimeout = w.mAttrs.userActivityTimeout; 1445 } 1446 1447 final int type = attrs.type; 1448 if (canBeSeen 1449 && (type == TYPE_SYSTEM_DIALOG 1450 || type == TYPE_SYSTEM_ERROR 1451 || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0)) { 1452 mSyswin = true; 1453 } 1454 1455 if (canBeSeen) { 1456 // This function assumes that the contents of the default display are 1457 // processed first before secondary displays. 1458 final DisplayContent displayContent = w.getDisplayContent(); 1459 if (displayContent != null && displayContent.isDefaultDisplay) { 1460 // While a dream or keyguard is showing, obscure ordinary application 1461 // content on secondary displays (by forcibly enabling mirroring unless 1462 // there is other content we want to show) but still allow opaque 1463 // keyguard dialogs to be shown. 1464 if (type == TYPE_DREAM || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { 1465 mObscureApplicationContentOnSecondaryDisplays = true; 1466 } 1467 mDisplayHasContent = true; 1468 } else if (displayContent != null && 1469 (!mObscureApplicationContentOnSecondaryDisplays 1470 || (mObscured && type == TYPE_KEYGUARD_DIALOG))) { 1471 // Allow full screen keyguard presentation dialogs to be seen. 1472 mDisplayHasContent = true; 1473 } 1474 if (mPreferredRefreshRate == 0 1475 && w.mAttrs.preferredRefreshRate != 0) { 1476 mPreferredRefreshRate = w.mAttrs.preferredRefreshRate; 1477 } 1478 if (mPreferredModeId == 0 1479 && w.mAttrs.preferredDisplayModeId != 0) { 1480 mPreferredModeId = w.mAttrs.preferredDisplayModeId; 1481 } 1482 if ((privateflags & PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE) != 0) { 1483 mSustainedPerformanceModeCurrent = true; 1484 } 1485 } 1486 } 1487 } 1488 1489 private void updateAllDrawnLocked(DisplayContent displayContent) { 1490 // See if any windows have been drawn, so they (and others 1491 // associated with them) can now be shown. 1492 ArrayList<TaskStack> stacks = displayContent.getStacks(); 1493 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { 1494 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 1495 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 1496 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 1497 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 1498 final AppWindowToken wtoken = tokens.get(tokenNdx); 1499 if (!wtoken.allDrawn) { 1500 int numInteresting = wtoken.numInterestingWindows; 1501 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) { 1502 if (DEBUG_VISIBILITY) 1503 Slog.v(TAG, "allDrawn: " + wtoken 1504 + " interesting=" + numInteresting 1505 + " drawn=" + wtoken.numDrawnWindows); 1506 wtoken.allDrawn = true; 1507 // Force an additional layout pass where WindowStateAnimator# 1508 // commitFinishDrawingLocked() will call performShowLocked(). 1509 displayContent.layoutNeeded = true; 1510 mService.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, 1511 wtoken.token).sendToTarget(); 1512 } 1513 } 1514 } 1515 } 1516 } 1517 } 1518 1519 private static int toBrightnessOverride(float value) { 1520 return (int)(value * PowerManager.BRIGHTNESS_ON); 1521 } 1522 1523 private void processApplicationsAnimatingInPlace(int transit) { 1524 if (transit == AppTransition.TRANSIT_TASK_IN_PLACE) { 1525 // Find the focused window 1526 final WindowState win = mService.findFocusedWindowLocked( 1527 mService.getDefaultDisplayContentLocked()); 1528 if (win != null) { 1529 final AppWindowToken wtoken = win.mAppToken; 1530 final AppWindowAnimator appAnimator = wtoken.mAppAnimator; 1531 if (DEBUG_APP_TRANSITIONS) 1532 Slog.v(TAG, "Now animating app in place " + wtoken); 1533 appAnimator.clearThumbnail(); 1534 appAnimator.setNullAnimation(); 1535 mService.updateTokenInPlaceLocked(wtoken, transit); 1536 wtoken.updateReportedVisibilityLocked(); 1537 1538 appAnimator.mAllAppWinAnimators.clear(); 1539 final int N = wtoken.allAppWindows.size(); 1540 for (int j = 0; j < N; j++) { 1541 appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator); 1542 } 1543 mService.mAnimator.mAppWindowAnimating |= appAnimator.isAnimating(); 1544 mService.mAnimator.orAnimating(appAnimator.showAllWindowsLocked()); 1545 } 1546 } 1547 } 1548 1549 private void createThumbnailAppAnimator(int transit, AppWindowToken appToken, 1550 int openingLayer, int closingLayer) { 1551 AppWindowAnimator openingAppAnimator = (appToken == null) ? null : appToken.mAppAnimator; 1552 if (openingAppAnimator == null || openingAppAnimator.animation == null) { 1553 return; 1554 } 1555 final int taskId = appToken.mTask.mTaskId; 1556 Bitmap thumbnailHeader = mService.mAppTransition.getAppTransitionThumbnailHeader(taskId); 1557 if (thumbnailHeader == null || thumbnailHeader.getConfig() == Bitmap.Config.ALPHA_8) { 1558 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG, "No thumbnail header bitmap for: " + taskId); 1559 return; 1560 } 1561 // This thumbnail animation is very special, we need to have 1562 // an extra surface with the thumbnail included with the animation. 1563 Rect dirty = new Rect(0, 0, thumbnailHeader.getWidth(), thumbnailHeader.getHeight()); 1564 try { 1565 // TODO(multi-display): support other displays 1566 final DisplayContent displayContent = mService.getDefaultDisplayContentLocked(); 1567 final Display display = displayContent.getDisplay(); 1568 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 1569 1570 // Create a new surface for the thumbnail 1571 SurfaceControl surfaceControl = new SurfaceControl(mService.mFxSession, 1572 "thumbnail anim", dirty.width(), dirty.height(), 1573 PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); 1574 surfaceControl.setLayerStack(display.getLayerStack()); 1575 if (SHOW_TRANSACTIONS) { 1576 Slog.i(TAG, " THUMBNAIL " + surfaceControl + ": CREATE"); 1577 } 1578 1579 // Draw the thumbnail onto the surface 1580 Surface drawSurface = new Surface(); 1581 drawSurface.copyFrom(surfaceControl); 1582 Canvas c = drawSurface.lockCanvas(dirty); 1583 c.drawBitmap(thumbnailHeader, 0, 0, null); 1584 drawSurface.unlockCanvasAndPost(c); 1585 drawSurface.release(); 1586 1587 // Get the thumbnail animation 1588 Animation anim; 1589 if (mService.mAppTransition.isNextThumbnailTransitionAspectScaled()) { 1590 // If this is a multi-window scenario, we use the windows frame as 1591 // destination of the thumbnail header animation. If this is a full screen 1592 // window scenario, we use the whole display as the target. 1593 WindowState win = appToken.findMainWindow(); 1594 Rect appRect = win != null ? win.getContentFrameLw() : 1595 new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight); 1596 Rect insets = win != null ? win.mContentInsets : null; 1597 // For the new aspect-scaled transition, we want it to always show 1598 // above the animating opening/closing window, and we want to 1599 // synchronize its thumbnail surface with the surface for the 1600 // open/close animation (only on the way down) 1601 anim = mService.mAppTransition.createThumbnailAspectScaleAnimationLocked(appRect, 1602 insets, thumbnailHeader, taskId, mService.mCurConfiguration.uiMode, 1603 mService.mCurConfiguration.orientation); 1604 openingAppAnimator.thumbnailForceAboveLayer = Math.max(openingLayer, closingLayer); 1605 openingAppAnimator.deferThumbnailDestruction = 1606 !mService.mAppTransition.isNextThumbnailTransitionScaleUp(); 1607 } else { 1608 anim = mService.mAppTransition.createThumbnailScaleAnimationLocked( 1609 displayInfo.appWidth, displayInfo.appHeight, transit, thumbnailHeader); 1610 } 1611 anim.restrictDuration(MAX_ANIMATION_DURATION); 1612 anim.scaleCurrentDuration(mService.getTransitionAnimationScaleLocked()); 1613 1614 openingAppAnimator.thumbnail = surfaceControl; 1615 openingAppAnimator.thumbnailLayer = openingLayer; 1616 openingAppAnimator.thumbnailAnimation = anim; 1617 mService.mAppTransition.getNextAppTransitionStartRect(taskId, mTmpStartRect); 1618 } catch (Surface.OutOfResourcesException e) { 1619 Slog.e(TAG, "Can't allocate thumbnail/Canvas surface w=" 1620 + dirty.width() + " h=" + dirty.height(), e); 1621 openingAppAnimator.clearThumbnail(); 1622 } 1623 } 1624 1625 boolean copyAnimToLayoutParamsLocked() { 1626 boolean doRequest = false; 1627 1628 final int bulkUpdateParams = mService.mAnimator.mBulkUpdateParams; 1629 if ((bulkUpdateParams & SET_UPDATE_ROTATION) != 0) { 1630 mUpdateRotation = true; 1631 doRequest = true; 1632 } 1633 if ((bulkUpdateParams & SET_WALLPAPER_MAY_CHANGE) != 0) { 1634 mWallpaperMayChange = true; 1635 doRequest = true; 1636 } 1637 if ((bulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0) { 1638 mWallpaperForceHidingChanged = true; 1639 doRequest = true; 1640 } 1641 if ((bulkUpdateParams & SET_ORIENTATION_CHANGE_COMPLETE) == 0) { 1642 mOrientationChangeComplete = false; 1643 } else { 1644 mOrientationChangeComplete = true; 1645 mLastWindowFreezeSource = mService.mAnimator.mLastWindowFreezeSource; 1646 if (mService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_NONE) { 1647 doRequest = true; 1648 } 1649 } 1650 if ((bulkUpdateParams & SET_TURN_ON_SCREEN) != 0) { 1651 mService.mTurnOnScreen = true; 1652 } 1653 if ((bulkUpdateParams & SET_WALLPAPER_ACTION_PENDING) != 0) { 1654 mWallpaperActionPending = true; 1655 } 1656 1657 return doRequest; 1658 } 1659 1660 void requestTraversal() { 1661 if (!mTraversalScheduled) { 1662 mTraversalScheduled = true; 1663 mService.mH.sendEmptyMessage(DO_TRAVERSAL); 1664 } 1665 } 1666 1667 /** 1668 * Puts the {@param surface} into a pending list to be destroyed after the current transaction 1669 * has been committed. 1670 */ 1671 void destroyAfterTransaction(SurfaceControl surface) { 1672 mPendingDestroyingSurfaces.add(surface); 1673 } 1674 1675 /** 1676 * Destroys any surfaces that have been put into the pending list with 1677 * {@link #destroyAfterTransaction}. 1678 */ 1679 void destroyPendingSurfaces() { 1680 for (int i = mPendingDestroyingSurfaces.size() - 1; i >= 0; i--) { 1681 mPendingDestroyingSurfaces.get(i).destroy(); 1682 } 1683 mPendingDestroyingSurfaces.clear(); 1684 } 1685 1686 public void dump(PrintWriter pw, String prefix) { 1687 pw.print(prefix); pw.print("mTraversalScheduled="); pw.println(mTraversalScheduled); 1688 } 1689} 1690