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