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