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