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