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