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