1 // Copyright 2012 Google Inc. All Rights Reserved. 2 3 package com.android.server.wm; 4 5 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; 6 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; 7 8 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_UPDATE_ROTATION; 9 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_WALLPAPER_MAY_CHANGE; 10 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_FORCE_HIDING_CHANGED; 11 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE; 12 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_WALLPAPER_ACTION_PENDING; 13 14 import android.content.Context; 15 import android.os.Debug; 16 import android.os.SystemClock; 17 import android.util.Log; 18 import android.util.Slog; 19 import android.util.SparseArray; 20 import android.util.SparseIntArray; 21 import android.util.TimeUtils; 22 import android.view.Display; 23 import android.view.SurfaceControl; 24 import android.view.WindowManagerPolicy; 25 import android.view.animation.Animation; 26 27 import com.android.server.wm.WindowManagerService.LayoutFields; 28 29 import java.io.PrintWriter; 30 import java.util.ArrayList; 31 32 /** 33 * Singleton class that carries out the animations and Surface operations in a separate task 34 * on behalf of WindowManagerService. 35 */ 36 public class WindowAnimator { 37 private static final String TAG = "WindowAnimator"; 38 39 final WindowManagerService mService; 40 final Context mContext; 41 final WindowManagerPolicy mPolicy; 42 43 boolean mAnimating; 44 45 final Runnable mAnimationRunnable; 46 47 /** Time of current animation step. Reset on each iteration */ 48 long mCurrentTime; 49 50 /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this 51 * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */ 52 private int mAnimTransactionSequence; 53 54 /** Window currently running an animation that has requested it be detached 55 * from the wallpaper. This means we need to ensure the wallpaper is 56 * visible behind it in case it animates in a way that would allow it to be 57 * seen. If multiple windows satisfy this, use the lowest window. */ 58 WindowState mWindowDetachedWallpaper = null; 59 60 WindowStateAnimator mUniverseBackground = null; 61 int mAboveUniverseLayer = 0; 62 63 int mBulkUpdateParams = 0; 64 Object mLastWindowFreezeSource; 65 66 SparseArray<DisplayContentsAnimator> mDisplayContentsAnimators = 67 new SparseArray<WindowAnimator.DisplayContentsAnimator>(2); 68 69 boolean mInitialized = false; 70 71 // forceHiding states. 72 static final int KEYGUARD_NOT_SHOWN = 0; 73 static final int KEYGUARD_ANIMATING_IN = 1; 74 static final int KEYGUARD_SHOWN = 2; 75 static final int KEYGUARD_ANIMATING_OUT = 3; 76 int mForceHiding = KEYGUARD_NOT_SHOWN; 77 78 private String forceHidingToString() { 79 switch (mForceHiding) { 80 case KEYGUARD_NOT_SHOWN: return "KEYGUARD_NOT_SHOWN"; 81 case KEYGUARD_ANIMATING_IN: return "KEYGUARD_ANIMATING_IN"; 82 case KEYGUARD_SHOWN: return "KEYGUARD_SHOWN"; 83 case KEYGUARD_ANIMATING_OUT:return "KEYGUARD_ANIMATING_OUT"; 84 default: return "KEYGUARD STATE UNKNOWN " + mForceHiding; 85 } 86 } 87 88 WindowAnimator(final WindowManagerService service) { 89 mService = service; 90 mContext = service.mContext; 91 mPolicy = service.mPolicy; 92 93 mAnimationRunnable = new Runnable() { 94 @Override 95 public void run() { 96 synchronized (mService.mWindowMap) { 97 mService.mAnimationScheduled = false; 98 animateLocked(); 99 } 100 } 101 }; 102 } 103 104 void addDisplayLocked(final int displayId) { 105 // Create the DisplayContentsAnimator object by retrieving it. 106 getDisplayContentsAnimatorLocked(displayId); 107 if (displayId == Display.DEFAULT_DISPLAY) { 108 mInitialized = true; 109 } 110 } 111 112 void removeDisplayLocked(final int displayId) { 113 final DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.get(displayId); 114 if (displayAnimator != null) { 115 if (displayAnimator.mScreenRotationAnimation != null) { 116 displayAnimator.mScreenRotationAnimation.kill(); 117 displayAnimator.mScreenRotationAnimation = null; 118 } 119 } 120 121 mDisplayContentsAnimators.delete(displayId); 122 } 123 124 AppWindowAnimator getWallpaperAppAnimator() { 125 return mService.mWallpaperTarget == null 126 ? null : mService.mWallpaperTarget.mAppToken == null 127 ? null : mService.mWallpaperTarget.mAppToken.mAppAnimator; 128 } 129 130 void hideWallpapersLocked(final WindowState w) { 131 final WindowState wallpaperTarget = mService.mWallpaperTarget; 132 final WindowState lowerWallpaperTarget = mService.mLowerWallpaperTarget; 133 final ArrayList<WindowToken> wallpaperTokens = mService.mWallpaperTokens; 134 135 if ((wallpaperTarget == w && lowerWallpaperTarget == null) || wallpaperTarget == null) { 136 final int numTokens = wallpaperTokens.size(); 137 for (int i = numTokens - 1; i >= 0; i--) { 138 final WindowToken token = wallpaperTokens.get(i); 139 final int numWindows = token.windows.size(); 140 for (int j = numWindows - 1; j >= 0; j--) { 141 final WindowState wallpaper = token.windows.get(j); 142 final WindowStateAnimator winAnimator = wallpaper.mWinAnimator; 143 if (!winAnimator.mLastHidden) { 144 winAnimator.hide(); 145 mService.dispatchWallpaperVisibility(wallpaper, false); 146 setPendingLayoutChanges(Display.DEFAULT_DISPLAY, 147 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER); 148 } 149 } 150 if (WindowManagerService.DEBUG_WALLPAPER_LIGHT && !token.hidden) Slog.d(TAG, 151 "Hiding wallpaper " + token + " from " + w 152 + " target=" + wallpaperTarget + " lower=" + lowerWallpaperTarget 153 + "\n" + Debug.getCallers(5, " ")); 154 token.hidden = true; 155 } 156 } 157 } 158 159 private void updateAppWindowsLocked(int displayId) { 160 final DisplayContent displayContent = mService.getDisplayContentLocked(displayId); 161 final ArrayList<Task> tasks = displayContent.getTasks(); 162 final int numTasks = tasks.size(); 163 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 164 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 165 final int numTokens = tokens.size(); 166 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 167 final AppWindowAnimator appAnimator = tokens.get(tokenNdx).mAppAnimator; 168 final boolean wasAnimating = appAnimator.animation != null 169 && appAnimator.animation != AppWindowAnimator.sDummyAnimation; 170 if (appAnimator.stepAnimationLocked(mCurrentTime)) { 171 mAnimating = true; 172 } else if (wasAnimating) { 173 // stopped animating, do one more pass through the layout 174 setAppLayoutChanges(appAnimator, WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER, 175 "appToken " + appAnimator.mAppToken + " done"); 176 if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG, 177 "updateWindowsApps...: done animating " + appAnimator.mAppToken); 178 } 179 } 180 } 181 182 final AppTokenList exitingAppTokens = displayContent.mExitingAppTokens; 183 final int NEAT = exitingAppTokens.size(); 184 for (int i = 0; i < NEAT; i++) { 185 final AppWindowAnimator appAnimator = exitingAppTokens.get(i).mAppAnimator; 186 final boolean wasAnimating = appAnimator.animation != null 187 && appAnimator.animation != AppWindowAnimator.sDummyAnimation; 188 if (appAnimator.stepAnimationLocked(mCurrentTime)) { 189 mAnimating = true; 190 } else if (wasAnimating) { 191 // stopped animating, do one more pass through the layout 192 setAppLayoutChanges(appAnimator, WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER, 193 "exiting appToken " + appAnimator.mAppToken + " done"); 194 if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG, 195 "updateWindowsApps...: done animating exiting " + appAnimator.mAppToken); 196 } 197 } 198 } 199 200 private void updateWindowsLocked(final int displayId) { 201 ++mAnimTransactionSequence; 202 203 final WindowList windows = mService.getWindowListLocked(displayId); 204 ArrayList<WindowStateAnimator> unForceHiding = null; 205 boolean wallpaperInUnForceHiding = false; 206 mForceHiding = KEYGUARD_NOT_SHOWN; 207 208 for (int i = windows.size() - 1; i >= 0; i--) { 209 WindowState win = windows.get(i); 210 WindowStateAnimator winAnimator = win.mWinAnimator; 211 final int flags = winAnimator.mAttrFlags; 212 213 if (winAnimator.mSurfaceControl != null) { 214 final boolean wasAnimating = winAnimator.mWasAnimating; 215 final boolean nowAnimating = winAnimator.stepAnimationLocked(mCurrentTime); 216 217 if (WindowManagerService.DEBUG_WALLPAPER) { 218 Slog.v(TAG, win + ": wasAnimating=" + wasAnimating + 219 ", nowAnimating=" + nowAnimating); 220 } 221 222 if (wasAnimating && !winAnimator.mAnimating && mService.mWallpaperTarget == win) { 223 mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE; 224 setPendingLayoutChanges(Display.DEFAULT_DISPLAY, 225 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER); 226 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { 227 mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 2", 228 getPendingLayoutChanges(Display.DEFAULT_DISPLAY)); 229 } 230 } 231 232 if (mPolicy.doesForceHide(win, win.mAttrs)) { 233 if (!wasAnimating && nowAnimating) { 234 if (WindowManagerService.DEBUG_ANIM || 235 WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG, 236 "Animation started that could impact force hide: " + win); 237 mBulkUpdateParams |= SET_FORCE_HIDING_CHANGED; 238 setPendingLayoutChanges(displayId, 239 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER); 240 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { 241 mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 3", 242 getPendingLayoutChanges(displayId)); 243 } 244 mService.mFocusMayChange = true; 245 } 246 if (win.isReadyForDisplay()) { 247 if (nowAnimating) { 248 if (winAnimator.mAnimationIsEntrance) { 249 mForceHiding = KEYGUARD_ANIMATING_IN; 250 } else { 251 mForceHiding = KEYGUARD_ANIMATING_OUT; 252 } 253 } else { 254 mForceHiding = KEYGUARD_SHOWN; 255 } 256 } 257 if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG, 258 "Force hide " + mForceHiding 259 + " hasSurface=" + win.mHasSurface 260 + " policyVis=" + win.mPolicyVisibility 261 + " destroying=" + win.mDestroying 262 + " attHidden=" + win.mAttachedHidden 263 + " vis=" + win.mViewVisibility 264 + " hidden=" + win.mRootToken.hidden 265 + " anim=" + win.mWinAnimator.mAnimation); 266 } else if (mPolicy.canBeForceHidden(win, win.mAttrs)) { 267 final boolean hideWhenLocked = 268 (winAnimator.mAttrFlags & FLAG_SHOW_WHEN_LOCKED) == 0; 269 final boolean changed; 270 if (((mForceHiding == KEYGUARD_ANIMATING_IN) 271 && (!winAnimator.isAnimating() || hideWhenLocked)) 272 || ((mForceHiding == KEYGUARD_SHOWN) && hideWhenLocked)) { 273 changed = win.hideLw(false, false); 274 if (WindowManagerService.DEBUG_VISIBILITY && changed) Slog.v(TAG, 275 "Now policy hidden: " + win); 276 } else { 277 changed = win.showLw(false, false); 278 if (WindowManagerService.DEBUG_VISIBILITY && changed) Slog.v(TAG, 279 "Now policy shown: " + win); 280 if (changed) { 281 if ((mBulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0 282 && win.isVisibleNow() /*w.isReadyForDisplay()*/) { 283 if (unForceHiding == null) { 284 unForceHiding = new ArrayList<WindowStateAnimator>(); 285 } 286 unForceHiding.add(winAnimator); 287 if ((flags & FLAG_SHOW_WALLPAPER) != 0) { 288 wallpaperInUnForceHiding = true; 289 } 290 } 291 final WindowState currentFocus = mService.mCurrentFocus; 292 if (currentFocus == null || currentFocus.mLayer < win.mLayer) { 293 // We are showing on to of the current 294 // focus, so re-evaluate focus to make 295 // sure it is correct. 296 if (WindowManagerService.DEBUG_FOCUS_LIGHT) Slog.v(TAG, 297 "updateWindowsLocked: setting mFocusMayChange true"); 298 mService.mFocusMayChange = true; 299 } 300 } 301 } 302 if (changed && (flags & FLAG_SHOW_WALLPAPER) != 0) { 303 mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE; 304 setPendingLayoutChanges(Display.DEFAULT_DISPLAY, 305 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER); 306 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { 307 mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 4", 308 getPendingLayoutChanges(Display.DEFAULT_DISPLAY)); 309 } 310 } 311 } 312 } 313 314 final AppWindowToken atoken = win.mAppToken; 315 if (winAnimator.mDrawState == WindowStateAnimator.READY_TO_SHOW) { 316 if (atoken == null || atoken.allDrawn) { 317 if (winAnimator.performShowLocked()) { 318 setPendingLayoutChanges(displayId, 319 WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM); 320 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { 321 mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 5", 322 getPendingLayoutChanges(displayId)); 323 } 324 } 325 } 326 } 327 final AppWindowAnimator appAnimator = winAnimator.mAppAnimator; 328 if (appAnimator != null && appAnimator.thumbnail != null) { 329 if (appAnimator.thumbnailTransactionSeq != mAnimTransactionSequence) { 330 appAnimator.thumbnailTransactionSeq = mAnimTransactionSequence; 331 appAnimator.thumbnailLayer = 0; 332 } 333 if (appAnimator.thumbnailLayer < winAnimator.mAnimLayer) { 334 appAnimator.thumbnailLayer = winAnimator.mAnimLayer; 335 } 336 } 337 } // end forall windows 338 339 // If we have windows that are being show due to them no longer 340 // being force-hidden, apply the appropriate animation to them. 341 if (unForceHiding != null) { 342 for (int i=unForceHiding.size()-1; i>=0; i--) { 343 Animation a = mPolicy.createForceHideEnterAnimation(wallpaperInUnForceHiding); 344 if (a != null) { 345 final WindowStateAnimator winAnimator = unForceHiding.get(i); 346 winAnimator.setAnimation(a); 347 winAnimator.mAnimationIsEntrance = true; 348 } 349 } 350 } 351 } 352 353 private void updateWallpaperLocked(int displayId) { 354 mService.getDisplayContentLocked(displayId).resetAnimationBackgroundAnimator(); 355 356 final WindowList windows = mService.getWindowListLocked(displayId); 357 WindowState detachedWallpaper = null; 358 359 for (int i = windows.size() - 1; i >= 0; i--) { 360 final WindowState win = windows.get(i); 361 WindowStateAnimator winAnimator = win.mWinAnimator; 362 if (winAnimator.mSurfaceControl == null) { 363 continue; 364 } 365 366 final int flags = winAnimator.mAttrFlags; 367 368 // If this window is animating, make a note that we have 369 // an animating window and take care of a request to run 370 // a detached wallpaper animation. 371 if (winAnimator.mAnimating) { 372 if (winAnimator.mAnimation != null) { 373 if ((flags & FLAG_SHOW_WALLPAPER) != 0 374 && winAnimator.mAnimation.getDetachWallpaper()) { 375 detachedWallpaper = win; 376 } 377 final int color = winAnimator.mAnimation.getBackgroundColor(); 378 if (color != 0) { 379 win.getStack().setAnimationBackground(winAnimator, color); 380 } 381 } 382 mAnimating = true; 383 } 384 385 // If this window's app token is running a detached wallpaper 386 // animation, make a note so we can ensure the wallpaper is 387 // displayed behind it. 388 final AppWindowAnimator appAnimator = winAnimator.mAppAnimator; 389 if (appAnimator != null && appAnimator.animation != null 390 && appAnimator.animating) { 391 if ((flags & FLAG_SHOW_WALLPAPER) != 0 392 && appAnimator.animation.getDetachWallpaper()) { 393 detachedWallpaper = win; 394 } 395 396 final int color = appAnimator.animation.getBackgroundColor(); 397 if (color != 0) { 398 win.getStack().setAnimationBackground(winAnimator, color); 399 } 400 } 401 } // end forall windows 402 403 if (mWindowDetachedWallpaper != detachedWallpaper) { 404 if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG, 405 "Detached wallpaper changed from " + mWindowDetachedWallpaper 406 + " to " + detachedWallpaper); 407 mWindowDetachedWallpaper = detachedWallpaper; 408 mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE; 409 } 410 } 411 412 /** See if any windows have been drawn, so they (and others associated with them) can now be 413 * shown. */ 414 private void testTokenMayBeDrawnLocked(int displayId) { 415 // See if any windows have been drawn, so they (and others 416 // associated with them) can now be shown. 417 final ArrayList<Task> tasks = mService.getDisplayContentLocked(displayId).getTasks(); 418 final int numTasks = tasks.size(); 419 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 420 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 421 final int numTokens = tokens.size(); 422 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 423 final AppWindowToken wtoken = tokens.get(tokenNdx); 424 AppWindowAnimator appAnimator = wtoken.mAppAnimator; 425 final boolean allDrawn = wtoken.allDrawn; 426 if (allDrawn != appAnimator.allDrawn) { 427 appAnimator.allDrawn = allDrawn; 428 if (allDrawn) { 429 // The token has now changed state to having all 430 // windows shown... what to do, what to do? 431 if (appAnimator.freezingScreen) { 432 appAnimator.showAllWindowsLocked(); 433 mService.unsetAppFreezingScreenLocked(wtoken, false, true); 434 if (WindowManagerService.DEBUG_ORIENTATION) Slog.i(TAG, 435 "Setting mOrientationChangeComplete=true because wtoken " 436 + wtoken + " numInteresting=" + wtoken.numInterestingWindows 437 + " numDrawn=" + wtoken.numDrawnWindows); 438 // This will set mOrientationChangeComplete and cause a pass through layout. 439 setAppLayoutChanges(appAnimator, 440 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER, 441 "testTokenMayBeDrawnLocked: freezingScreen"); 442 } else { 443 setAppLayoutChanges(appAnimator, 444 WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM, 445 "testTokenMayBeDrawnLocked"); 446 447 // We can now show all of the drawn windows! 448 if (!mService.mOpeningApps.contains(wtoken)) { 449 mAnimating |= appAnimator.showAllWindowsLocked(); 450 } 451 } 452 } 453 } 454 } 455 } 456 } 457 458 private void performAnimationsLocked(final int displayId) { 459 updateWindowsLocked(displayId); 460 updateWallpaperLocked(displayId); 461 } 462 463 464 /** Locked on mService.mWindowMap. */ 465 private void animateLocked() { 466 if (!mInitialized) { 467 return; 468 } 469 470 mCurrentTime = SystemClock.uptimeMillis(); 471 mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE; 472 boolean wasAnimating = mAnimating; 473 mAnimating = false; 474 if (WindowManagerService.DEBUG_WINDOW_TRACE) { 475 Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime); 476 } 477 478 if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i( 479 TAG, ">>> OPEN TRANSACTION animateLocked"); 480 SurfaceControl.openTransaction(); 481 SurfaceControl.setAnimationTransaction(); 482 try { 483 final int numDisplays = mDisplayContentsAnimators.size(); 484 for (int i = 0; i < numDisplays; i++) { 485 final int displayId = mDisplayContentsAnimators.keyAt(i); 486 updateAppWindowsLocked(displayId); 487 DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i); 488 489 final ScreenRotationAnimation screenRotationAnimation = 490 displayAnimator.mScreenRotationAnimation; 491 if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) { 492 if (screenRotationAnimation.stepAnimationLocked(mCurrentTime)) { 493 mAnimating = true; 494 } else { 495 mBulkUpdateParams |= SET_UPDATE_ROTATION; 496 screenRotationAnimation.kill(); 497 displayAnimator.mScreenRotationAnimation = null; 498 } 499 } 500 501 // Update animations of all applications, including those 502 // associated with exiting/removed apps 503 performAnimationsLocked(displayId); 504 505 final WindowList windows = mService.getWindowListLocked(displayId); 506 final int N = windows.size(); 507 for (int j = 0; j < N; j++) { 508 windows.get(j).mWinAnimator.prepareSurfaceLocked(true); 509 } 510 } 511 512 for (int i = 0; i < numDisplays; i++) { 513 final int displayId = mDisplayContentsAnimators.keyAt(i); 514 515 testTokenMayBeDrawnLocked(displayId); 516 517 final ScreenRotationAnimation screenRotationAnimation = 518 mDisplayContentsAnimators.valueAt(i).mScreenRotationAnimation; 519 if (screenRotationAnimation != null) { 520 screenRotationAnimation.updateSurfacesInTransaction(); 521 } 522 523 mAnimating |= mService.getDisplayContentLocked(displayId).animateDimLayers(); 524 525 //TODO (multidisplay): Magnification is supported only for the default display. 526 if (mService.mDisplayMagnifier != null && displayId == Display.DEFAULT_DISPLAY) { 527 mService.mDisplayMagnifier.drawMagnifiedRegionBorderIfNeededLocked(); 528 } 529 } 530 531 if (mAnimating) { 532 mService.scheduleAnimationLocked(); 533 } 534 535 mService.setFocusedStackLayer(); 536 537 if (mService.mWatermark != null) { 538 mService.mWatermark.drawIfNeeded(); 539 } 540 } catch (RuntimeException e) { 541 Log.wtf(TAG, "Unhandled exception in Window Manager", e); 542 } finally { 543 SurfaceControl.closeTransaction(); 544 if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i( 545 TAG, "<<< CLOSE TRANSACTION animateLocked"); 546 } 547 548 boolean hasPendingLayoutChanges = false; 549 final int numDisplays = mService.mDisplayContents.size(); 550 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 551 final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx); 552 final int pendingChanges = getPendingLayoutChanges(displayContent.getDisplayId()); 553 if ((pendingChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) { 554 mBulkUpdateParams |= SET_WALLPAPER_ACTION_PENDING; 555 } 556 if (pendingChanges != 0) { 557 hasPendingLayoutChanges = true; 558 } 559 } 560 561 boolean doRequest = false; 562 if (mBulkUpdateParams != 0) { 563 doRequest = mService.copyAnimToLayoutParamsLocked(); 564 } 565 566 if (hasPendingLayoutChanges || doRequest) { 567 mService.requestTraversalLocked(); 568 } 569 570 if (!mAnimating && wasAnimating) { 571 mService.requestTraversalLocked(); 572 } 573 if (WindowManagerService.DEBUG_WINDOW_TRACE) { 574 Slog.i(TAG, "!!! animate: exit mAnimating=" + mAnimating 575 + " mBulkUpdateParams=" + Integer.toHexString(mBulkUpdateParams) 576 + " mPendingLayoutChanges(DEFAULT_DISPLAY)=" 577 + Integer.toHexString(getPendingLayoutChanges(Display.DEFAULT_DISPLAY))); 578 } 579 } 580 581 static String bulkUpdateParamsToString(int bulkUpdateParams) { 582 StringBuilder builder = new StringBuilder(128); 583 if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) { 584 builder.append(" UPDATE_ROTATION"); 585 } 586 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) { 587 builder.append(" WALLPAPER_MAY_CHANGE"); 588 } 589 if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) { 590 builder.append(" FORCE_HIDING_CHANGED"); 591 } 592 if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) != 0) { 593 builder.append(" ORIENTATION_CHANGE_COMPLETE"); 594 } 595 if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) { 596 builder.append(" TURN_ON_SCREEN"); 597 } 598 return builder.toString(); 599 } 600 601 public void dumpLocked(PrintWriter pw, String prefix, boolean dumpAll) { 602 final String subPrefix = " " + prefix; 603 final String subSubPrefix = " " + subPrefix; 604 605 for (int i = 0; i < mDisplayContentsAnimators.size(); i++) { 606 pw.print(prefix); pw.print("DisplayContentsAnimator #"); 607 pw.print(mDisplayContentsAnimators.keyAt(i)); 608 pw.println(":"); 609 DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i); 610 final WindowList windows = 611 mService.getWindowListLocked(mDisplayContentsAnimators.keyAt(i)); 612 final int N = windows.size(); 613 for (int j = 0; j < N; j++) { 614 WindowStateAnimator wanim = windows.get(j).mWinAnimator; 615 pw.print(subPrefix); pw.print("Window #"); pw.print(j); 616 pw.print(": "); pw.println(wanim); 617 } 618 if (displayAnimator.mScreenRotationAnimation != null) { 619 pw.print(subPrefix); pw.println("mScreenRotationAnimation:"); 620 displayAnimator.mScreenRotationAnimation.printTo(subSubPrefix, pw); 621 } else if (dumpAll) { 622 pw.print(subPrefix); pw.println("no ScreenRotationAnimation "); 623 } 624 } 625 626 pw.println(); 627 628 if (dumpAll) { 629 pw.print(prefix); pw.print("mAnimTransactionSequence="); 630 pw.print(mAnimTransactionSequence); 631 pw.print(" mForceHiding="); pw.println(forceHidingToString()); 632 pw.print(prefix); pw.print("mCurrentTime="); 633 pw.println(TimeUtils.formatUptime(mCurrentTime)); 634 } 635 if (mBulkUpdateParams != 0) { 636 pw.print(prefix); pw.print("mBulkUpdateParams=0x"); 637 pw.print(Integer.toHexString(mBulkUpdateParams)); 638 pw.println(bulkUpdateParamsToString(mBulkUpdateParams)); 639 } 640 if (mWindowDetachedWallpaper != null) { 641 pw.print(prefix); pw.print("mWindowDetachedWallpaper="); 642 pw.println(mWindowDetachedWallpaper); 643 } 644 if (mUniverseBackground != null) { 645 pw.print(prefix); pw.print("mUniverseBackground="); pw.print(mUniverseBackground); 646 pw.print(" mAboveUniverseLayer="); pw.println(mAboveUniverseLayer); 647 } 648 } 649 650 int getPendingLayoutChanges(final int displayId) { 651 return mService.getDisplayContentLocked(displayId).pendingLayoutChanges; 652 } 653 654 void setPendingLayoutChanges(final int displayId, final int changes) { 655 mService.getDisplayContentLocked(displayId).pendingLayoutChanges |= changes; 656 } 657 658 void setAppLayoutChanges(final AppWindowAnimator appAnimator, final int changes, String s) { 659 // Used to track which displays layout changes have been done. 660 SparseIntArray displays = new SparseIntArray(2); 661 WindowList windows = appAnimator.mAppToken.allAppWindows; 662 for (int i = windows.size() - 1; i >= 0; i--) { 663 final int displayId = windows.get(i).getDisplayId(); 664 if (displays.indexOfKey(displayId) < 0) { 665 setPendingLayoutChanges(displayId, changes); 666 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { 667 mService.debugLayoutRepeats(s, getPendingLayoutChanges(displayId)); 668 } 669 // Keep from processing this display again. 670 displays.put(displayId, changes); 671 } 672 } 673 } 674 675 private DisplayContentsAnimator getDisplayContentsAnimatorLocked(int displayId) { 676 DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.get(displayId); 677 if (displayAnimator == null) { 678 displayAnimator = new DisplayContentsAnimator(); 679 mDisplayContentsAnimators.put(displayId, displayAnimator); 680 } 681 return displayAnimator; 682 } 683 684 void setScreenRotationAnimationLocked(int displayId, ScreenRotationAnimation animation) { 685 getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation = animation; 686 } 687 688 ScreenRotationAnimation getScreenRotationAnimationLocked(int displayId) { 689 return getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation; 690 } 691 692 private class DisplayContentsAnimator { 693 ScreenRotationAnimation mScreenRotationAnimation = null; 694 } 695 } 696