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