WindowAnimator.java revision 4501d23cedbaaa33a7a28a76af61e7b097dc2d66
1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server.wm; 18 19import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; 20import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; 21 22import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; 23import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR; 24import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; 25import static com.android.server.wm.WindowManagerService.DEBUG_KEYGUARD; 26import static com.android.server.wm.WindowSurfacePlacer.SET_UPDATE_ROTATION; 27import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE; 28import static com.android.server.wm.WindowSurfacePlacer.SET_FORCE_HIDING_CHANGED; 29import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE; 30import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_ACTION_PENDING; 31 32import android.content.Context; 33import android.os.RemoteException; 34import android.util.Slog; 35import android.util.SparseArray; 36import android.util.TimeUtils; 37import android.view.Display; 38import android.view.SurfaceControl; 39import android.view.WindowManagerPolicy; 40import android.view.animation.AlphaAnimation; 41import android.view.animation.Animation; 42import android.view.Choreographer; 43 44import java.io.PrintWriter; 45import java.util.ArrayList; 46 47/** 48 * Singleton class that carries out the animations and Surface operations in a separate task 49 * on behalf of WindowManagerService. 50 */ 51public class WindowAnimator { 52 private static final String TAG = "WindowAnimator"; 53 54 /** How long to give statusbar to clear the private keyguard flag when animating out */ 55 private static final long KEYGUARD_ANIM_TIMEOUT_MS = 1000; 56 57 final WindowManagerService mService; 58 final Context mContext; 59 final WindowManagerPolicy mPolicy; 60 61 /** Is any window animating? */ 62 boolean mAnimating; 63 64 /** Is any app window animating? */ 65 boolean mAppWindowAnimating; 66 67 final Choreographer.FrameCallback mAnimationFrameCallback; 68 69 /** Time of current animation step. Reset on each iteration */ 70 long mCurrentTime; 71 72 /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this 73 * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */ 74 private int mAnimTransactionSequence; 75 76 /** Window currently running an animation that has requested it be detached 77 * from the wallpaper. This means we need to ensure the wallpaper is 78 * visible behind it in case it animates in a way that would allow it to be 79 * seen. If multiple windows satisfy this, use the lowest window. */ 80 WindowState mWindowDetachedWallpaper = null; 81 82 int mBulkUpdateParams = 0; 83 Object mLastWindowFreezeSource; 84 85 SparseArray<DisplayContentsAnimator> mDisplayContentsAnimators = new SparseArray<>(2); 86 87 boolean mInitialized = false; 88 89 boolean mKeyguardGoingAway; 90 boolean mKeyguardGoingAwayToNotificationShade; 91 boolean mKeyguardGoingAwayDisableWindowAnimations; 92 93 /** Use one animation for all entering activities after keyguard is dismissed. */ 94 Animation mPostKeyguardExitAnimation; 95 96 // forceHiding states. 97 static final int KEYGUARD_NOT_SHOWN = 0; 98 static final int KEYGUARD_SHOWN = 1; 99 static final int KEYGUARD_ANIMATING_OUT = 2; 100 int mForceHiding = KEYGUARD_NOT_SHOWN; 101 102 private String forceHidingToString() { 103 switch (mForceHiding) { 104 case KEYGUARD_NOT_SHOWN: return "KEYGUARD_NOT_SHOWN"; 105 case KEYGUARD_SHOWN: return "KEYGUARD_SHOWN"; 106 case KEYGUARD_ANIMATING_OUT:return "KEYGUARD_ANIMATING_OUT"; 107 default: return "KEYGUARD STATE UNKNOWN " + mForceHiding; 108 } 109 } 110 111 WindowAnimator(final WindowManagerService service) { 112 mService = service; 113 mContext = service.mContext; 114 mPolicy = service.mPolicy; 115 116 mAnimationFrameCallback = new Choreographer.FrameCallback() { 117 public void doFrame(long frameTimeNs) { 118 synchronized (mService.mWindowMap) { 119 mService.mAnimationScheduled = false; 120 animateLocked(frameTimeNs); 121 } 122 } 123 }; 124 } 125 126 void addDisplayLocked(final int displayId) { 127 // Create the DisplayContentsAnimator object by retrieving it. 128 getDisplayContentsAnimatorLocked(displayId); 129 if (displayId == Display.DEFAULT_DISPLAY) { 130 mInitialized = true; 131 } 132 } 133 134 void removeDisplayLocked(final int displayId) { 135 final DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.get(displayId); 136 if (displayAnimator != null) { 137 if (displayAnimator.mScreenRotationAnimation != null) { 138 displayAnimator.mScreenRotationAnimation.kill(); 139 displayAnimator.mScreenRotationAnimation = null; 140 } 141 } 142 143 mDisplayContentsAnimators.delete(displayId); 144 } 145 146 private void updateAppWindowsLocked(int displayId) { 147 ArrayList<TaskStack> stacks = mService.getDisplayContentLocked(displayId).getStacks(); 148 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { 149 final TaskStack stack = stacks.get(stackNdx); 150 final ArrayList<Task> tasks = stack.getTasks(); 151 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 152 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 153 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 154 final AppWindowAnimator appAnimator = tokens.get(tokenNdx).mAppAnimator; 155 appAnimator.wasAnimating = appAnimator.animating; 156 if (appAnimator.stepAnimationLocked(mCurrentTime, displayId)) { 157 appAnimator.animating = true; 158 mAnimating = mAppWindowAnimating = true; 159 } else if (appAnimator.wasAnimating) { 160 // stopped animating, do one more pass through the layout 161 setAppLayoutChanges(appAnimator, 162 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER, 163 "appToken " + appAnimator.mAppToken + " done", displayId); 164 if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG, 165 "updateWindowsApps...: done animating " + appAnimator.mAppToken); 166 } 167 } 168 } 169 170 final AppTokenList exitingAppTokens = stack.mExitingAppTokens; 171 final int exitingCount = exitingAppTokens.size(); 172 for (int i = 0; i < exitingCount; i++) { 173 final AppWindowAnimator appAnimator = exitingAppTokens.get(i).mAppAnimator; 174 appAnimator.wasAnimating = appAnimator.animating; 175 if (appAnimator.stepAnimationLocked(mCurrentTime, displayId)) { 176 mAnimating = mAppWindowAnimating = true; 177 } else if (appAnimator.wasAnimating) { 178 // stopped animating, do one more pass through the layout 179 setAppLayoutChanges(appAnimator, 180 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER, 181 "exiting appToken " + appAnimator.mAppToken + " done", displayId); 182 if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG, 183 "updateWindowsApps...: done animating exiting " 184 + appAnimator.mAppToken); 185 } 186 } 187 } 188 } 189 190 private boolean shouldForceHide(WindowState win) { 191 final WindowState imeTarget = mService.mInputMethodTarget; 192 final boolean showImeOverKeyguard = imeTarget != null && imeTarget.isVisibleNow() && 193 ((imeTarget.getAttrs().flags & FLAG_SHOW_WHEN_LOCKED) != 0 194 || !mPolicy.canBeForceHidden(imeTarget, imeTarget.mAttrs)); 195 196 final WindowState winShowWhenLocked = (WindowState) mPolicy.getWinShowWhenLockedLw(); 197 final AppWindowToken appShowWhenLocked = winShowWhenLocked == null ? 198 null : winShowWhenLocked.mAppToken; 199 200 boolean allowWhenLocked = false; 201 // Show IME over the keyguard if the target allows it 202 allowWhenLocked |= (win.mIsImWindow || imeTarget == win) && showImeOverKeyguard; 203 // Show SHOW_WHEN_LOCKED windows that turn on the screen 204 allowWhenLocked |= (win.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0 && win.mTurnOnScreen; 205 206 if (appShowWhenLocked != null) { 207 allowWhenLocked |= appShowWhenLocked == win.mAppToken 208 // Show all SHOW_WHEN_LOCKED windows while they're animating 209 || (win.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0 && win.isAnimatingLw() 210 // Show error dialogs over apps that dismiss keyguard. 211 || (win.mAttrs.privateFlags & PRIVATE_FLAG_SYSTEM_ERROR) != 0; 212 } 213 214 // Only hide windows if the keyguard is active and not animating away. 215 boolean keyguardOn = mPolicy.isKeyguardShowingOrOccluded() 216 && mForceHiding != KEYGUARD_ANIMATING_OUT; 217 return keyguardOn && !allowWhenLocked && (win.getDisplayId() == Display.DEFAULT_DISPLAY); 218 } 219 220 private void updateWindowsLocked(final int displayId) { 221 ++mAnimTransactionSequence; 222 223 final WindowList windows = mService.getWindowListLocked(displayId); 224 225 if (mKeyguardGoingAway) { 226 for (int i = windows.size() - 1; i >= 0; i--) { 227 WindowState win = windows.get(i); 228 if (!mPolicy.isKeyguardHostWindow(win.mAttrs)) { 229 continue; 230 } 231 final WindowStateAnimator winAnimator = win.mWinAnimator; 232 if ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { 233 if (!winAnimator.mAnimating) { 234 if (DEBUG_KEYGUARD) Slog.d(TAG, 235 "updateWindowsLocked: creating delay animation"); 236 237 // Create a new animation to delay until keyguard is gone on its own. 238 winAnimator.mAnimation = new AlphaAnimation(1.0f, 1.0f); 239 winAnimator.mAnimation.setDuration(KEYGUARD_ANIM_TIMEOUT_MS); 240 winAnimator.mAnimationIsEntrance = false; 241 winAnimator.mAnimationStartTime = -1; 242 winAnimator.mKeyguardGoingAwayAnimation = true; 243 } 244 } else { 245 if (DEBUG_KEYGUARD) Slog.d(TAG, 246 "updateWindowsLocked: StatusBar is no longer keyguard"); 247 mKeyguardGoingAway = false; 248 winAnimator.clearAnimation(); 249 } 250 break; 251 } 252 } 253 254 mForceHiding = KEYGUARD_NOT_SHOWN; 255 256 boolean wallpaperInUnForceHiding = false; 257 boolean startingInUnForceHiding = false; 258 ArrayList<WindowStateAnimator> unForceHiding = null; 259 WindowState wallpaper = null; 260 final WallpaperController wallpaperController = mService.mWallpaperControllerLocked; 261 for (int i = windows.size() - 1; i >= 0; i--) { 262 WindowState win = windows.get(i); 263 WindowStateAnimator winAnimator = win.mWinAnimator; 264 final int flags = win.mAttrs.flags; 265 boolean canBeForceHidden = mPolicy.canBeForceHidden(win, win.mAttrs); 266 boolean shouldBeForceHidden = shouldForceHide(win); 267 if (winAnimator.mSurfaceControl != null) { 268 final boolean wasAnimating = winAnimator.mWasAnimating; 269 final boolean nowAnimating = winAnimator.stepAnimationLocked(mCurrentTime); 270 winAnimator.mWasAnimating = nowAnimating; 271 mAnimating |= nowAnimating; 272 273 boolean appWindowAnimating = winAnimator.mAppAnimator != null 274 && winAnimator.mAppAnimator.animating; 275 boolean wasAppWindowAnimating = winAnimator.mAppAnimator != null 276 && winAnimator.mAppAnimator.wasAnimating; 277 boolean anyAnimating = appWindowAnimating || nowAnimating; 278 boolean anyWasAnimating = wasAppWindowAnimating || wasAnimating; 279 280 try { 281 if (anyAnimating && !anyWasAnimating) { 282 win.mClient.onAnimationStarted(winAnimator.mAnimatingMove ? -1 283 : winAnimator.mKeyguardGoingAwayAnimation ? 1 284 : 0); 285 } else if (!anyAnimating && anyWasAnimating) { 286 win.mClient.onAnimationStopped(); 287 } 288 } catch (RemoteException e) { 289 Slog.w(TAG, "Failed to dispatch window animation state change.", e); 290 } 291 292 if (WindowManagerService.DEBUG_WALLPAPER) { 293 Slog.v(TAG, win + ": wasAnimating=" + wasAnimating + 294 ", nowAnimating=" + nowAnimating); 295 } 296 297 if (wasAnimating && !winAnimator.mAnimating 298 && wallpaperController.isWallpaperTarget(win)) { 299 mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE; 300 setPendingLayoutChanges(Display.DEFAULT_DISPLAY, 301 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER); 302 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { 303 mService.mWindowPlacerLocked.debugLayoutRepeats( 304 "updateWindowsAndWallpaperLocked 2", 305 getPendingLayoutChanges(Display.DEFAULT_DISPLAY)); 306 } 307 } 308 309 if (mPolicy.isForceHiding(win.mAttrs)) { 310 if (!wasAnimating && nowAnimating) { 311 if (DEBUG_KEYGUARD || WindowManagerService.DEBUG_ANIM || 312 WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG, 313 "Animation started that could impact force hide: " + win); 314 mBulkUpdateParams |= SET_FORCE_HIDING_CHANGED; 315 setPendingLayoutChanges(displayId, 316 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER); 317 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { 318 mService.mWindowPlacerLocked.debugLayoutRepeats( 319 "updateWindowsAndWallpaperLocked 3", 320 getPendingLayoutChanges(displayId)); 321 } 322 mService.mFocusMayChange = true; 323 } else if (mKeyguardGoingAway && !nowAnimating) { 324 // Timeout!! 325 Slog.e(TAG, "Timeout waiting for animation to startup"); 326 mPolicy.startKeyguardExitAnimation(0, 0); 327 mKeyguardGoingAway = false; 328 } 329 if (win.isReadyForDisplay()) { 330 if (nowAnimating && win.mWinAnimator.mKeyguardGoingAwayAnimation) { 331 mForceHiding = KEYGUARD_ANIMATING_OUT; 332 } else { 333 mForceHiding = win.isDrawnLw() ? KEYGUARD_SHOWN : KEYGUARD_NOT_SHOWN; 334 } 335 } 336 if (DEBUG_KEYGUARD || WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG, 337 "Force hide " + forceHidingToString() 338 + " hasSurface=" + win.mHasSurface 339 + " policyVis=" + win.mPolicyVisibility 340 + " destroying=" + win.mDestroying 341 + " attHidden=" + win.mAttachedHidden 342 + " vis=" + win.mViewVisibility 343 + " hidden=" + win.mRootToken.hidden 344 + " anim=" + win.mWinAnimator.mAnimation); 345 } else if (canBeForceHidden) { 346 if (shouldBeForceHidden) { 347 if (!win.hideLw(false, false)) { 348 // Was already hidden 349 continue; 350 } 351 if (DEBUG_KEYGUARD || WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG, 352 "Now policy hidden: " + win); 353 } else { 354 boolean applyExistingExitAnimation = mPostKeyguardExitAnimation != null 355 && !mPostKeyguardExitAnimation.hasEnded() 356 && !winAnimator.mKeyguardGoingAwayAnimation 357 && win.hasDrawnLw() 358 && win.mAttachedWindow == null 359 && !win.mIsImWindow 360 && displayId == Display.DEFAULT_DISPLAY; 361 362 // If the window is already showing and we don't need to apply an existing 363 // Keyguard exit animation, skip. 364 if (!win.showLw(false, false) && !applyExistingExitAnimation) { 365 continue; 366 } 367 final boolean visibleNow = win.isVisibleNow(); 368 if (!visibleNow) { 369 // Couldn't really show, must showLw() again when win becomes visible. 370 win.hideLw(false, false); 371 continue; 372 } 373 if (DEBUG_KEYGUARD || WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG, 374 "Now policy shown: " + win); 375 if ((mBulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0 376 && win.mAttachedWindow == null) { 377 if (unForceHiding == null) { 378 unForceHiding = new ArrayList<>(); 379 } 380 unForceHiding.add(winAnimator); 381 if ((flags & FLAG_SHOW_WALLPAPER) != 0) { 382 wallpaperInUnForceHiding = true; 383 } 384 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) { 385 startingInUnForceHiding = true; 386 } 387 } else if (applyExistingExitAnimation) { 388 // We're already in the middle of an animation. Use the existing 389 // animation to bring in this window. 390 if (DEBUG_KEYGUARD) Slog.v(TAG, 391 "Applying existing Keyguard exit animation to new window: win=" 392 + win); 393 Animation a = mPolicy.createForceHideEnterAnimation( 394 false, mKeyguardGoingAwayToNotificationShade); 395 winAnimator.setAnimation(a, mPostKeyguardExitAnimation.getStartTime()); 396 winAnimator.mKeyguardGoingAwayAnimation = true; 397 } 398 final WindowState currentFocus = mService.mCurrentFocus; 399 if (currentFocus == null || currentFocus.mLayer < win.mLayer) { 400 // We are showing on top of the current 401 // focus, so re-evaluate focus to make 402 // sure it is correct. 403 if (WindowManagerService.DEBUG_FOCUS_LIGHT) Slog.v(TAG, 404 "updateWindowsLocked: setting mFocusMayChange true"); 405 mService.mFocusMayChange = true; 406 } 407 } 408 if ((flags & FLAG_SHOW_WALLPAPER) != 0) { 409 mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE; 410 setPendingLayoutChanges(Display.DEFAULT_DISPLAY, 411 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER); 412 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { 413 mService.mWindowPlacerLocked.debugLayoutRepeats( 414 "updateWindowsAndWallpaperLocked 4", 415 getPendingLayoutChanges(Display.DEFAULT_DISPLAY)); 416 } 417 } 418 } 419 } 420 421 // If the window doesn't have a surface, the only thing we care about is the correct 422 // policy visibility. 423 else if (canBeForceHidden) { 424 if (shouldBeForceHidden) { 425 win.hideLw(false, false); 426 } else { 427 win.showLw(false, false); 428 } 429 } 430 431 final AppWindowToken atoken = win.mAppToken; 432 if (winAnimator.mDrawState == WindowStateAnimator.READY_TO_SHOW) { 433 if (atoken == null || atoken.allDrawn) { 434 if (winAnimator.performShowLocked()) { 435 setPendingLayoutChanges(displayId, 436 WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM); 437 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { 438 mService.mWindowPlacerLocked.debugLayoutRepeats( 439 "updateWindowsAndWallpaperLocked 5", 440 getPendingLayoutChanges(displayId)); 441 } 442 } 443 } 444 } 445 final AppWindowAnimator appAnimator = winAnimator.mAppAnimator; 446 if (appAnimator != null && appAnimator.thumbnail != null) { 447 if (appAnimator.thumbnailTransactionSeq != mAnimTransactionSequence) { 448 appAnimator.thumbnailTransactionSeq = mAnimTransactionSequence; 449 appAnimator.thumbnailLayer = 0; 450 } 451 if (appAnimator.thumbnailLayer < winAnimator.mAnimLayer) { 452 appAnimator.thumbnailLayer = winAnimator.mAnimLayer; 453 } 454 } 455 if (win.mIsWallpaper) { 456 wallpaper = win; 457 } 458 } // end forall windows 459 460 // If we have windows that are being show due to them no longer 461 // being force-hidden, apply the appropriate animation to them if animations are not 462 // disabled. 463 if (unForceHiding != null) { 464 if (!mKeyguardGoingAwayDisableWindowAnimations) { 465 boolean first = true; 466 for (int i=unForceHiding.size()-1; i>=0; i--) { 467 final WindowStateAnimator winAnimator = unForceHiding.get(i); 468 Animation a = mPolicy.createForceHideEnterAnimation( 469 wallpaperInUnForceHiding && !startingInUnForceHiding, 470 mKeyguardGoingAwayToNotificationShade); 471 if (a != null) { 472 if (DEBUG_KEYGUARD) Slog.v(TAG, 473 "Starting keyguard exit animation on window " + winAnimator.mWin); 474 winAnimator.setAnimation(a); 475 winAnimator.mKeyguardGoingAwayAnimation = true; 476 if (first) { 477 mPostKeyguardExitAnimation = a; 478 mPostKeyguardExitAnimation.setStartTime(mCurrentTime); 479 first = false; 480 } 481 } 482 } 483 } else if (mKeyguardGoingAway) { 484 mPolicy.startKeyguardExitAnimation(mCurrentTime, 0 /* duration */); 485 mKeyguardGoingAway = false; 486 } 487 488 489 // Wallpaper is going away in un-force-hide motion, animate it as well. 490 if (!wallpaperInUnForceHiding && wallpaper != null 491 && !mKeyguardGoingAwayDisableWindowAnimations) { 492 if (DEBUG_KEYGUARD) Slog.d(TAG, "updateWindowsLocked: wallpaper animating away"); 493 Animation a = mPolicy.createForceHideWallpaperExitAnimation( 494 mKeyguardGoingAwayToNotificationShade); 495 if (a != null) { 496 wallpaper.mWinAnimator.setAnimation(a); 497 } 498 } 499 } 500 501 if (mPostKeyguardExitAnimation != null) { 502 // We're in the midst of a keyguard exit animation. 503 if (mKeyguardGoingAway) { 504 mPolicy.startKeyguardExitAnimation(mCurrentTime + 505 mPostKeyguardExitAnimation.getStartOffset(), 506 mPostKeyguardExitAnimation.getDuration()); 507 mKeyguardGoingAway = false; 508 } 509 // mPostKeyguardExitAnimation might either be ended normally, cancelled, or "orphaned", 510 // meaning that the window it was running on was removed. We check for hasEnded() for 511 // ended normally and cancelled case, and check the time for the "orphaned" case. 512 else if (mPostKeyguardExitAnimation.hasEnded() 513 || mCurrentTime - mPostKeyguardExitAnimation.getStartTime() 514 > mPostKeyguardExitAnimation.getDuration()) { 515 // Done with the animation, reset. 516 if (DEBUG_KEYGUARD) Slog.v(TAG, "Done with Keyguard exit animations."); 517 mPostKeyguardExitAnimation = null; 518 } 519 } 520 } 521 522 private void updateWallpaperLocked(int displayId) { 523 mService.getDisplayContentLocked(displayId).resetAnimationBackgroundAnimator(); 524 525 final WindowList windows = mService.getWindowListLocked(displayId); 526 WindowState detachedWallpaper = null; 527 528 for (int i = windows.size() - 1; i >= 0; i--) { 529 final WindowState win = windows.get(i); 530 WindowStateAnimator winAnimator = win.mWinAnimator; 531 if (winAnimator.mSurfaceControl == null) { 532 continue; 533 } 534 535 final int flags = win.mAttrs.flags; 536 537 // If this window is animating, make a note that we have 538 // an animating window and take care of a request to run 539 // a detached wallpaper animation. 540 if (winAnimator.mAnimating) { 541 if (winAnimator.mAnimation != null) { 542 if ((flags & FLAG_SHOW_WALLPAPER) != 0 543 && winAnimator.mAnimation.getDetachWallpaper()) { 544 detachedWallpaper = win; 545 } 546 final int color = winAnimator.mAnimation.getBackgroundColor(); 547 if (color != 0) { 548 final TaskStack stack = win.getStack(); 549 if (stack != null) { 550 stack.setAnimationBackground(winAnimator, color); 551 } 552 } 553 } 554 mAnimating = true; 555 } 556 557 // If this window's app token is running a detached wallpaper 558 // animation, make a note so we can ensure the wallpaper is 559 // displayed behind it. 560 final AppWindowAnimator appAnimator = winAnimator.mAppAnimator; 561 if (appAnimator != null && appAnimator.animation != null 562 && appAnimator.animating) { 563 if ((flags & FLAG_SHOW_WALLPAPER) != 0 564 && appAnimator.animation.getDetachWallpaper()) { 565 detachedWallpaper = win; 566 } 567 568 final int color = appAnimator.animation.getBackgroundColor(); 569 if (color != 0) { 570 final TaskStack stack = win.getStack(); 571 if (stack != null) { 572 stack.setAnimationBackground(winAnimator, color); 573 } 574 } 575 } 576 } // end forall windows 577 578 if (mWindowDetachedWallpaper != detachedWallpaper) { 579 if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG, 580 "Detached wallpaper changed from " + mWindowDetachedWallpaper 581 + " to " + detachedWallpaper); 582 mWindowDetachedWallpaper = detachedWallpaper; 583 mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE; 584 } 585 } 586 587 /** See if any windows have been drawn, so they (and others associated with them) can now be 588 * shown. */ 589 private void testTokenMayBeDrawnLocked(int displayId) { 590 // See if any windows have been drawn, so they (and others 591 // associated with them) can now be shown. 592 final ArrayList<Task> tasks = mService.getDisplayContentLocked(displayId).getTasks(); 593 final int numTasks = tasks.size(); 594 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 595 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 596 final int numTokens = tokens.size(); 597 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 598 final AppWindowToken wtoken = tokens.get(tokenNdx); 599 AppWindowAnimator appAnimator = wtoken.mAppAnimator; 600 final boolean allDrawn = wtoken.allDrawn; 601 if (allDrawn != appAnimator.allDrawn) { 602 appAnimator.allDrawn = allDrawn; 603 if (allDrawn) { 604 // The token has now changed state to having all 605 // windows shown... what to do, what to do? 606 if (appAnimator.freezingScreen) { 607 appAnimator.showAllWindowsLocked(); 608 mService.unsetAppFreezingScreenLocked(wtoken, false, true); 609 if (WindowManagerService.DEBUG_ORIENTATION) Slog.i(TAG, 610 "Setting mOrientationChangeComplete=true because wtoken " 611 + wtoken + " numInteresting=" + wtoken.numInterestingWindows 612 + " numDrawn=" + wtoken.numDrawnWindows); 613 // This will set mOrientationChangeComplete and cause a pass through 614 // layout. 615 setAppLayoutChanges(appAnimator, 616 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER, 617 "testTokenMayBeDrawnLocked: freezingScreen", displayId); 618 } else { 619 setAppLayoutChanges(appAnimator, 620 WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM, 621 "testTokenMayBeDrawnLocked", displayId); 622 623 // We can now show all of the drawn windows! 624 if (!mService.mOpeningApps.contains(wtoken)) { 625 mAnimating |= appAnimator.showAllWindowsLocked(); 626 } 627 } 628 } 629 } 630 } 631 } 632 } 633 634 635 /** Locked on mService.mWindowMap. */ 636 private void animateLocked(long frameTimeNs) { 637 if (!mInitialized) { 638 return; 639 } 640 641 mCurrentTime = frameTimeNs / TimeUtils.NANOS_PER_MS; 642 mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE; 643 boolean wasAnimating = mAnimating; 644 mAnimating = false; 645 mAppWindowAnimating = false; 646 if (WindowManagerService.DEBUG_WINDOW_TRACE) { 647 Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime); 648 } 649 650 if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i( 651 TAG, ">>> OPEN TRANSACTION animateLocked"); 652 SurfaceControl.openTransaction(); 653 SurfaceControl.setAnimationTransaction(); 654 try { 655 final int numDisplays = mDisplayContentsAnimators.size(); 656 for (int i = 0; i < numDisplays; i++) { 657 final int displayId = mDisplayContentsAnimators.keyAt(i); 658 updateAppWindowsLocked(displayId); 659 DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i); 660 661 final ScreenRotationAnimation screenRotationAnimation = 662 displayAnimator.mScreenRotationAnimation; 663 if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) { 664 if (screenRotationAnimation.stepAnimationLocked(mCurrentTime)) { 665 mAnimating = true; 666 } else { 667 mBulkUpdateParams |= SET_UPDATE_ROTATION; 668 screenRotationAnimation.kill(); 669 displayAnimator.mScreenRotationAnimation = null; 670 671 //TODO (multidisplay): Accessibility supported only for the default display. 672 if (mService.mAccessibilityController != null 673 && displayId == Display.DEFAULT_DISPLAY) { 674 // We just finished rotation animation which means we did not 675 // anounce the rotation and waited for it to end, announce now. 676 mService.mAccessibilityController.onRotationChangedLocked( 677 mService.getDefaultDisplayContentLocked(), mService.mRotation); 678 } 679 } 680 } 681 682 // Update animations of all applications, including those 683 // associated with exiting/removed apps 684 updateWindowsLocked(displayId); 685 updateWallpaperLocked(displayId); 686 687 final WindowList windows = mService.getWindowListLocked(displayId); 688 final int N = windows.size(); 689 for (int j = 0; j < N; j++) { 690 windows.get(j).mWinAnimator.prepareSurfaceLocked(true); 691 } 692 } 693 694 for (int i = 0; i < numDisplays; i++) { 695 final int displayId = mDisplayContentsAnimators.keyAt(i); 696 697 testTokenMayBeDrawnLocked(displayId); 698 699 final ScreenRotationAnimation screenRotationAnimation = 700 mDisplayContentsAnimators.valueAt(i).mScreenRotationAnimation; 701 if (screenRotationAnimation != null) { 702 screenRotationAnimation.updateSurfacesInTransaction(); 703 } 704 705 mAnimating |= mService.getDisplayContentLocked(displayId).animateDimLayers(); 706 707 //TODO (multidisplay): Magnification is supported only for the default display. 708 if (mService.mAccessibilityController != null 709 && displayId == Display.DEFAULT_DISPLAY) { 710 mService.mAccessibilityController.drawMagnifiedRegionBorderIfNeededLocked(); 711 } 712 } 713 714 if (mAnimating) { 715 mService.scheduleAnimationLocked(); 716 } 717 718 if (mService.mWatermark != null) { 719 mService.mWatermark.drawIfNeeded(); 720 } 721 } catch (RuntimeException e) { 722 Slog.wtf(TAG, "Unhandled exception in Window Manager", e); 723 } finally { 724 SurfaceControl.closeTransaction(); 725 if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i( 726 TAG, "<<< CLOSE TRANSACTION animateLocked"); 727 } 728 729 boolean hasPendingLayoutChanges = false; 730 final int numDisplays = mService.mDisplayContents.size(); 731 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 732 final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx); 733 final int pendingChanges = getPendingLayoutChanges(displayContent.getDisplayId()); 734 if ((pendingChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) { 735 mBulkUpdateParams |= SET_WALLPAPER_ACTION_PENDING; 736 } 737 if (pendingChanges != 0) { 738 hasPendingLayoutChanges = true; 739 } 740 } 741 742 boolean doRequest = false; 743 if (mBulkUpdateParams != 0) { 744 doRequest = mService.mWindowPlacerLocked.copyAnimToLayoutParamsLocked(); 745 } 746 747 if (hasPendingLayoutChanges || doRequest) { 748 mService.requestTraversalLocked(); 749 } 750 751 if (!mAnimating && wasAnimating) { 752 mService.requestTraversalLocked(); 753 } 754 if (WindowManagerService.DEBUG_WINDOW_TRACE) { 755 Slog.i(TAG, "!!! animate: exit mAnimating=" + mAnimating 756 + " mBulkUpdateParams=" + Integer.toHexString(mBulkUpdateParams) 757 + " mPendingLayoutChanges(DEFAULT_DISPLAY)=" 758 + Integer.toHexString(getPendingLayoutChanges(Display.DEFAULT_DISPLAY))); 759 } 760 } 761 762 private static String bulkUpdateParamsToString(int bulkUpdateParams) { 763 StringBuilder builder = new StringBuilder(128); 764 if ((bulkUpdateParams & WindowSurfacePlacer.SET_UPDATE_ROTATION) != 0) { 765 builder.append(" UPDATE_ROTATION"); 766 } 767 if ((bulkUpdateParams & WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE) != 0) { 768 builder.append(" WALLPAPER_MAY_CHANGE"); 769 } 770 if ((bulkUpdateParams & WindowSurfacePlacer.SET_FORCE_HIDING_CHANGED) != 0) { 771 builder.append(" FORCE_HIDING_CHANGED"); 772 } 773 if ((bulkUpdateParams & WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE) != 0) { 774 builder.append(" ORIENTATION_CHANGE_COMPLETE"); 775 } 776 if ((bulkUpdateParams & WindowSurfacePlacer.SET_TURN_ON_SCREEN) != 0) { 777 builder.append(" TURN_ON_SCREEN"); 778 } 779 return builder.toString(); 780 } 781 782 public void dumpLocked(PrintWriter pw, String prefix, boolean dumpAll) { 783 final String subPrefix = " " + prefix; 784 final String subSubPrefix = " " + subPrefix; 785 786 for (int i = 0; i < mDisplayContentsAnimators.size(); i++) { 787 pw.print(prefix); pw.print("DisplayContentsAnimator #"); 788 pw.print(mDisplayContentsAnimators.keyAt(i)); 789 pw.println(":"); 790 DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i); 791 final WindowList windows = 792 mService.getWindowListLocked(mDisplayContentsAnimators.keyAt(i)); 793 final int N = windows.size(); 794 for (int j = 0; j < N; j++) { 795 WindowStateAnimator wanim = windows.get(j).mWinAnimator; 796 pw.print(subPrefix); pw.print("Window #"); pw.print(j); 797 pw.print(": "); pw.println(wanim); 798 } 799 if (displayAnimator.mScreenRotationAnimation != null) { 800 pw.print(subPrefix); pw.println("mScreenRotationAnimation:"); 801 displayAnimator.mScreenRotationAnimation.printTo(subSubPrefix, pw); 802 } else if (dumpAll) { 803 pw.print(subPrefix); pw.println("no ScreenRotationAnimation "); 804 } 805 pw.println(); 806 } 807 808 pw.println(); 809 810 if (dumpAll) { 811 pw.print(prefix); pw.print("mAnimTransactionSequence="); 812 pw.print(mAnimTransactionSequence); 813 pw.print(" mForceHiding="); pw.println(forceHidingToString()); 814 pw.print(prefix); pw.print("mCurrentTime="); 815 pw.println(TimeUtils.formatUptime(mCurrentTime)); 816 } 817 if (mBulkUpdateParams != 0) { 818 pw.print(prefix); pw.print("mBulkUpdateParams=0x"); 819 pw.print(Integer.toHexString(mBulkUpdateParams)); 820 pw.println(bulkUpdateParamsToString(mBulkUpdateParams)); 821 } 822 if (mWindowDetachedWallpaper != null) { 823 pw.print(prefix); pw.print("mWindowDetachedWallpaper="); 824 pw.println(mWindowDetachedWallpaper); 825 } 826 } 827 828 int getPendingLayoutChanges(final int displayId) { 829 if (displayId < 0) { 830 return 0; 831 } 832 final DisplayContent displayContent = mService.getDisplayContentLocked(displayId); 833 return (displayContent != null) ? displayContent.pendingLayoutChanges : 0; 834 } 835 836 void setPendingLayoutChanges(final int displayId, final int changes) { 837 if (displayId < 0) { 838 return; 839 } 840 final DisplayContent displayContent = mService.getDisplayContentLocked(displayId); 841 if (displayContent != null) { 842 displayContent.pendingLayoutChanges |= changes; 843 } 844 } 845 846 void setAppLayoutChanges(final AppWindowAnimator appAnimator, final int changes, String reason, 847 final int displayId) { 848 WindowList windows = appAnimator.mAppToken.allAppWindows; 849 for (int i = windows.size() - 1; i >= 0; i--) { 850 if (displayId == windows.get(i).getDisplayId()) { 851 setPendingLayoutChanges(displayId, changes); 852 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { 853 mService.mWindowPlacerLocked.debugLayoutRepeats(reason, 854 getPendingLayoutChanges(displayId)); 855 } 856 break; 857 } 858 } 859 } 860 861 private DisplayContentsAnimator getDisplayContentsAnimatorLocked(int displayId) { 862 DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.get(displayId); 863 if (displayAnimator == null) { 864 displayAnimator = new DisplayContentsAnimator(); 865 mDisplayContentsAnimators.put(displayId, displayAnimator); 866 } 867 return displayAnimator; 868 } 869 870 void setScreenRotationAnimationLocked(int displayId, ScreenRotationAnimation animation) { 871 if (displayId >= 0) { 872 getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation = animation; 873 } 874 } 875 876 ScreenRotationAnimation getScreenRotationAnimationLocked(int displayId) { 877 if (displayId < 0) { 878 return null; 879 } 880 return getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation; 881 } 882 883 private class DisplayContentsAnimator { 884 ScreenRotationAnimation mScreenRotationAnimation = null; 885 } 886} 887