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_DRAW; 27 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION; 28 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW; 29 import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC; 30 import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS; 31 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; 32 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 33 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION; 34 import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS; 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_ANIM; 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.common.ProtoLog; 64 import com.android.server.policy.WindowManagerPolicy; 65 66 import java.io.PrintWriter; 67 68 /** 69 * Keep track of animations and surface operations for a single WindowState. 70 **/ 71 class WindowStateAnimator { 72 static final String TAG = TAG_WITH_CLASS_NAME ? "WindowStateAnimator" : TAG_WM; 73 static final int PRESERVED_SURFACE_LAYER = 1; 74 75 /** 76 * Mode how the window gets clipped by the root task bounds during an animation: The clipping 77 * should be applied after applying the animation transformation, i.e. the root task bounds 78 * don't move during the animation. 79 */ 80 static final int ROOT_TASK_CLIP_AFTER_ANIM = 0; 81 82 /** 83 * Mode how window gets clipped by the root task bounds during an animation: Don't clip the 84 * window by the root task bounds. 85 */ 86 static final int ROOT_TASK_CLIP_NONE = 1; 87 88 // Unchanging local convenience fields. 89 final WindowManagerService mService; 90 final WindowState mWin; 91 final WindowAnimator mAnimator; 92 final Session mSession; 93 final WindowManagerPolicy mPolicy; 94 final Context mContext; 95 final boolean mIsWallpaper; 96 private final WallpaperController mWallpaperControllerLocked; 97 98 boolean mAnimationIsEntrance; 99 100 WindowSurfaceController mSurfaceController; 101 102 float mShownAlpha = 0; 103 float mAlpha = 0; 104 float mLastAlpha = 0; 105 106 /** 107 * This is rectangle of the window's surface that is not covered by 108 * system decorations. 109 */ 110 private final Rect mSystemDecorRect = new Rect(); 111 112 // Set to true if, when the window gets displayed, it should perform 113 // an enter animation. 114 boolean mEnterAnimationPending; 115 116 /** Used to indicate that this window is undergoing an enter animation. Used for system 117 * windows to make the callback to View.dispatchOnWindowShownCallback(). Set when the 118 * window is first added or shown, cleared when the callback has been made. */ 119 boolean mEnteringAnimation; 120 121 /** The pixel format of the underlying SurfaceControl */ 122 int mSurfaceFormat; 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 156 private final Rect mTmpSize = new Rect(); 157 158 /** 159 * Handles surface changes synchronized to after the client has drawn the surface. This 160 * transaction is currently used to reparent the old surface children to the new surface once 161 * the client has completed drawing to the new surface. 162 * This transaction is also used to merge transactions parceled in by the client. The client 163 * uses the transaction to update the relative z of its children from the old parent surface 164 * to the new parent surface once window manager reparents its children. 165 */ 166 private final SurfaceControl.Transaction mPostDrawTransaction = 167 new SurfaceControl.Transaction(); 168 WindowStateAnimator(final WindowState win)169 WindowStateAnimator(final WindowState win) { 170 final WindowManagerService service = win.mWmService; 171 172 mService = service; 173 mAnimator = service.mAnimator; 174 mPolicy = service.mPolicy; 175 mContext = service.mContext; 176 177 mWin = win; 178 mSession = win.mSession; 179 mAttrType = win.mAttrs.type; 180 mIsWallpaper = win.mIsWallpaper; 181 mWallpaperControllerLocked = win.getDisplayContent().mWallpaperController; 182 } 183 onAnimationFinished()184 void onAnimationFinished() { 185 // Done animating, clean up. 186 if (DEBUG_ANIM) Slog.v( 187 TAG, "Animation done in " + this + ": exiting=" + mWin.mAnimatingExit 188 + ", reportedVisible=" 189 + (mWin.mActivityRecord != null && mWin.mActivityRecord.reportedVisible)); 190 191 mWin.checkPolicyVisibilityChange(); 192 final DisplayContent displayContent = mWin.getDisplayContent(); 193 if ((mAttrType == LayoutParams.TYPE_STATUS_BAR 194 || mAttrType == LayoutParams.TYPE_NOTIFICATION_SHADE) && mWin.isVisibleByPolicy()) { 195 // Upon completion of a not-visible to visible status bar animation a relayout is 196 // required. 197 displayContent.setLayoutNeeded(); 198 } 199 mWin.onExitAnimationDone(); 200 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM; 201 if (displayContent.mWallpaperController.isWallpaperTarget(mWin)) { 202 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 203 } 204 if (DEBUG_LAYOUT_REPEATS) { 205 mService.mWindowPlacerLocked.debugLayoutRepeats( 206 "WindowStateAnimator", displayContent.pendingLayoutChanges); 207 } 208 209 if (mWin.mActivityRecord != null) { 210 mWin.mActivityRecord.updateReportedVisibilityLocked(); 211 } 212 } 213 hide(SurfaceControl.Transaction transaction, String reason)214 void hide(SurfaceControl.Transaction transaction, String reason) { 215 if (!mLastHidden) { 216 //dump(); 217 mLastHidden = true; 218 219 if (mSurfaceController != null) { 220 mSurfaceController.hide(transaction, reason); 221 } 222 } 223 } 224 finishDrawingLocked(SurfaceControl.Transaction postDrawTransaction, boolean forceApplyNow)225 boolean finishDrawingLocked(SurfaceControl.Transaction postDrawTransaction, 226 boolean forceApplyNow) { 227 final boolean startingWindow = 228 mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; 229 if (startingWindow) { 230 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Finishing drawing window %s: mDrawState=%s", 231 mWin, drawStateToString()); 232 } 233 234 boolean layoutNeeded = false; 235 236 if (mDrawState == DRAW_PENDING) { 237 ProtoLog.v(WM_DEBUG_DRAW, 238 "finishDrawingLocked: mDrawState=COMMIT_DRAW_PENDING %s in %s", mWin, 239 mSurfaceController); 240 if (startingWindow) { 241 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Draw state now committed in %s", mWin); 242 } 243 mDrawState = COMMIT_DRAW_PENDING; 244 layoutNeeded = true; 245 } 246 247 if (postDrawTransaction != null) { 248 // If there is no surface, the last draw was for the previous surface. We don't want to 249 // wait until the new surface is shown and instead just apply the transaction right 250 // away. 251 if (mLastHidden && mDrawState != NO_SURFACE && !forceApplyNow) { 252 mPostDrawTransaction.merge(postDrawTransaction); 253 } else { 254 mWin.getSyncTransaction().merge(postDrawTransaction); 255 } 256 layoutNeeded = true; 257 } 258 259 return layoutNeeded; 260 } 261 262 // This must be called while inside a transaction. commitFinishDrawingLocked()263 boolean commitFinishDrawingLocked() { 264 if (DEBUG_STARTING_WINDOW_VERBOSE && 265 mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) { 266 Slog.i(TAG, "commitFinishDrawingLocked: " + mWin + " cur mDrawState=" 267 + drawStateToString()); 268 } 269 if (mDrawState != COMMIT_DRAW_PENDING && mDrawState != READY_TO_SHOW) { 270 return false; 271 } 272 if (DEBUG_ANIM) { 273 Slog.i(TAG, "commitFinishDrawingLocked: mDrawState=READY_TO_SHOW " + mSurfaceController); 274 } 275 mDrawState = READY_TO_SHOW; 276 boolean result = false; 277 final ActivityRecord activity = mWin.mActivityRecord; 278 if (activity == null || activity.canShowWindows() 279 || mWin.mAttrs.type == TYPE_APPLICATION_STARTING) { 280 result = mWin.performShowLocked(); 281 } 282 return result; 283 } 284 resetDrawState()285 void resetDrawState() { 286 mDrawState = DRAW_PENDING; 287 288 if (mWin.mActivityRecord == null) { 289 return; 290 } 291 292 if (!mWin.mActivityRecord.isAnimating(TRANSITION)) { 293 mWin.mActivityRecord.clearAllDrawn(); 294 } 295 } 296 createSurfaceLocked(int windowType)297 WindowSurfaceController createSurfaceLocked(int windowType) { 298 final WindowState w = mWin; 299 300 if (mSurfaceController != null) { 301 return mSurfaceController; 302 } 303 304 w.setHasSurface(false); 305 306 if (DEBUG_ANIM) { 307 Slog.i(TAG, "createSurface " + this + ": mDrawState=DRAW_PENDING"); 308 } 309 310 resetDrawState(); 311 312 mService.makeWindowFreezingScreenIfNeededLocked(w); 313 314 int flags = SurfaceControl.HIDDEN; 315 final WindowManager.LayoutParams attrs = w.mAttrs; 316 317 if (w.isSecureLocked()) { 318 flags |= SurfaceControl.SECURE; 319 } 320 321 if ((mWin.mAttrs.privateFlags & PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY) != 0) { 322 flags |= SurfaceControl.SKIP_SCREENSHOT; 323 } 324 325 w.calculateSurfaceBounds(attrs, mTmpSize); 326 327 final int width = mTmpSize.width(); 328 final int height = mTmpSize.height(); 329 330 if (DEBUG_VISIBILITY) { 331 Slog.v(TAG, "Creating surface in session " 332 + mSession.mSurfaceSession + " window " + this 333 + " w=" + width + " h=" + height 334 + " x=" + mTmpSize.left + " y=" + mTmpSize.top 335 + " format=" + attrs.format + " flags=" + flags); 336 } 337 338 // Set up surface control with initial size. 339 try { 340 341 // This can be removed once we move all Buffer Layers to use BLAST. 342 final boolean isHwAccelerated = (attrs.flags & FLAG_HARDWARE_ACCELERATED) != 0; 343 final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format; 344 345 mSurfaceController = new WindowSurfaceController(attrs.getTitle().toString(), width, 346 height, format, flags, this, windowType); 347 mSurfaceController.setColorSpaceAgnostic((attrs.privateFlags 348 & WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC) != 0); 349 350 mSurfaceFormat = format; 351 352 w.setHasSurface(true); 353 // The surface instance is changed. Make sure the input info can be applied to the 354 // new surface, e.g. relaunch activity. 355 w.mInputWindowHandle.forceChange(); 356 357 ProtoLog.i(WM_SHOW_SURFACE_ALLOC, 358 " CREATE SURFACE %s IN SESSION %s: pid=%d format=%d flags=0x%x / %s", 359 mSurfaceController, mSession.mSurfaceSession, mSession.mPid, attrs.format, 360 flags, this); 361 } catch (OutOfResourcesException e) { 362 Slog.w(TAG, "OutOfResourcesException creating surface"); 363 mService.mRoot.reclaimSomeSurfaceMemory(this, "create", true); 364 mDrawState = NO_SURFACE; 365 return null; 366 } catch (Exception e) { 367 Slog.e(TAG, "Exception creating surface (parent dead?)", e); 368 mDrawState = NO_SURFACE; 369 return null; 370 } 371 372 if (DEBUG) { 373 Slog.v(TAG, "Got surface: " + mSurfaceController 374 + ", set left=" + w.getFrame().left + " top=" + w.getFrame().top); 375 } 376 377 if (SHOW_LIGHT_TRANSACTIONS) { 378 Slog.i(TAG, ">>> OPEN TRANSACTION createSurfaceLocked"); 379 WindowManagerService.logSurface(w, "CREATE pos=(" 380 + w.getFrame().left + "," + w.getFrame().top + ") (" 381 + width + "x" + height + ")" + " HIDE", false); 382 } 383 384 mLastHidden = true; 385 386 if (DEBUG) Slog.v(TAG, "Created surface " + this); 387 return mSurfaceController; 388 } 389 hasSurface()390 boolean hasSurface() { 391 return mSurfaceController != null && mSurfaceController.hasSurface(); 392 } 393 destroySurfaceLocked(SurfaceControl.Transaction t)394 void destroySurfaceLocked(SurfaceControl.Transaction t) { 395 final ActivityRecord activity = mWin.mActivityRecord; 396 if (activity != null) { 397 if (mWin == activity.mStartingWindow) { 398 activity.startingDisplayed = false; 399 } 400 } 401 402 if (mSurfaceController == null) { 403 return; 404 } 405 406 mWin.mHidden = true; 407 408 try { 409 if (DEBUG_VISIBILITY) { 410 logWithStack(TAG, "Window " + this + " destroying surface " 411 + mSurfaceController + ", session " + mSession); 412 } 413 ProtoLog.i(WM_SHOW_SURFACE_ALLOC, "SURFACE DESTROY: %s. %s", 414 mWin, new RuntimeException().fillInStackTrace()); 415 destroySurface(t); 416 // Don't hide wallpaper if we're deferring the surface destroy 417 // because of a surface change. 418 mWallpaperControllerLocked.hideWallpapers(mWin); 419 } catch (RuntimeException e) { 420 Slog.w(TAG, "Exception thrown when destroying Window " + this 421 + " surface " + mSurfaceController + " session " + mSession + ": " 422 + e.toString()); 423 } 424 425 // Whether the surface was preserved (and copied to mPendingDestroySurface) or not, it 426 // needs to be cleared to match the WindowState.mHasSurface state. It is also necessary 427 // so it can be recreated successfully in mPendingDestroySurface case. 428 mWin.setHasSurface(false); 429 if (mSurfaceController != null) { 430 mSurfaceController.setShown(false); 431 } 432 mSurfaceController = null; 433 mDrawState = NO_SURFACE; 434 } 435 computeShownFrameLocked()436 void computeShownFrameLocked() { 437 if (mIsWallpaper && mService.mRoot.mWallpaperActionPending) { 438 return; 439 } else if (mWin.isDragResizeChanged()) { 440 // This window is awaiting a relayout because user just started (or ended) 441 // drag-resizing. The shown frame (which affects surface size and pos) 442 // should not be updated until we get next finished draw with the new surface. 443 // Otherwise one or two frames rendered with old settings would be displayed 444 // with new geometry. 445 return; 446 } 447 448 if (DEBUG) { 449 Slog.v(TAG, "computeShownFrameLocked: " + this 450 + " not attached, mAlpha=" + mAlpha); 451 } 452 453 mShownAlpha = mAlpha; 454 } 455 isInBlastSync()456 private boolean isInBlastSync() { 457 return mService.useBLASTSync() && mWin.useBLASTSync(); 458 } 459 shouldConsumeMainWindowSizeTransaction()460 private boolean shouldConsumeMainWindowSizeTransaction() { 461 // We only consume the transaction when the client is calling relayout 462 // because this is the only time we know the frameNumber will be valid 463 // due to the client renderer being paused. Put otherwise, only when 464 // mInRelayout is true can we guarantee the next frame will contain 465 // the most recent configuration. 466 if (!mWin.mInRelayout) return false; 467 // Since we can only do this for one window, we focus on the main application window 468 if (mAttrType != TYPE_BASE_APPLICATION) return false; 469 final Task task = mWin.getTask(); 470 if (task == null) return false; 471 if (task.getMainWindowSizeChangeTransaction() == null) return false; 472 // Likewise we only focus on the task root, since we can only use one window 473 if (!mWin.mActivityRecord.isRootOfTask()) return false; 474 return true; 475 } 476 setSurfaceBoundariesLocked(SurfaceControl.Transaction t)477 void setSurfaceBoundariesLocked(SurfaceControl.Transaction t) { 478 if (mSurfaceController == null) { 479 return; 480 } 481 482 final WindowState w = mWin; 483 final Task task = w.getTask(); 484 if (shouldConsumeMainWindowSizeTransaction()) { 485 if (isInBlastSync()) { 486 // If we're in a sync transaction, there's no need to call defer transaction. 487 // The sync transaction will contain the buffer so the bounds change transaction 488 // will only be applied with the buffer. 489 t.merge(task.getMainWindowSizeChangeTransaction()); 490 task.setMainWindowSizeChangeTransaction(null); 491 } else { 492 mWin.applyWithNextDraw(finishedFrame -> { 493 final SurfaceControl.Transaction sizeChangedTransaction = 494 task.getMainWindowSizeChangeTransaction(); 495 if (sizeChangedTransaction != null) { 496 finishedFrame.merge(sizeChangedTransaction); 497 task.setMainWindowSizeChangeTransaction(null); 498 } 499 }); 500 } 501 } 502 } 503 prepareSurfaceLocked(SurfaceControl.Transaction t)504 void prepareSurfaceLocked(SurfaceControl.Transaction t) { 505 final WindowState w = mWin; 506 if (!hasSurface()) { 507 508 // There is no need to wait for an animation change if our window is gone for layout 509 // already as we'll never be visible. 510 if (w.getOrientationChanging() && w.isGoneForLayout()) { 511 ProtoLog.v(WM_DEBUG_ORIENTATION, "Orientation change skips hidden %s", w); 512 w.setOrientationChanging(false); 513 } 514 return; 515 } 516 517 boolean displayed = false; 518 519 computeShownFrameLocked(); 520 521 setSurfaceBoundariesLocked(t); 522 523 if (w.isParentWindowHidden() || !w.isOnScreen()) { 524 hide(t, "prepareSurfaceLocked"); 525 mWallpaperControllerLocked.hideWallpapers(w); 526 527 // If we are waiting for this window to handle an orientation change. If this window is 528 // really hidden (gone for layout), there is no point in still waiting for it. 529 // Note that this does introduce a potential glitch if the window becomes unhidden 530 // before it has drawn for the new orientation. 531 if (w.getOrientationChanging() && w.isGoneForLayout()) { 532 w.setOrientationChanging(false); 533 ProtoLog.v(WM_DEBUG_ORIENTATION, 534 "Orientation change skips hidden %s", w); 535 } 536 } else if (mLastAlpha != mShownAlpha 537 || mLastHidden) { 538 displayed = true; 539 mLastAlpha = mShownAlpha; 540 ProtoLog.i(WM_SHOW_TRANSACTIONS, 541 "SURFACE controller=%s alpha=%f HScale=%f, VScale=%f: %s", 542 mSurfaceController, mShownAlpha, w.mHScale, w.mVScale, w); 543 544 boolean prepared = 545 mSurfaceController.prepareToShowInTransaction(t, mShownAlpha); 546 547 if (prepared && mDrawState == HAS_DRAWN) { 548 if (mLastHidden) { 549 if (showSurfaceRobustlyLocked(t)) { 550 mAnimator.requestRemovalOfReplacedWindows(w); 551 mLastHidden = false; 552 final DisplayContent displayContent = w.getDisplayContent(); 553 if (!displayContent.getLastHasContent()) { 554 // This draw means the difference between unique content and mirroring. 555 // Run another pass through performLayout to set mHasContent in the 556 // LogicalDisplay. 557 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM; 558 if (DEBUG_LAYOUT_REPEATS) { 559 mService.mWindowPlacerLocked.debugLayoutRepeats( 560 "showSurfaceRobustlyLocked " + w, 561 displayContent.pendingLayoutChanges); 562 } 563 } 564 } else { 565 w.setOrientationChanging(false); 566 } 567 } 568 } 569 if (hasSurface()) { 570 w.mToken.hasVisible = true; 571 } 572 } else { 573 if (DEBUG_ANIM && mWin.isAnimating(TRANSITION | PARENTS)) { 574 Slog.v(TAG, "prepareSurface: No changes in animation for " + this); 575 } 576 displayed = true; 577 } 578 579 if (w.getOrientationChanging()) { 580 if (!w.isDrawn()) { 581 if (w.mDisplayContent.waitForUnfreeze(w)) { 582 w.mWmService.mRoot.mOrientationChangeComplete = false; 583 mAnimator.mLastWindowFreezeSource = w; 584 } 585 ProtoLog.v(WM_DEBUG_ORIENTATION, 586 "Orientation continue waiting for draw in %s", w); 587 } else { 588 w.setOrientationChanging(false); 589 ProtoLog.v(WM_DEBUG_ORIENTATION, "Orientation change complete in %s", w); 590 } 591 } 592 593 if (displayed) { 594 w.mToken.hasVisible = true; 595 } 596 } 597 598 /** 599 * Try to change the pixel format without recreating the surface. This 600 * will be common in the case of changing from PixelFormat.OPAQUE to 601 * PixelFormat.TRANSLUCENT in the hardware-accelerated case as both 602 * requested formats resolve to the same underlying SurfaceControl format 603 * @return True if format was succesfully changed, false otherwise 604 */ tryChangeFormatInPlaceLocked()605 boolean tryChangeFormatInPlaceLocked() { 606 if (mSurfaceController == null) { 607 return false; 608 } 609 final LayoutParams attrs = mWin.getAttrs(); 610 final boolean isHwAccelerated = (attrs.flags & FLAG_HARDWARE_ACCELERATED) != 0; 611 final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format; 612 if (format == mSurfaceFormat) { 613 setOpaqueLocked(!PixelFormat.formatHasAlpha(attrs.format)); 614 return true; 615 } 616 return false; 617 } 618 setOpaqueLocked(boolean isOpaque)619 void setOpaqueLocked(boolean isOpaque) { 620 if (mSurfaceController == null) { 621 return; 622 } 623 mSurfaceController.setOpaque(isOpaque); 624 } 625 setSecureLocked(boolean isSecure)626 void setSecureLocked(boolean isSecure) { 627 if (mSurfaceController == null) { 628 return; 629 } 630 mSurfaceController.setSecure(isSecure); 631 } 632 setColorSpaceAgnosticLocked(boolean agnostic)633 void setColorSpaceAgnosticLocked(boolean agnostic) { 634 if (mSurfaceController == null) { 635 return; 636 } 637 mSurfaceController.setColorSpaceAgnostic(agnostic); 638 } 639 640 /** 641 * Have the surface flinger show a surface, robustly dealing with 642 * error conditions. In particular, if there is not enough memory 643 * to show the surface, then we will try to get rid of other surfaces 644 * in order to succeed. 645 * 646 * @return Returns true if the surface was successfully shown. 647 */ showSurfaceRobustlyLocked(SurfaceControl.Transaction t)648 private boolean showSurfaceRobustlyLocked(SurfaceControl.Transaction t) { 649 boolean shown = mSurfaceController.showRobustly(t); 650 if (!shown) 651 return false; 652 653 t.merge(mPostDrawTransaction); 654 return true; 655 } 656 applyEnterAnimationLocked()657 void applyEnterAnimationLocked() { 658 // If we are the new part of a window replacement transition and we have requested 659 // not to animate, we instead want to make it seamless, so we don't want to apply 660 // an enter transition. 661 if (mWin.mSkipEnterAnimationForSeamlessReplacement) { 662 return; 663 } 664 665 final int transit; 666 if (mEnterAnimationPending) { 667 mEnterAnimationPending = false; 668 transit = WindowManagerPolicy.TRANSIT_ENTER; 669 } else { 670 transit = WindowManagerPolicy.TRANSIT_SHOW; 671 } 672 673 // We don't apply animation for application main window here since this window type 674 // should be controlled by ActivityRecord in general. Wallpaper is also excluded because 675 // WallpaperController should handle it. 676 if (mAttrType != TYPE_BASE_APPLICATION && !mIsWallpaper) { 677 applyAnimationLocked(transit, true); 678 } 679 680 if (mService.mAccessibilityController.hasCallbacks()) { 681 mService.mAccessibilityController.onWindowTransition(mWin, transit); 682 } 683 } 684 685 /** 686 * Choose the correct animation and set it to the passed WindowState. 687 * @param transit If AppTransition.TRANSIT_PREVIEW_DONE and the app window has been drawn 688 * then the animation will be app_starting_exit. Any other value loads the animation from 689 * the switch statement below. 690 * @param isEntrance The animation type the last time this was called. Used to keep from 691 * loading the same animation twice. 692 * @return true if an animation has been loaded. 693 */ applyAnimationLocked(int transit, boolean isEntrance)694 boolean applyAnimationLocked(int transit, boolean isEntrance) { 695 if (mWin.isAnimating() && mAnimationIsEntrance == isEntrance) { 696 // If we are trying to apply an animation, but already running 697 // an animation of the same type, then just leave that one alone. 698 return true; 699 } 700 701 final boolean isImeWindow = mWin.mAttrs.type == TYPE_INPUT_METHOD; 702 if (isEntrance && isImeWindow) { 703 mWin.getDisplayContent().adjustForImeIfNeeded(); 704 mWin.setDisplayLayoutNeeded(); 705 mService.mWindowPlacerLocked.requestTraversal(); 706 } 707 708 // Only apply an animation if the display isn't frozen. If it is 709 // frozen, there is no reason to animate and it can cause strange 710 // artifacts when we unfreeze the display if some different animation 711 // is running. 712 if (mWin.mToken.okToAnimate()) { 713 int anim = mWin.getDisplayContent().getDisplayPolicy().selectAnimation(mWin, transit); 714 int attr = -1; 715 Animation a = null; 716 if (anim != DisplayPolicy.ANIMATION_STYLEABLE) { 717 if (anim != DisplayPolicy.ANIMATION_NONE) { 718 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "WSA#loadAnimation"); 719 a = AnimationUtils.loadAnimation(mContext, anim); 720 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 721 } 722 } else { 723 switch (transit) { 724 case WindowManagerPolicy.TRANSIT_ENTER: 725 attr = com.android.internal.R.styleable.WindowAnimation_windowEnterAnimation; 726 break; 727 case WindowManagerPolicy.TRANSIT_EXIT: 728 attr = com.android.internal.R.styleable.WindowAnimation_windowExitAnimation; 729 break; 730 case WindowManagerPolicy.TRANSIT_SHOW: 731 attr = com.android.internal.R.styleable.WindowAnimation_windowShowAnimation; 732 break; 733 case WindowManagerPolicy.TRANSIT_HIDE: 734 attr = com.android.internal.R.styleable.WindowAnimation_windowHideAnimation; 735 break; 736 } 737 if (attr >= 0) { 738 a = mWin.getDisplayContent().mAppTransition.loadAnimationAttr( 739 mWin.mAttrs, attr, TRANSIT_OLD_NONE); 740 } 741 } 742 if (DEBUG_ANIM) Slog.v(TAG, 743 "applyAnimation: win=" + this 744 + " anim=" + anim + " attr=0x" + Integer.toHexString(attr) 745 + " a=" + a 746 + " transit=" + transit 747 + " type=" + mAttrType 748 + " isEntrance=" + isEntrance + " Callers " + Debug.getCallers(3)); 749 if (a != null) { 750 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this); 751 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "WSA#startAnimation"); 752 mWin.startAnimation(a); 753 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 754 mAnimationIsEntrance = isEntrance; 755 } 756 } else if (!isImeWindow) { 757 mWin.cancelAnimation(); 758 } 759 760 if (!isEntrance && isImeWindow) { 761 mWin.getDisplayContent().adjustForImeIfNeeded(); 762 } 763 764 return mWin.isAnimating(0 /* flags */, ANIMATION_TYPE_WINDOW_ANIMATION); 765 } 766 dumpDebug(ProtoOutputStream proto, long fieldId)767 void dumpDebug(ProtoOutputStream proto, long fieldId) { 768 final long token = proto.start(fieldId); 769 if (mSurfaceController != null) { 770 mSurfaceController.dumpDebug(proto, SURFACE); 771 } 772 proto.write(DRAW_STATE, mDrawState); 773 mSystemDecorRect.dumpDebug(proto, SYSTEM_DECOR_RECT); 774 proto.end(token); 775 } 776 dump(PrintWriter pw, String prefix, boolean dumpAll)777 public void dump(PrintWriter pw, String prefix, boolean dumpAll) { 778 if (mAnimationIsEntrance) { 779 pw.print(prefix); pw.print(" mAnimationIsEntrance="); pw.print(mAnimationIsEntrance); 780 } 781 if (mSurfaceController != null) { 782 mSurfaceController.dump(pw, prefix, dumpAll); 783 } 784 if (dumpAll) { 785 pw.print(prefix); pw.print("mDrawState="); pw.print(drawStateToString()); 786 pw.print(prefix); pw.print(" mLastHidden="); pw.println(mLastHidden); 787 pw.print(prefix); pw.print("mEnterAnimationPending=" + mEnterAnimationPending); 788 pw.print(prefix); pw.print("mSystemDecorRect="); mSystemDecorRect.printShortString(pw); 789 790 pw.println(); 791 } 792 793 if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) { 794 pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha); 795 pw.print(" mAlpha="); pw.print(mAlpha); 796 pw.print(" mLastAlpha="); pw.println(mLastAlpha); 797 } 798 if (mWin.mGlobalScale != 1) { 799 pw.print(prefix); pw.print("mGlobalScale="); pw.print(mWin.mGlobalScale); 800 } 801 } 802 803 @Override toString()804 public String toString() { 805 StringBuffer sb = new StringBuffer("WindowStateAnimator{"); 806 sb.append(Integer.toHexString(System.identityHashCode(this))); 807 sb.append(' '); 808 sb.append(mWin.mAttrs.getTitle()); 809 sb.append('}'); 810 return sb.toString(); 811 } 812 getShown()813 boolean getShown() { 814 if (mSurfaceController != null) { 815 return mSurfaceController.getShown(); 816 } 817 return false; 818 } 819 destroySurface(SurfaceControl.Transaction t)820 void destroySurface(SurfaceControl.Transaction t) { 821 // Since the SurfaceControl is getting torn down, it's safe to just clean up any 822 // pending transactions that were in mPostDrawTransaction, as well. 823 t.merge(mPostDrawTransaction); 824 825 try { 826 if (mSurfaceController != null) { 827 mSurfaceController.destroy(t); 828 } 829 } catch (RuntimeException e) { 830 Slog.w(TAG, "Exception thrown when destroying surface " + this 831 + " surface " + mSurfaceController + " session " + mSession + ": " + e); 832 } finally { 833 mWin.setHasSurface(false); 834 mSurfaceController = null; 835 mDrawState = NO_SURFACE; 836 } 837 } 838 getSurfaceControl()839 SurfaceControl getSurfaceControl() { 840 if (!hasSurface()) { 841 return null; 842 } 843 return mSurfaceController.mSurfaceControl; 844 } 845 } 846