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 17 package com.android.server.wm; 18 19 import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; 20 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY; 21 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; 22 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; 23 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; 24 import static android.view.WindowManager.TRANSIT_OLD_NONE; 25 26 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ANIM; 27 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_DRAW; 28 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION; 29 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW; 30 import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC; 31 import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS; 32 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; 33 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 34 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION; 35 import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS; 36 import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; 37 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG; 38 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS; 39 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE; 40 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; 41 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS; 42 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; 43 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 44 import static com.android.server.wm.WindowManagerService.logWithStack; 45 import static com.android.server.wm.WindowStateAnimatorProto.DRAW_STATE; 46 import static com.android.server.wm.WindowStateAnimatorProto.SURFACE; 47 import static com.android.server.wm.WindowStateAnimatorProto.SYSTEM_DECOR_RECT; 48 49 import android.content.Context; 50 import android.graphics.PixelFormat; 51 import android.graphics.Rect; 52 import android.os.Debug; 53 import android.os.Trace; 54 import android.util.Slog; 55 import android.util.proto.ProtoOutputStream; 56 import android.view.Surface.OutOfResourcesException; 57 import android.view.SurfaceControl; 58 import android.view.WindowManager; 59 import android.view.WindowManager.LayoutParams; 60 import android.view.animation.Animation; 61 import android.view.animation.AnimationUtils; 62 63 import com.android.internal.protolog.ProtoLogImpl; 64 import com.android.internal.protolog.common.ProtoLog; 65 import com.android.server.policy.WindowManagerPolicy; 66 67 import java.io.PrintWriter; 68 69 /** 70 * Keep track of animations and surface operations for a single WindowState. 71 **/ 72 class WindowStateAnimator { 73 static final String TAG = TAG_WITH_CLASS_NAME ? "WindowStateAnimator" : TAG_WM; 74 static final int PRESERVED_SURFACE_LAYER = 1; 75 76 /** 77 * Mode how the window gets clipped by the root task bounds during an animation: The clipping 78 * should be applied after applying the animation transformation, i.e. the root task bounds 79 * don't move during the animation. 80 */ 81 static final int ROOT_TASK_CLIP_AFTER_ANIM = 0; 82 83 /** 84 * Mode how window gets clipped by the root task bounds during an animation: Don't clip the 85 * window by the root task bounds. 86 */ 87 static final int ROOT_TASK_CLIP_NONE = 1; 88 89 // Unchanging local convenience fields. 90 final WindowManagerService mService; 91 final WindowState mWin; 92 final WindowAnimator mAnimator; 93 final Session mSession; 94 final WindowManagerPolicy mPolicy; 95 final Context mContext; 96 final boolean mIsWallpaper; 97 private final WallpaperController mWallpaperControllerLocked; 98 99 boolean mAnimationIsEntrance; 100 101 WindowSurfaceController mSurfaceController; 102 103 float mShownAlpha = 0; 104 float mAlpha = 0; 105 float mLastAlpha = 0; 106 107 /** 108 * This is rectangle of the window's surface that is not covered by 109 * system decorations. 110 */ 111 private final Rect mSystemDecorRect = new Rect(); 112 113 // Set to true if, when the window gets displayed, it should perform 114 // an enter animation. 115 boolean mEnterAnimationPending; 116 117 /** Used to indicate that this window is undergoing an enter animation. Used for system 118 * windows to make the callback to View.dispatchOnWindowShownCallback(). Set when the 119 * window is first added or shown, cleared when the callback has been made. */ 120 boolean mEnteringAnimation; 121 122 /** This is set when there is no Surface */ 123 static final int NO_SURFACE = 0; 124 /** This is set after the Surface has been created but before the window has been drawn. During 125 * this time the surface is hidden. */ 126 static final int DRAW_PENDING = 1; 127 /** This is set after the window has finished drawing for the first time but before its surface 128 * is shown. The surface will be displayed when the next layout is run. */ 129 static final int COMMIT_DRAW_PENDING = 2; 130 /** This is set during the time after the window's drawing has been committed, and before its 131 * surface is actually shown. It is used to delay showing the surface until all windows in a 132 * token are ready to be shown. */ 133 static final int READY_TO_SHOW = 3; 134 /** Set when the window has been shown in the screen the first time. */ 135 static final int HAS_DRAWN = 4; 136 drawStateToString()137 String drawStateToString() { 138 switch (mDrawState) { 139 case NO_SURFACE: return "NO_SURFACE"; 140 case DRAW_PENDING: return "DRAW_PENDING"; 141 case COMMIT_DRAW_PENDING: return "COMMIT_DRAW_PENDING"; 142 case READY_TO_SHOW: return "READY_TO_SHOW"; 143 case HAS_DRAWN: return "HAS_DRAWN"; 144 default: return Integer.toString(mDrawState); 145 } 146 } 147 int mDrawState; 148 149 /** Was this window last hidden? */ 150 boolean mLastHidden; 151 152 int mAttrType; 153 WindowStateAnimator(final WindowState win)154 WindowStateAnimator(final WindowState win) { 155 final WindowManagerService service = win.mWmService; 156 157 mService = service; 158 mAnimator = service.mAnimator; 159 mPolicy = service.mPolicy; 160 mContext = service.mContext; 161 162 mWin = win; 163 mSession = win.mSession; 164 mAttrType = win.mAttrs.type; 165 mIsWallpaper = win.mIsWallpaper; 166 mWallpaperControllerLocked = win.getDisplayContent().mWallpaperController; 167 } 168 onAnimationFinished()169 void onAnimationFinished() { 170 // Done animating, clean up. 171 ProtoLog.v(WM_DEBUG_ANIM, "Animation done in %s: exiting=%b, reportedVisible=%b", 172 this, mWin.mAnimatingExit, 173 (mWin.mActivityRecord != null && mWin.mActivityRecord.reportedVisible)); 174 175 mWin.checkPolicyVisibilityChange(); 176 final DisplayContent displayContent = mWin.getDisplayContent(); 177 if ((mAttrType == LayoutParams.TYPE_STATUS_BAR 178 || mAttrType == LayoutParams.TYPE_NOTIFICATION_SHADE) && mWin.isVisibleByPolicy()) { 179 // Upon completion of a not-visible to visible status bar animation a relayout is 180 // required. 181 displayContent.setLayoutNeeded(); 182 } 183 mWin.onExitAnimationDone(); 184 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM; 185 if (displayContent.mWallpaperController.isWallpaperTarget(mWin)) { 186 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 187 } 188 if (DEBUG_LAYOUT_REPEATS) { 189 mService.mWindowPlacerLocked.debugLayoutRepeats( 190 "WindowStateAnimator", displayContent.pendingLayoutChanges); 191 } 192 193 if (mWin.mActivityRecord != null) { 194 mWin.mActivityRecord.updateReportedVisibilityLocked(); 195 } 196 } 197 hide(SurfaceControl.Transaction transaction, String reason)198 void hide(SurfaceControl.Transaction transaction, String reason) { 199 if (!mLastHidden) { 200 //dump(); 201 mLastHidden = true; 202 203 if (mSurfaceController != null) { 204 mSurfaceController.hide(transaction, reason); 205 } 206 } 207 } 208 finishDrawingLocked(SurfaceControl.Transaction postDrawTransaction)209 boolean finishDrawingLocked(SurfaceControl.Transaction postDrawTransaction) { 210 final boolean startingWindow = 211 mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; 212 if (startingWindow) { 213 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Finishing drawing window %s: mDrawState=%s", 214 mWin, drawStateToString()); 215 } 216 217 boolean layoutNeeded = false; 218 219 if (mDrawState == DRAW_PENDING) { 220 ProtoLog.v(WM_DEBUG_DRAW, 221 "finishDrawingLocked: mDrawState=COMMIT_DRAW_PENDING %s in %s", mWin, 222 mSurfaceController); 223 if (startingWindow) { 224 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Draw state now committed in %s", mWin); 225 } 226 mDrawState = COMMIT_DRAW_PENDING; 227 layoutNeeded = true; 228 } 229 230 if (postDrawTransaction != null) { 231 mWin.getSyncTransaction().merge(postDrawTransaction); 232 layoutNeeded = true; 233 } 234 235 return layoutNeeded; 236 } 237 238 // This must be called while inside a transaction. commitFinishDrawingLocked()239 boolean commitFinishDrawingLocked() { 240 if (DEBUG_STARTING_WINDOW_VERBOSE && 241 mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) { 242 Slog.i(TAG, "commitFinishDrawingLocked: " + mWin + " cur mDrawState=" 243 + drawStateToString()); 244 } 245 if (mDrawState != COMMIT_DRAW_PENDING && mDrawState != READY_TO_SHOW) { 246 return false; 247 } 248 ProtoLog.i(WM_DEBUG_ANIM, "commitFinishDrawingLocked: mDrawState=READY_TO_SHOW %s", 249 mSurfaceController); 250 mDrawState = READY_TO_SHOW; 251 boolean result = false; 252 final ActivityRecord activity = mWin.mActivityRecord; 253 if (activity == null || activity.canShowWindows() 254 || mWin.mAttrs.type == TYPE_APPLICATION_STARTING) { 255 result = mWin.performShowLocked(); 256 } 257 return result; 258 } 259 resetDrawState()260 void resetDrawState() { 261 mDrawState = DRAW_PENDING; 262 263 if (mWin.mActivityRecord == null) { 264 return; 265 } 266 267 if (!mWin.mActivityRecord.isAnimating(TRANSITION)) { 268 mWin.mActivityRecord.clearAllDrawn(); 269 } 270 } 271 createSurfaceLocked()272 WindowSurfaceController createSurfaceLocked() { 273 final WindowState w = mWin; 274 275 if (mSurfaceController != null) { 276 return mSurfaceController; 277 } 278 279 w.setHasSurface(false); 280 281 ProtoLog.i(WM_DEBUG_ANIM, "createSurface %s: mDrawState=DRAW_PENDING", this); 282 283 resetDrawState(); 284 285 mService.makeWindowFreezingScreenIfNeededLocked(w); 286 287 int flags = SurfaceControl.HIDDEN; 288 final WindowManager.LayoutParams attrs = w.mAttrs; 289 290 if (w.isSecureLocked()) { 291 flags |= SurfaceControl.SECURE; 292 } 293 294 if ((mWin.mAttrs.privateFlags & PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY) != 0) { 295 flags |= SurfaceControl.SKIP_SCREENSHOT; 296 } 297 298 if (DEBUG_VISIBILITY) { 299 Slog.v(TAG, "Creating surface in session " 300 + mSession.mSurfaceSession + " window " + this 301 + " format=" + attrs.format + " flags=" + flags); 302 } 303 304 // Set up surface control with initial size. 305 try { 306 307 // This can be removed once we move all Buffer Layers to use BLAST. 308 final boolean isHwAccelerated = (attrs.flags & FLAG_HARDWARE_ACCELERATED) != 0; 309 final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format; 310 311 mSurfaceController = new WindowSurfaceController(attrs.getTitle().toString(), format, 312 flags, this, attrs.type); 313 mSurfaceController.setColorSpaceAgnostic((attrs.privateFlags 314 & WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC) != 0); 315 316 w.setHasSurface(true); 317 // The surface instance is changed. Make sure the input info can be applied to the 318 // new surface, e.g. relaunch activity. 319 w.mInputWindowHandle.forceChange(); 320 321 ProtoLog.i(WM_SHOW_SURFACE_ALLOC, 322 " CREATE SURFACE %s IN SESSION %s: pid=%d format=%d flags=0x%x / %s", 323 mSurfaceController, mSession.mSurfaceSession, mSession.mPid, attrs.format, 324 flags, this); 325 } catch (OutOfResourcesException e) { 326 Slog.w(TAG, "OutOfResourcesException creating surface"); 327 mService.mRoot.reclaimSomeSurfaceMemory(this, "create", true); 328 mDrawState = NO_SURFACE; 329 return null; 330 } catch (Exception e) { 331 Slog.e(TAG, "Exception creating surface (parent dead?)", e); 332 mDrawState = NO_SURFACE; 333 return null; 334 } 335 336 if (DEBUG) { 337 Slog.v(TAG, "Got surface: " + mSurfaceController 338 + ", set left=" + w.getFrame().left + " top=" + w.getFrame().top); 339 } 340 341 if (SHOW_LIGHT_TRANSACTIONS) { 342 Slog.i(TAG, ">>> OPEN TRANSACTION createSurfaceLocked"); 343 WindowManagerService.logSurface(w, "CREATE pos=(" 344 + w.getFrame().left + "," + w.getFrame().top + ") HIDE", false); 345 } 346 347 mLastHidden = true; 348 349 if (DEBUG) Slog.v(TAG, "Created surface " + this); 350 return mSurfaceController; 351 } 352 hasSurface()353 boolean hasSurface() { 354 return mSurfaceController != null && mSurfaceController.hasSurface(); 355 } 356 destroySurfaceLocked(SurfaceControl.Transaction t)357 void destroySurfaceLocked(SurfaceControl.Transaction t) { 358 if (mSurfaceController == null) { 359 return; 360 } 361 362 mWin.mHidden = true; 363 364 try { 365 if (DEBUG_VISIBILITY) { 366 logWithStack(TAG, "Window " + this + " destroying surface " 367 + mSurfaceController + ", session " + mSession); 368 } 369 ProtoLog.i(WM_SHOW_SURFACE_ALLOC, "SURFACE DESTROY: %s. %s", 370 mWin, new RuntimeException().fillInStackTrace()); 371 destroySurface(t); 372 // Don't hide wallpaper if we're deferring the surface destroy 373 // because of a surface change. 374 mWallpaperControllerLocked.hideWallpapers(mWin); 375 } catch (RuntimeException e) { 376 Slog.w(TAG, "Exception thrown when destroying Window " + this 377 + " surface " + mSurfaceController + " session " + mSession + ": " 378 + e.toString()); 379 } 380 381 // Whether the surface was preserved (and copied to mPendingDestroySurface) or not, it 382 // needs to be cleared to match the WindowState.mHasSurface state. It is also necessary 383 // so it can be recreated successfully in mPendingDestroySurface case. 384 mWin.setHasSurface(false); 385 if (mSurfaceController != null) { 386 mSurfaceController.setShown(false); 387 } 388 mSurfaceController = null; 389 mDrawState = NO_SURFACE; 390 } 391 computeShownFrameLocked()392 void computeShownFrameLocked() { 393 if (mIsWallpaper && mService.mRoot.mWallpaperActionPending) { 394 return; 395 } else if (mWin.isDragResizeChanged()) { 396 // This window is awaiting a relayout because user just started (or ended) 397 // drag-resizing. The shown frame (which affects surface size and pos) 398 // should not be updated until we get next finished draw with the new surface. 399 // Otherwise one or two frames rendered with old settings would be displayed 400 // with new geometry. 401 return; 402 } 403 404 if (DEBUG) { 405 Slog.v(TAG, "computeShownFrameLocked: " + this 406 + " not attached, mAlpha=" + mAlpha); 407 } 408 409 mShownAlpha = mAlpha; 410 } 411 isInBlastSync()412 private boolean isInBlastSync() { 413 return mService.useBLASTSync() && mWin.useBLASTSync(); 414 } 415 prepareSurfaceLocked(SurfaceControl.Transaction t)416 void prepareSurfaceLocked(SurfaceControl.Transaction t) { 417 final WindowState w = mWin; 418 if (!hasSurface()) { 419 420 // There is no need to wait for an animation change if our window is gone for layout 421 // already as we'll never be visible. 422 if (w.getOrientationChanging() && w.isGoneForLayout()) { 423 ProtoLog.v(WM_DEBUG_ORIENTATION, "Orientation change skips hidden %s", w); 424 w.setOrientationChanging(false); 425 } 426 return; 427 } 428 429 computeShownFrameLocked(); 430 431 if (w.isParentWindowHidden() || !w.isOnScreen()) { 432 hide(t, "prepareSurfaceLocked"); 433 mWallpaperControllerLocked.hideWallpapers(w); 434 435 // If we are waiting for this window to handle an orientation change. If this window is 436 // really hidden (gone for layout), there is no point in still waiting for it. 437 // Note that this does introduce a potential glitch if the window becomes unhidden 438 // before it has drawn for the new orientation. 439 if (w.getOrientationChanging() && w.isGoneForLayout()) { 440 w.setOrientationChanging(false); 441 ProtoLog.v(WM_DEBUG_ORIENTATION, 442 "Orientation change skips hidden %s", w); 443 } 444 } else if (mLastAlpha != mShownAlpha 445 || mLastHidden) { 446 mLastAlpha = mShownAlpha; 447 ProtoLog.i(WM_SHOW_TRANSACTIONS, 448 "SURFACE controller=%s alpha=%f HScale=%f, VScale=%f: %s", 449 mSurfaceController, mShownAlpha, w.mHScale, w.mVScale, w); 450 451 boolean prepared = 452 mSurfaceController.prepareToShowInTransaction(t, mShownAlpha); 453 454 if (prepared && mDrawState == HAS_DRAWN) { 455 if (mLastHidden) { 456 if (showSurfaceRobustlyLocked(t)) { 457 mAnimator.requestRemovalOfReplacedWindows(w); 458 mLastHidden = false; 459 final DisplayContent displayContent = w.getDisplayContent(); 460 if (!displayContent.getLastHasContent()) { 461 // This draw means the difference between unique content and mirroring. 462 // Run another pass through performLayout to set mHasContent in the 463 // LogicalDisplay. 464 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM; 465 if (DEBUG_LAYOUT_REPEATS) { 466 mService.mWindowPlacerLocked.debugLayoutRepeats( 467 "showSurfaceRobustlyLocked " + w, 468 displayContent.pendingLayoutChanges); 469 } 470 } 471 } else { 472 w.setOrientationChanging(false); 473 } 474 } 475 } 476 } else { 477 if (mWin.isAnimating(TRANSITION | PARENTS)) { 478 ProtoLog.v(WM_DEBUG_ANIM, "prepareSurface: No changes in animation for %s", this); 479 } 480 } 481 482 if (w.getOrientationChanging()) { 483 if (!w.isDrawn()) { 484 if (w.mDisplayContent.shouldSyncRotationChange(w)) { 485 w.mWmService.mRoot.mOrientationChangeComplete = false; 486 mAnimator.mLastWindowFreezeSource = w; 487 } 488 ProtoLog.v(WM_DEBUG_ORIENTATION, 489 "Orientation continue waiting for draw in %s", w); 490 } else { 491 w.setOrientationChanging(false); 492 ProtoLog.v(WM_DEBUG_ORIENTATION, "Orientation change complete in %s", w); 493 } 494 } 495 } 496 setOpaqueLocked(boolean isOpaque)497 void setOpaqueLocked(boolean isOpaque) { 498 if (mSurfaceController == null) { 499 return; 500 } 501 mSurfaceController.setOpaque(isOpaque); 502 } 503 setSecureLocked(boolean isSecure)504 void setSecureLocked(boolean isSecure) { 505 if (mSurfaceController == null) { 506 return; 507 } 508 mSurfaceController.setSecure(isSecure); 509 } 510 setColorSpaceAgnosticLocked(boolean agnostic)511 void setColorSpaceAgnosticLocked(boolean agnostic) { 512 if (mSurfaceController == null) { 513 return; 514 } 515 mSurfaceController.setColorSpaceAgnostic(agnostic); 516 } 517 518 /** 519 * Have the surface flinger show a surface, robustly dealing with 520 * error conditions. In particular, if there is not enough memory 521 * to show the surface, then we will try to get rid of other surfaces 522 * in order to succeed. 523 * 524 * @return Returns true if the surface was successfully shown. 525 */ showSurfaceRobustlyLocked(SurfaceControl.Transaction t)526 private boolean showSurfaceRobustlyLocked(SurfaceControl.Transaction t) { 527 boolean shown = mSurfaceController.showRobustly(t); 528 if (!shown) 529 return false; 530 531 return true; 532 } 533 applyEnterAnimationLocked()534 void applyEnterAnimationLocked() { 535 // If we are the new part of a window replacement transition and we have requested 536 // not to animate, we instead want to make it seamless, so we don't want to apply 537 // an enter transition. 538 if (mWin.mSkipEnterAnimationForSeamlessReplacement) { 539 return; 540 } 541 542 final int transit; 543 if (mEnterAnimationPending) { 544 mEnterAnimationPending = false; 545 transit = WindowManagerPolicy.TRANSIT_ENTER; 546 } else { 547 transit = WindowManagerPolicy.TRANSIT_SHOW; 548 } 549 550 // We don't apply animation for application main window here since this window type 551 // should be controlled by ActivityRecord in general. Wallpaper is also excluded because 552 // WallpaperController should handle it. 553 if (mAttrType != TYPE_BASE_APPLICATION && !mIsWallpaper) { 554 applyAnimationLocked(transit, true); 555 } 556 557 if (mService.mAccessibilityController.hasCallbacks()) { 558 mService.mAccessibilityController.onWindowTransition(mWin, transit); 559 } 560 } 561 562 /** 563 * Choose the correct animation and set it to the passed WindowState. 564 * @param transit If AppTransition.TRANSIT_PREVIEW_DONE and the app window has been drawn 565 * then the animation will be app_starting_exit. Any other value loads the animation from 566 * the switch statement below. 567 * @param isEntrance The animation type the last time this was called. Used to keep from 568 * loading the same animation twice. 569 * @return true if an animation has been loaded. 570 */ applyAnimationLocked(int transit, boolean isEntrance)571 boolean applyAnimationLocked(int transit, boolean isEntrance) { 572 if (mWin.isAnimating() && mAnimationIsEntrance == isEntrance) { 573 // If we are trying to apply an animation, but already running 574 // an animation of the same type, then just leave that one alone. 575 return true; 576 } 577 578 if (mWin.mAttrs.type == TYPE_INPUT_METHOD) { 579 mWin.getDisplayContent().adjustForImeIfNeeded(); 580 if (isEntrance) { 581 mWin.setDisplayLayoutNeeded(); 582 mService.mWindowPlacerLocked.requestTraversal(); 583 } 584 } 585 586 if (mWin.mControllableInsetProvider != null) { 587 // All our animations should be driven by the insets control target. 588 return false; 589 } 590 591 // Only apply an animation if the display isn't frozen. If it is 592 // frozen, there is no reason to animate and it can cause strange 593 // artifacts when we unfreeze the display if some different animation 594 // is running. 595 if (mWin.mToken.okToAnimate()) { 596 int anim = mWin.getDisplayContent().getDisplayPolicy().selectAnimation(mWin, transit); 597 int attr = -1; 598 Animation a = null; 599 if (anim != DisplayPolicy.ANIMATION_STYLEABLE) { 600 if (anim != DisplayPolicy.ANIMATION_NONE) { 601 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "WSA#loadAnimation"); 602 a = AnimationUtils.loadAnimation(mContext, anim); 603 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 604 } 605 } else { 606 switch (transit) { 607 case WindowManagerPolicy.TRANSIT_ENTER: 608 attr = com.android.internal.R.styleable.WindowAnimation_windowEnterAnimation; 609 break; 610 case WindowManagerPolicy.TRANSIT_EXIT: 611 attr = com.android.internal.R.styleable.WindowAnimation_windowExitAnimation; 612 break; 613 case WindowManagerPolicy.TRANSIT_SHOW: 614 attr = com.android.internal.R.styleable.WindowAnimation_windowShowAnimation; 615 break; 616 case WindowManagerPolicy.TRANSIT_HIDE: 617 attr = com.android.internal.R.styleable.WindowAnimation_windowHideAnimation; 618 break; 619 } 620 if (attr >= 0) { 621 a = mWin.getDisplayContent().mAppTransition.loadAnimationAttr( 622 mWin.mAttrs, attr, TRANSIT_OLD_NONE); 623 } 624 } 625 if (ProtoLogImpl.isEnabled(WM_DEBUG_ANIM)) { 626 ProtoLog.v(WM_DEBUG_ANIM, "applyAnimation: win=%s" 627 + " anim=%d attr=0x%x a=%s transit=%d type=%d isEntrance=%b Callers %s", 628 this, anim, attr, a, transit, mAttrType, isEntrance, Debug.getCallers(20)); 629 } 630 if (a != null) { 631 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "WSA#startAnimation"); 632 mWin.startAnimation(a); 633 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 634 mAnimationIsEntrance = isEntrance; 635 } 636 } else { 637 mWin.cancelAnimation(); 638 } 639 640 return mWin.isAnimating(0 /* flags */, ANIMATION_TYPE_WINDOW_ANIMATION); 641 } 642 dumpDebug(ProtoOutputStream proto, long fieldId)643 void dumpDebug(ProtoOutputStream proto, long fieldId) { 644 final long token = proto.start(fieldId); 645 if (mSurfaceController != null) { 646 mSurfaceController.dumpDebug(proto, SURFACE); 647 } 648 proto.write(DRAW_STATE, mDrawState); 649 mSystemDecorRect.dumpDebug(proto, SYSTEM_DECOR_RECT); 650 proto.end(token); 651 } 652 dump(PrintWriter pw, String prefix, boolean dumpAll)653 public void dump(PrintWriter pw, String prefix, boolean dumpAll) { 654 if (mAnimationIsEntrance) { 655 pw.print(prefix); pw.print(" mAnimationIsEntrance="); pw.print(mAnimationIsEntrance); 656 } 657 if (mSurfaceController != null) { 658 mSurfaceController.dump(pw, prefix, dumpAll); 659 } 660 if (dumpAll) { 661 pw.print(prefix); pw.print("mDrawState="); pw.print(drawStateToString()); 662 pw.print(prefix); pw.print(" mLastHidden="); pw.println(mLastHidden); 663 pw.print(prefix); pw.print("mEnterAnimationPending=" + mEnterAnimationPending); 664 pw.print(prefix); pw.print("mSystemDecorRect="); mSystemDecorRect.printShortString(pw); 665 666 pw.println(); 667 } 668 669 if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) { 670 pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha); 671 pw.print(" mAlpha="); pw.print(mAlpha); 672 pw.print(" mLastAlpha="); pw.println(mLastAlpha); 673 } 674 if (mWin.mGlobalScale != 1) { 675 pw.print(prefix); pw.print("mGlobalScale="); pw.print(mWin.mGlobalScale); 676 } 677 } 678 679 @Override toString()680 public String toString() { 681 StringBuffer sb = new StringBuffer("WindowStateAnimator{"); 682 sb.append(Integer.toHexString(System.identityHashCode(this))); 683 sb.append(' '); 684 sb.append(mWin.mAttrs.getTitle()); 685 sb.append('}'); 686 return sb.toString(); 687 } 688 getShown()689 boolean getShown() { 690 if (mSurfaceController != null) { 691 return mSurfaceController.getShown(); 692 } 693 return false; 694 } 695 destroySurface(SurfaceControl.Transaction t)696 void destroySurface(SurfaceControl.Transaction t) { 697 try { 698 if (mSurfaceController != null) { 699 mSurfaceController.destroy(t); 700 } 701 } catch (RuntimeException e) { 702 Slog.w(TAG, "Exception thrown when destroying surface " + this 703 + " surface " + mSurfaceController + " session " + mSession + ": " + e); 704 } finally { 705 mWin.setHasSurface(false); 706 mSurfaceController = null; 707 mDrawState = NO_SURFACE; 708 } 709 } 710 getSurfaceControl()711 SurfaceControl getSurfaceControl() { 712 if (!hasSurface()) { 713 return null; 714 } 715 return mSurfaceController.mSurfaceControl; 716 } 717 } 718