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