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