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