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