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