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