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