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