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