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