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