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