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