1// Copyright 2012 Google Inc. All Rights Reserved. 2 3package com.android.server.wm; 4 5import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; 6import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; 7 8import static com.android.server.wm.WindowManagerService.LayoutFields.SET_UPDATE_ROTATION; 9import static com.android.server.wm.WindowManagerService.LayoutFields.SET_WALLPAPER_MAY_CHANGE; 10import static com.android.server.wm.WindowManagerService.LayoutFields.SET_FORCE_HIDING_CHANGED; 11import static com.android.server.wm.WindowManagerService.LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE; 12 13import static com.android.server.wm.WindowManagerService.H.UPDATE_ANIM_PARAMETERS; 14 15import android.content.Context; 16import android.os.Debug; 17import android.os.SystemClock; 18import android.util.Log; 19import android.util.Slog; 20import android.util.SparseArray; 21import android.util.SparseIntArray; 22import android.util.TimeUtils; 23import android.view.Display; 24import android.view.Surface; 25import android.view.WindowManagerPolicy; 26import android.view.animation.Animation; 27 28import com.android.server.wm.WindowManagerService.AppWindowAnimParams; 29import com.android.server.wm.WindowManagerService.LayoutFields; 30import com.android.server.wm.WindowManagerService.LayoutToAnimatorParams; 31 32import java.io.PrintWriter; 33import java.util.ArrayList; 34 35/** 36 * Singleton class that carries out the animations and Surface operations in a separate task 37 * on behalf of WindowManagerService. 38 */ 39public class WindowAnimator { 40 private static final String TAG = "WindowAnimator"; 41 42 final WindowManagerService mService; 43 final Context mContext; 44 final WindowManagerPolicy mPolicy; 45 46 boolean mAnimating; 47 48 final Runnable mAnimationRunnable; 49 50 int mAdjResult; 51 52 // Layout changes for individual Displays. Indexed by displayId. 53 SparseIntArray mPendingLayoutChanges = new SparseIntArray(); 54 55 // TODO: Assign these from each iteration through DisplayContent. Only valid between loops. 56 /** Overall window dimensions */ 57 int mDw, mDh; 58 59 /** Interior window dimensions */ 60 int mInnerDw, mInnerDh; 61 62 /** Time of current animation step. Reset on each iteration */ 63 long mCurrentTime; 64 65 /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this 66 * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */ 67 private int mAnimTransactionSequence; 68 69 // Window currently running an animation that has requested it be detached 70 // from the wallpaper. This means we need to ensure the wallpaper is 71 // visible behind it in case it animates in a way that would allow it to be 72 // seen. If multiple windows satisfy this, use the lowest window. 73 WindowState mWindowDetachedWallpaper = null; 74 75 WindowStateAnimator mUniverseBackground = null; 76 int mAboveUniverseLayer = 0; 77 78 int mBulkUpdateParams = 0; 79 80 SparseArray<DisplayContentsAnimator> mDisplayContentsAnimators = 81 new SparseArray<WindowAnimator.DisplayContentsAnimator>(); 82 83 static final int WALLPAPER_ACTION_PENDING = 1; 84 int mPendingActions; 85 86 WindowState mWallpaperTarget = null; 87 AppWindowAnimator mWpAppAnimator = null; 88 WindowState mLowerWallpaperTarget = null; 89 WindowState mUpperWallpaperTarget = null; 90 91 ArrayList<AppWindowAnimator> mAppAnimators = new ArrayList<AppWindowAnimator>(); 92 93 ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>(); 94 95 /** Parameters being passed from this into mService. */ 96 static class AnimatorToLayoutParams { 97 boolean mUpdateQueued; 98 int mBulkUpdateParams; 99 SparseIntArray mPendingLayoutChanges; 100 WindowState mWindowDetachedWallpaper; 101 } 102 /** Do not modify unless holding mService.mWindowMap or this and mAnimToLayout in that order */ 103 final AnimatorToLayoutParams mAnimToLayout = new AnimatorToLayoutParams(); 104 105 boolean mInitialized = false; 106 107 // forceHiding states. 108 static final int KEYGUARD_NOT_SHOWN = 0; 109 static final int KEYGUARD_ANIMATING_IN = 1; 110 static final int KEYGUARD_SHOWN = 2; 111 static final int KEYGUARD_ANIMATING_OUT = 3; 112 int mForceHiding = KEYGUARD_NOT_SHOWN; 113 114 private String forceHidingToString() { 115 switch (mForceHiding) { 116 case KEYGUARD_NOT_SHOWN: return "KEYGUARD_NOT_SHOWN"; 117 case KEYGUARD_ANIMATING_IN: return "KEYGUARD_ANIMATING_IN"; 118 case KEYGUARD_SHOWN: return "KEYGUARD_SHOWN"; 119 case KEYGUARD_ANIMATING_OUT:return "KEYGUARD_ANIMATING_OUT"; 120 default: return "KEYGUARD STATE UNKNOWN " + mForceHiding; 121 } 122 } 123 124 WindowAnimator(final WindowManagerService service) { 125 mService = service; 126 mContext = service.mContext; 127 mPolicy = service.mPolicy; 128 129 mAnimationRunnable = new Runnable() { 130 @Override 131 public void run() { 132 // TODO(cmautner): When full isolation is achieved for animation, the first lock 133 // goes away and only the WindowAnimator.this remains. 134 synchronized(mService.mWindowMap) { 135 synchronized(WindowAnimator.this) { 136 copyLayoutToAnimParamsLocked(); 137 animateLocked(); 138 } 139 } 140 } 141 }; 142 } 143 144 void addDisplayLocked(final int displayId) { 145 // Create the DisplayContentsAnimator object by retrieving it. 146 getDisplayContentsAnimatorLocked(displayId); 147 if (displayId == Display.DEFAULT_DISPLAY) { 148 mInitialized = true; 149 } 150 } 151 152 void removeDisplayLocked(final int displayId) { 153 final DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.get(displayId); 154 if (displayAnimator != null) { 155 if (displayAnimator.mWindowAnimationBackgroundSurface != null) { 156 displayAnimator.mWindowAnimationBackgroundSurface.kill(); 157 displayAnimator.mWindowAnimationBackgroundSurface = null; 158 } 159 if (displayAnimator.mScreenRotationAnimation != null) { 160 displayAnimator.mScreenRotationAnimation.kill(); 161 displayAnimator.mScreenRotationAnimation = null; 162 } 163 if (displayAnimator.mDimAnimator != null) { 164 displayAnimator.mDimAnimator.kill(); 165 displayAnimator.mDimAnimator = null; 166 } 167 } 168 169 mDisplayContentsAnimators.delete(displayId); 170 } 171 172 /** Locked on mAnimToLayout */ 173 void updateAnimToLayoutLocked() { 174 final AnimatorToLayoutParams animToLayout = mAnimToLayout; 175 synchronized (animToLayout) { 176 animToLayout.mBulkUpdateParams = mBulkUpdateParams; 177 animToLayout.mPendingLayoutChanges = mPendingLayoutChanges.clone(); 178 animToLayout.mWindowDetachedWallpaper = mWindowDetachedWallpaper; 179 180 if (!animToLayout.mUpdateQueued) { 181 animToLayout.mUpdateQueued = true; 182 mService.mH.sendMessage(mService.mH.obtainMessage(UPDATE_ANIM_PARAMETERS)); 183 } 184 } 185 } 186 187 /** Copy all WindowManagerService params into local params here. Locked on 'this'. */ 188 private void copyLayoutToAnimParamsLocked() { 189 final LayoutToAnimatorParams layoutToAnim = mService.mLayoutToAnim; 190 synchronized(layoutToAnim) { 191 layoutToAnim.mAnimationScheduled = false; 192 193 if (!layoutToAnim.mParamsModified) { 194 return; 195 } 196 layoutToAnim.mParamsModified = false; 197 198 if ((layoutToAnim.mChanges & LayoutToAnimatorParams.WALLPAPER_TOKENS_CHANGED) != 0) { 199 layoutToAnim.mChanges &= ~LayoutToAnimatorParams.WALLPAPER_TOKENS_CHANGED; 200 mWallpaperTokens = new ArrayList<WindowToken>(layoutToAnim.mWallpaperTokens); 201 } 202 203 if (WindowManagerService.DEBUG_WALLPAPER_LIGHT) { 204 if (mWallpaperTarget != layoutToAnim.mWallpaperTarget 205 || mLowerWallpaperTarget != layoutToAnim.mLowerWallpaperTarget 206 || mUpperWallpaperTarget != layoutToAnim.mUpperWallpaperTarget) { 207 Slog.d(TAG, "Pulling anim wallpaper: target=" + layoutToAnim.mWallpaperTarget 208 + " lower=" + layoutToAnim.mLowerWallpaperTarget + " upper=" 209 + layoutToAnim.mUpperWallpaperTarget); 210 } 211 } 212 mWallpaperTarget = layoutToAnim.mWallpaperTarget; 213 mWpAppAnimator = mWallpaperTarget == null 214 ? null : mWallpaperTarget.mAppToken == null 215 ? null : mWallpaperTarget.mAppToken.mAppAnimator; 216 mLowerWallpaperTarget = layoutToAnim.mLowerWallpaperTarget; 217 mUpperWallpaperTarget = layoutToAnim.mUpperWallpaperTarget; 218 219 // Set the new DimAnimator params. 220 final int numDisplays = mDisplayContentsAnimators.size(); 221 for (int i = 0; i < numDisplays; i++) { 222 final int displayId = mDisplayContentsAnimators.keyAt(i); 223 DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i); 224 225 displayAnimator.mWinAnimators.clear(); 226 final WinAnimatorList winAnimators = layoutToAnim.mWinAnimatorLists.get(displayId); 227 if (winAnimators != null) { 228 displayAnimator.mWinAnimators.addAll(winAnimators); 229 } 230 231 DimAnimator.Parameters dimParams = layoutToAnim.mDimParams.get(displayId); 232 if (dimParams == null) { 233 displayAnimator.mDimParams = null; 234 } else { 235 final WindowStateAnimator newWinAnimator = dimParams.mDimWinAnimator; 236 237 // Only set dim params on the highest dimmed layer. 238 final WindowStateAnimator existingDimWinAnimator = 239 displayAnimator.mDimParams == null ? 240 null : displayAnimator.mDimParams.mDimWinAnimator; 241 // Don't turn on for an unshown surface, or for any layer but the highest 242 // dimmed layer. 243 if (newWinAnimator.mSurfaceShown && (existingDimWinAnimator == null 244 || !existingDimWinAnimator.mSurfaceShown 245 || existingDimWinAnimator.mAnimLayer < newWinAnimator.mAnimLayer)) { 246 displayAnimator.mDimParams = new DimAnimator.Parameters(dimParams); 247 } 248 } 249 } 250 251 mAppAnimators.clear(); 252 final int N = layoutToAnim.mAppWindowAnimParams.size(); 253 for (int i = 0; i < N; i++) { 254 final AppWindowAnimParams params = layoutToAnim.mAppWindowAnimParams.get(i); 255 AppWindowAnimator appAnimator = params.mAppAnimator; 256 appAnimator.mAllAppWinAnimators.clear(); 257 appAnimator.mAllAppWinAnimators.addAll(params.mWinAnimators); 258 mAppAnimators.add(appAnimator); 259 } 260 } 261 } 262 263 void hideWallpapersLocked(final WindowState w, boolean fromAnimator) { 264 // There is an issue where this function can be called either from 265 // the animation or the layout side of the window manager. The problem 266 // is that if it is called from the layout side, we may not yet have 267 // propagated the current layout wallpaper state over into the animation 268 // state. If that is the case, we can do bad things like hide the 269 // wallpaper when we had just made it shown because the animation side 270 // doesn't yet see that there is now a wallpaper target. As a temporary 271 // work-around, we tell the function here which side of the window manager 272 // is calling so it can use the right state. 273 if (fromAnimator) { 274 hideWallpapersLocked(w, mWallpaperTarget, mLowerWallpaperTarget, mWallpaperTokens); 275 } else { 276 hideWallpapersLocked(w, mService.mWallpaperTarget, 277 mService.mLowerWallpaperTarget, mService.mWallpaperTokens); 278 } 279 } 280 281 void hideWallpapersLocked(final WindowState w, final WindowState wallpaperTarget, 282 final WindowState lowerWallpaperTarget, final ArrayList<WindowToken> wallpaperTokens) { 283 if ((wallpaperTarget == w && lowerWallpaperTarget == null) || wallpaperTarget == null) { 284 final int numTokens = wallpaperTokens.size(); 285 for (int i = numTokens - 1; i >= 0; i--) { 286 final WindowToken token = wallpaperTokens.get(i); 287 final int numWindows = token.windows.size(); 288 for (int j = numWindows - 1; j >= 0; j--) { 289 final WindowState wallpaper = token.windows.get(j); 290 final WindowStateAnimator winAnimator = wallpaper.mWinAnimator; 291 if (!winAnimator.mLastHidden) { 292 winAnimator.hide(); 293 mService.dispatchWallpaperVisibility(wallpaper, false); 294 setPendingLayoutChanges(Display.DEFAULT_DISPLAY, 295 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER); 296 } 297 } 298 if (WindowManagerService.DEBUG_WALLPAPER_LIGHT && !token.hidden) Slog.d(TAG, 299 "Hiding wallpaper " + token + " from " + w 300 + " target=" + wallpaperTarget + " lower=" + lowerWallpaperTarget 301 + "\n" + Debug.getCallers(5, " ")); 302 token.hidden = true; 303 } 304 } 305 } 306 307 private void updateAppWindowsLocked() { 308 int i; 309 final int NAT = mAppAnimators.size(); 310 for (i=0; i<NAT; i++) { 311 final AppWindowAnimator appAnimator = mAppAnimators.get(i); 312 final boolean wasAnimating = appAnimator.animation != null 313 && appAnimator.animation != AppWindowAnimator.sDummyAnimation; 314 if (appAnimator.stepAnimationLocked(mCurrentTime, mInnerDw, mInnerDh)) { 315 mAnimating = true; 316 } else if (wasAnimating) { 317 // stopped animating, do one more pass through the layout 318 setAppLayoutChanges(appAnimator, WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER, 319 "appToken " + appAnimator.mAppToken + " done"); 320 if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG, 321 "updateWindowsApps...: done animating " + appAnimator.mAppToken); 322 } 323 } 324 325 final int NEAT = mService.mExitingAppTokens.size(); 326 for (i=0; i<NEAT; i++) { 327 final AppWindowAnimator appAnimator = mService.mExitingAppTokens.get(i).mAppAnimator; 328 final boolean wasAnimating = appAnimator.animation != null 329 && appAnimator.animation != AppWindowAnimator.sDummyAnimation; 330 if (appAnimator.stepAnimationLocked(mCurrentTime, mInnerDw, mInnerDh)) { 331 mAnimating = true; 332 } else if (wasAnimating) { 333 // stopped animating, do one more pass through the layout 334 setAppLayoutChanges(appAnimator, WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER, 335 "exiting appToken " + appAnimator.mAppToken + " done"); 336 if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG, 337 "updateWindowsApps...: done animating exiting " + appAnimator.mAppToken); 338 } 339 } 340 } 341 342 private void updateWindowsLocked(final int displayId) { 343 ++mAnimTransactionSequence; 344 345 final WinAnimatorList winAnimatorList = 346 getDisplayContentsAnimatorLocked(displayId).mWinAnimators; 347 ArrayList<WindowStateAnimator> unForceHiding = null; 348 boolean wallpaperInUnForceHiding = false; 349 mForceHiding = KEYGUARD_NOT_SHOWN; 350 351 for (int i = winAnimatorList.size() - 1; i >= 0; i--) { 352 WindowStateAnimator winAnimator = winAnimatorList.get(i); 353 WindowState win = winAnimator.mWin; 354 final int flags = winAnimator.mAttrFlags; 355 356 if (winAnimator.mSurface != null) { 357 final boolean wasAnimating = winAnimator.mWasAnimating; 358 final boolean nowAnimating = winAnimator.stepAnimationLocked(mCurrentTime); 359 360 if (WindowManagerService.DEBUG_WALLPAPER) { 361 Slog.v(TAG, win + ": wasAnimating=" + wasAnimating + 362 ", nowAnimating=" + nowAnimating); 363 } 364 365 if (wasAnimating && !winAnimator.mAnimating && mWallpaperTarget == win) { 366 mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE; 367 setPendingLayoutChanges(Display.DEFAULT_DISPLAY, 368 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER); 369 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { 370 mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 2", 371 mPendingLayoutChanges.get(Display.DEFAULT_DISPLAY)); 372 } 373 } 374 375 if (mPolicy.doesForceHide(win, win.mAttrs)) { 376 if (!wasAnimating && nowAnimating) { 377 if (WindowManagerService.DEBUG_ANIM || 378 WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG, 379 "Animation started that could impact force hide: " + win); 380 mBulkUpdateParams |= SET_FORCE_HIDING_CHANGED; 381 setPendingLayoutChanges(displayId, 382 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER); 383 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { 384 mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 3", 385 mPendingLayoutChanges.get(displayId)); 386 } 387 mService.mFocusMayChange = true; 388 } 389 if (win.isReadyForDisplay()) { 390 if (nowAnimating) { 391 if (winAnimator.mAnimationIsEntrance) { 392 mForceHiding = KEYGUARD_ANIMATING_IN; 393 } else { 394 mForceHiding = KEYGUARD_ANIMATING_OUT; 395 } 396 } else { 397 mForceHiding = KEYGUARD_SHOWN; 398 } 399 } 400 if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG, 401 "Force hide " + mForceHiding 402 + " hasSurface=" + win.mHasSurface 403 + " policyVis=" + win.mPolicyVisibility 404 + " destroying=" + win.mDestroying 405 + " attHidden=" + win.mAttachedHidden 406 + " vis=" + win.mViewVisibility 407 + " hidden=" + win.mRootToken.hidden 408 + " anim=" + win.mWinAnimator.mAnimation); 409 } else if (mPolicy.canBeForceHidden(win, win.mAttrs)) { 410 final boolean hideWhenLocked = 411 (winAnimator.mAttrFlags & FLAG_SHOW_WHEN_LOCKED) == 0; 412 final boolean changed; 413 if (((mForceHiding == KEYGUARD_ANIMATING_IN) 414 && (!winAnimator.isAnimating() || hideWhenLocked)) 415 || ((mForceHiding == KEYGUARD_SHOWN) && hideWhenLocked)) { 416 changed = win.hideLw(false, false); 417 if (WindowManagerService.DEBUG_VISIBILITY && changed) Slog.v(TAG, 418 "Now policy hidden: " + win); 419 } else { 420 changed = win.showLw(false, false); 421 if (WindowManagerService.DEBUG_VISIBILITY && changed) Slog.v(TAG, 422 "Now policy shown: " + win); 423 if (changed) { 424 if ((mBulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0 425 && win.isVisibleNow() /*w.isReadyForDisplay()*/) { 426 if (unForceHiding == null) { 427 unForceHiding = new ArrayList<WindowStateAnimator>(); 428 } 429 unForceHiding.add(winAnimator); 430 if ((flags & FLAG_SHOW_WALLPAPER) != 0) { 431 wallpaperInUnForceHiding = true; 432 } 433 } 434 if (mCurrentFocus == null || mCurrentFocus.mLayer < win.mLayer) { 435 // We are showing on to of the current 436 // focus, so re-evaluate focus to make 437 // sure it is correct. 438 mService.mFocusMayChange = true; 439 } 440 } 441 } 442 if (changed && (flags & FLAG_SHOW_WALLPAPER) != 0) { 443 mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE; 444 setPendingLayoutChanges(Display.DEFAULT_DISPLAY, 445 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER); 446 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { 447 mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 4", 448 mPendingLayoutChanges.get(Display.DEFAULT_DISPLAY)); 449 } 450 } 451 } 452 } 453 454 final AppWindowToken atoken = win.mAppToken; 455 if (winAnimator.mDrawState == WindowStateAnimator.READY_TO_SHOW) { 456 if (atoken == null || atoken.allDrawn) { 457 if (winAnimator.performShowLocked()) { 458 mPendingLayoutChanges.put(displayId, 459 WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM); 460 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { 461 mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 5", 462 mPendingLayoutChanges.get(displayId)); 463 } 464 } 465 } 466 } 467 final AppWindowAnimator appAnimator = winAnimator.mAppAnimator; 468 if (appAnimator != null && appAnimator.thumbnail != null) { 469 if (appAnimator.thumbnailTransactionSeq != mAnimTransactionSequence) { 470 appAnimator.thumbnailTransactionSeq = mAnimTransactionSequence; 471 appAnimator.thumbnailLayer = 0; 472 } 473 if (appAnimator.thumbnailLayer < winAnimator.mAnimLayer) { 474 appAnimator.thumbnailLayer = winAnimator.mAnimLayer; 475 } 476 } 477 } // end forall windows 478 479 // If we have windows that are being show due to them no longer 480 // being force-hidden, apply the appropriate animation to them. 481 if (unForceHiding != null) { 482 for (int i=unForceHiding.size()-1; i>=0; i--) { 483 Animation a = mPolicy.createForceHideEnterAnimation(wallpaperInUnForceHiding); 484 if (a != null) { 485 final WindowStateAnimator winAnimator = unForceHiding.get(i); 486 winAnimator.setAnimation(a); 487 winAnimator.mAnimationIsEntrance = true; 488 } 489 } 490 } 491 } 492 493 private void updateWallpaperLocked(int displayId) { 494 final DisplayContentsAnimator displayAnimator = 495 getDisplayContentsAnimatorLocked(displayId); 496 final WinAnimatorList winAnimatorList = displayAnimator.mWinAnimators; 497 WindowStateAnimator windowAnimationBackground = null; 498 int windowAnimationBackgroundColor = 0; 499 WindowState detachedWallpaper = null; 500 final DimSurface windowAnimationBackgroundSurface = 501 displayAnimator.mWindowAnimationBackgroundSurface; 502 503 for (int i = winAnimatorList.size() - 1; i >= 0; i--) { 504 WindowStateAnimator winAnimator = winAnimatorList.get(i); 505 if (winAnimator.mSurface == null) { 506 continue; 507 } 508 509 final int flags = winAnimator.mAttrFlags; 510 final WindowState win = winAnimator.mWin; 511 512 // If this window is animating, make a note that we have 513 // an animating window and take care of a request to run 514 // a detached wallpaper animation. 515 if (winAnimator.mAnimating) { 516 if (winAnimator.mAnimation != null) { 517 if ((flags & FLAG_SHOW_WALLPAPER) != 0 518 && winAnimator.mAnimation.getDetachWallpaper()) { 519 detachedWallpaper = win; 520 } 521 final int backgroundColor = winAnimator.mAnimation.getBackgroundColor(); 522 if (backgroundColor != 0) { 523 if (windowAnimationBackground == null || (winAnimator.mAnimLayer < 524 windowAnimationBackground.mAnimLayer)) { 525 windowAnimationBackground = winAnimator; 526 windowAnimationBackgroundColor = backgroundColor; 527 } 528 } 529 } 530 mAnimating = true; 531 } 532 533 // If this window's app token is running a detached wallpaper 534 // animation, make a note so we can ensure the wallpaper is 535 // displayed behind it. 536 final AppWindowAnimator appAnimator = winAnimator.mAppAnimator; 537 if (appAnimator != null && appAnimator.animation != null 538 && appAnimator.animating) { 539 if ((flags & FLAG_SHOW_WALLPAPER) != 0 540 && appAnimator.animation.getDetachWallpaper()) { 541 detachedWallpaper = win; 542 } 543 544 final int backgroundColor = appAnimator.animation.getBackgroundColor(); 545 if (backgroundColor != 0) { 546 if (windowAnimationBackground == null || (winAnimator.mAnimLayer < 547 windowAnimationBackground.mAnimLayer)) { 548 windowAnimationBackground = winAnimator; 549 windowAnimationBackgroundColor = backgroundColor; 550 } 551 } 552 } 553 } // end forall windows 554 555 if (mWindowDetachedWallpaper != detachedWallpaper) { 556 if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG, 557 "Detached wallpaper changed from " + mWindowDetachedWallpaper 558 + " to " + detachedWallpaper); 559 mWindowDetachedWallpaper = detachedWallpaper; 560 mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE; 561 } 562 563 if (windowAnimationBackgroundColor != 0) { 564 // If the window that wants black is the current wallpaper 565 // target, then the black goes *below* the wallpaper so we 566 // don't cause the wallpaper to suddenly disappear. 567 int animLayer = windowAnimationBackground.mAnimLayer; 568 WindowState win = windowAnimationBackground.mWin; 569 if (mWallpaperTarget == win 570 || mLowerWallpaperTarget == win || mUpperWallpaperTarget == win) { 571 final int N = winAnimatorList.size(); 572 for (int i = 0; i < N; i++) { 573 WindowStateAnimator winAnimator = winAnimatorList.get(i); 574 if (winAnimator.mIsWallpaper) { 575 animLayer = winAnimator.mAnimLayer; 576 break; 577 } 578 } 579 } 580 581 if (windowAnimationBackgroundSurface != null) { 582 windowAnimationBackgroundSurface.show(mDw, mDh, 583 animLayer - WindowManagerService.LAYER_OFFSET_DIM, 584 windowAnimationBackgroundColor); 585 } 586 } else { 587 if (windowAnimationBackgroundSurface != null) { 588 windowAnimationBackgroundSurface.hide(); 589 } 590 } 591 } 592 593 private void testTokenMayBeDrawnLocked() { 594 // See if any windows have been drawn, so they (and others 595 // associated with them) can now be shown. 596 final int NT = mAppAnimators.size(); 597 for (int i=0; i<NT; i++) { 598 AppWindowAnimator appAnimator = mAppAnimators.get(i); 599 AppWindowToken wtoken = appAnimator.mAppToken; 600 final boolean allDrawn = wtoken.allDrawn; 601 if (allDrawn != appAnimator.allDrawn) { 602 appAnimator.allDrawn = allDrawn; 603 if (allDrawn) { 604 // The token has now changed state to having all 605 // windows shown... what to do, what to do? 606 if (appAnimator.freezingScreen) { 607 appAnimator.showAllWindowsLocked(); 608 mService.unsetAppFreezingScreenLocked(wtoken, false, true); 609 if (WindowManagerService.DEBUG_ORIENTATION) Slog.i(TAG, 610 "Setting mOrientationChangeComplete=true because wtoken " 611 + wtoken + " numInteresting=" + wtoken.numInterestingWindows 612 + " numDrawn=" + wtoken.numDrawnWindows); 613 // This will set mOrientationChangeComplete and cause a pass through layout. 614 setAppLayoutChanges(appAnimator, 615 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER, 616 "testTokenMayBeDrawnLocked: freezingScreen"); 617 } else { 618 setAppLayoutChanges(appAnimator, 619 WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM, 620 "testTokenMayBeDrawnLocked"); 621 622 // We can now show all of the drawn windows! 623 if (!mService.mOpeningApps.contains(wtoken)) { 624 mAnimating |= appAnimator.showAllWindowsLocked(); 625 } 626 } 627 } 628 } 629 } 630 } 631 632 private void performAnimationsLocked(final int displayId) { 633 updateWindowsLocked(displayId); 634 updateWallpaperLocked(displayId); 635 } 636 637 // TODO(cmautner): Change the following comment when no longer locked on mWindowMap */ 638 /** Locked on mService.mWindowMap and this. */ 639 private void animateLocked() { 640 if (!mInitialized) { 641 return; 642 } 643 644 mPendingLayoutChanges.clear(); 645 mCurrentTime = SystemClock.uptimeMillis(); 646 mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE; 647 boolean wasAnimating = mAnimating; 648 mAnimating = false; 649 if (WindowManagerService.DEBUG_WINDOW_TRACE) { 650 Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime); 651 } 652 653 if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i( 654 TAG, ">>> OPEN TRANSACTION animateLocked"); 655 Surface.openTransaction(); 656 Surface.setAnimationTransaction(); 657 try { 658 updateAppWindowsLocked(); 659 660 final int numDisplays = mDisplayContentsAnimators.size(); 661 for (int i = 0; i < numDisplays; i++) { 662 final int displayId = mDisplayContentsAnimators.keyAt(i); 663 DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i); 664 665 final ScreenRotationAnimation screenRotationAnimation = 666 displayAnimator.mScreenRotationAnimation; 667 if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) { 668 if (screenRotationAnimation.stepAnimationLocked(mCurrentTime)) { 669 mAnimating = true; 670 } else { 671 mBulkUpdateParams |= SET_UPDATE_ROTATION; 672 screenRotationAnimation.kill(); 673 displayAnimator.mScreenRotationAnimation = null; 674 } 675 } 676 677 // Update animations of all applications, including those 678 // associated with exiting/removed apps 679 performAnimationsLocked(displayId); 680 681 final WinAnimatorList winAnimatorList = displayAnimator.mWinAnimators; 682 final int N = winAnimatorList.size(); 683 for (int j = 0; j < N; j++) { 684 winAnimatorList.get(j).prepareSurfaceLocked(true); 685 } 686 } 687 688 testTokenMayBeDrawnLocked(); 689 690 for (int i = 0; i < numDisplays; i++) { 691 final int displayId = mDisplayContentsAnimators.keyAt(i); 692 DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i); 693 694 final ScreenRotationAnimation screenRotationAnimation = 695 displayAnimator.mScreenRotationAnimation; 696 if (screenRotationAnimation != null) { 697 screenRotationAnimation.updateSurfacesInTransaction(); 698 } 699 700 final DimAnimator.Parameters dimParams = displayAnimator.mDimParams; 701 final DimAnimator dimAnimator = displayAnimator.mDimAnimator; 702 if (dimAnimator != null && dimParams != null) { 703 dimAnimator.updateParameters(mContext.getResources(), dimParams, mCurrentTime); 704 } 705 if (dimAnimator != null && dimAnimator.mDimShown) { 706 mAnimating |= dimAnimator.updateSurface(isDimmingLocked(displayId), 707 mCurrentTime, !mService.okToDisplay()); 708 } 709 } 710 711 if (mService.mWatermark != null) { 712 mService.mWatermark.drawIfNeeded(); 713 } 714 } catch (RuntimeException e) { 715 Log.wtf(TAG, "Unhandled exception in Window Manager", e); 716 } finally { 717 Surface.closeTransaction(); 718 if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i( 719 TAG, "<<< CLOSE TRANSACTION animateLocked"); 720 } 721 722 for (int i = mPendingLayoutChanges.size() - 1; i >= 0; i--) { 723 if ((mPendingLayoutChanges.valueAt(i) 724 & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) { 725 mPendingActions |= WALLPAPER_ACTION_PENDING; 726 } 727 } 728 729 if (mBulkUpdateParams != 0 || mPendingLayoutChanges.size() > 0) { 730 updateAnimToLayoutLocked(); 731 } 732 733 if (mAnimating) { 734 synchronized (mService.mLayoutToAnim) { 735 mService.scheduleAnimationLocked(); 736 } 737 } else if (wasAnimating) { 738 mService.requestTraversalLocked(); 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(mPendingLayoutChanges.get(Display.DEFAULT_DISPLAY))); 745 } 746 } 747 748 WindowState mCurrentFocus; 749 void setCurrentFocus(final WindowState currentFocus) { 750 mCurrentFocus = currentFocus; 751 } 752 753 void setDisplayDimensions(final int curWidth, final int curHeight, 754 final int appWidth, final int appHeight) { 755 mDw = curWidth; 756 mDh = curHeight; 757 mInnerDw = appWidth; 758 mInnerDh = appHeight; 759 } 760 761 boolean isDimmingLocked(int displayId) { 762 return getDisplayContentsAnimatorLocked(displayId).mDimParams != null; 763 } 764 765 boolean isDimmingLocked(final WindowStateAnimator winAnimator) { 766 DimAnimator.Parameters dimParams = 767 getDisplayContentsAnimatorLocked(winAnimator.mWin.getDisplayId()).mDimParams; 768 return dimParams != null && dimParams.mDimWinAnimator == winAnimator; 769 } 770 771 static String bulkUpdateParamsToString(int bulkUpdateParams) { 772 StringBuilder builder = new StringBuilder(128); 773 if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) { 774 builder.append(" UPDATE_ROTATION"); 775 } 776 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) { 777 builder.append(" WALLPAPER_MAY_CHANGE"); 778 } 779 if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) { 780 builder.append(" FORCE_HIDING_CHANGED"); 781 } 782 if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) != 0) { 783 builder.append(" ORIENTATION_CHANGE_COMPLETE"); 784 } 785 if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) { 786 builder.append(" TURN_ON_SCREEN"); 787 } 788 return builder.toString(); 789 } 790 791 public void dumpLocked(PrintWriter pw, String prefix, boolean dumpAll) { 792 final String subPrefix = " " + prefix; 793 final String subSubPrefix = " " + subPrefix; 794 795 boolean needSep = false; 796 if (mAppAnimators.size() > 0) { 797 needSep = true; 798 pw.println(" App Animators:"); 799 for (int i=mAppAnimators.size()-1; i>=0; i--) { 800 AppWindowAnimator anim = mAppAnimators.get(i); 801 pw.print(prefix); pw.print("App Animator #"); pw.print(i); 802 pw.print(' '); pw.print(anim); 803 if (dumpAll) { 804 pw.println(':'); 805 anim.dump(pw, subPrefix, dumpAll); 806 } else { 807 pw.println(); 808 } 809 } 810 } 811 if (mWallpaperTokens.size() > 0) { 812 if (needSep) { 813 pw.println(); 814 } 815 needSep = true; 816 pw.print(prefix); pw.println("Wallpaper tokens:"); 817 for (int i=mWallpaperTokens.size()-1; i>=0; i--) { 818 WindowToken token = mWallpaperTokens.get(i); 819 pw.print(prefix); pw.print("Wallpaper #"); pw.print(i); 820 pw.print(' '); pw.print(token); 821 if (dumpAll) { 822 pw.println(':'); 823 token.dump(pw, subPrefix); 824 } else { 825 pw.println(); 826 } 827 } 828 } 829 830 if (needSep) { 831 pw.println(); 832 } 833 for (int i = 0; i < mDisplayContentsAnimators.size(); i++) { 834 pw.print(prefix); pw.print("DisplayContentsAnimator #"); 835 pw.print(mDisplayContentsAnimators.keyAt(i)); 836 pw.println(":"); 837 DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i); 838 for (int j=0; j<displayAnimator.mWinAnimators.size(); j++) { 839 WindowStateAnimator wanim = displayAnimator.mWinAnimators.get(j); 840 pw.print(subPrefix); pw.print("Window #"); pw.print(j); 841 pw.print(": "); pw.println(wanim); 842 } 843 if (displayAnimator.mWindowAnimationBackgroundSurface != null) { 844 if (dumpAll || displayAnimator.mWindowAnimationBackgroundSurface.mDimShown) { 845 pw.print(subPrefix); pw.println("mWindowAnimationBackgroundSurface:"); 846 displayAnimator.mWindowAnimationBackgroundSurface.printTo(subSubPrefix, pw); 847 } 848 } 849 if (displayAnimator.mDimAnimator != null) { 850 if (dumpAll || displayAnimator.mDimAnimator.mDimShown) { 851 pw.print(subPrefix); pw.println("mDimAnimator:"); 852 displayAnimator.mDimAnimator.printTo(subSubPrefix, pw); 853 } 854 } else if (dumpAll) { 855 pw.print(subPrefix); pw.println("no DimAnimator "); 856 } 857 if (displayAnimator.mDimParams != null) { 858 pw.print(subPrefix); pw.println("mDimParams:"); 859 displayAnimator.mDimParams.printTo(subSubPrefix, pw); 860 } else if (dumpAll) { 861 pw.print(subPrefix); pw.println("no DimParams "); 862 } 863 if (displayAnimator.mScreenRotationAnimation != null) { 864 pw.print(subPrefix); pw.println("mScreenRotationAnimation:"); 865 displayAnimator.mScreenRotationAnimation.printTo(subSubPrefix, pw); 866 } else if (dumpAll) { 867 pw.print(subPrefix); pw.println("no ScreenRotationAnimation "); 868 } 869 } 870 871 pw.println(); 872 873 if (dumpAll) { 874 pw.print(prefix); pw.print("mAnimTransactionSequence="); 875 pw.print(mAnimTransactionSequence); 876 pw.print(" mForceHiding="); pw.println(forceHidingToString()); 877 pw.print(prefix); pw.print("mCurrentTime="); 878 pw.println(TimeUtils.formatUptime(mCurrentTime)); 879 pw.print(prefix); pw.print("mDw="); 880 pw.print(mDw); pw.print(" mDh="); pw.print(mDh); 881 pw.print(" mInnerDw="); pw.print(mInnerDw); 882 pw.print(" mInnerDh="); pw.println(mInnerDh); 883 } 884 if (mBulkUpdateParams != 0) { 885 pw.print(prefix); pw.print("mBulkUpdateParams=0x"); 886 pw.print(Integer.toHexString(mBulkUpdateParams)); 887 pw.println(bulkUpdateParamsToString(mBulkUpdateParams)); 888 } 889 if (mPendingActions != 0) { 890 pw.print(prefix); pw.print("mPendingActions=0x"); 891 pw.println(Integer.toHexString(mPendingActions)); 892 } 893 if (mWindowDetachedWallpaper != null) { 894 pw.print(prefix); pw.print("mWindowDetachedWallpaper="); 895 pw.println(mWindowDetachedWallpaper); 896 } 897 pw.print(prefix); pw.print("mWallpaperTarget="); pw.println(mWallpaperTarget); 898 pw.print(prefix); pw.print("mWpAppAnimator="); pw.println(mWpAppAnimator); 899 if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) { 900 pw.print(prefix); pw.print("mLowerWallpaperTarget="); 901 pw.println(mLowerWallpaperTarget); 902 pw.print(prefix); pw.print("mUpperWallpaperTarget="); 903 pw.println(mUpperWallpaperTarget); 904 } 905 if (mUniverseBackground != null) { 906 pw.print(prefix); pw.print("mUniverseBackground="); pw.print(mUniverseBackground); 907 pw.print(" mAboveUniverseLayer="); pw.println(mAboveUniverseLayer); 908 } 909 } 910 911 void clearPendingActions() { 912 synchronized (this) { 913 mPendingActions = 0; 914 } 915 } 916 917 void setPendingLayoutChanges(final int displayId, final int changes) { 918 mPendingLayoutChanges.put(displayId, mPendingLayoutChanges.get(displayId) | changes); 919 } 920 921 void setAppLayoutChanges(final AppWindowAnimator appAnimator, final int changes, String s) { 922 // Used to track which displays layout changes have been done. 923 SparseIntArray displays = new SparseIntArray(); 924 for (int i = appAnimator.mAllAppWinAnimators.size() - 1; i >= 0; i--) { 925 WindowStateAnimator winAnimator = appAnimator.mAllAppWinAnimators.get(i); 926 final int displayId = winAnimator.mWin.mDisplayContent.getDisplayId(); 927 if (displays.indexOfKey(displayId) < 0) { 928 setPendingLayoutChanges(displayId, changes); 929 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { 930 mService.debugLayoutRepeats(s, mPendingLayoutChanges.get(displayId)); 931 } 932 // Keep from processing this display again. 933 displays.put(displayId, changes); 934 } 935 } 936 } 937 938 private DisplayContentsAnimator getDisplayContentsAnimatorLocked(int displayId) { 939 DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.get(displayId); 940 if (displayAnimator == null) { 941 displayAnimator = new DisplayContentsAnimator(displayId); 942 mDisplayContentsAnimators.put(displayId, displayAnimator); 943 } 944 return displayAnimator; 945 } 946 947 void setScreenRotationAnimationLocked(int displayId, ScreenRotationAnimation animation) { 948 getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation = animation; 949 } 950 951 ScreenRotationAnimation getScreenRotationAnimationLocked(int displayId) { 952 return getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation; 953 } 954 955 private class DisplayContentsAnimator { 956 WinAnimatorList mWinAnimators = new WinAnimatorList(); 957 DimAnimator mDimAnimator = null; 958 DimAnimator.Parameters mDimParams = null; 959 DimSurface mWindowAnimationBackgroundSurface = null; 960 ScreenRotationAnimation mScreenRotationAnimation = null; 961 962 public DisplayContentsAnimator(int displayId) { 963 mDimAnimator = new DimAnimator(mService.mFxSession, displayId); 964 mWindowAnimationBackgroundSurface = 965 new DimSurface(mService.mFxSession, displayId); 966 } 967 } 968} 969