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