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