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