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