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