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.graphics.Matrix.MSCALE_X; 20 import static android.graphics.Matrix.MSCALE_Y; 21 import static android.graphics.Matrix.MSKEW_X; 22 import static android.graphics.Matrix.MSKEW_Y; 23 import static android.graphics.Matrix.MTRANS_X; 24 import static android.graphics.Matrix.MTRANS_Y; 25 import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; 26 import static android.view.WindowManager.LayoutParams.FLAG_SCALED; 27 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY; 28 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; 29 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; 30 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; 31 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; 32 import static android.view.WindowManager.TRANSIT_NONE; 33 34 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; 35 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 36 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_DRAW; 37 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION; 38 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW; 39 import static com.android.server.wm.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC; 40 import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS; 41 import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS; 42 import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; 43 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG; 44 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM; 45 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS; 46 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE; 47 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; 48 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_CROP; 49 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS; 50 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; 51 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 52 import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER; 53 import static com.android.server.wm.WindowManagerService.logWithStack; 54 import static com.android.server.wm.WindowStateAnimatorProto.DRAW_STATE; 55 import static com.android.server.wm.WindowStateAnimatorProto.LAST_CLIP_RECT; 56 import static com.android.server.wm.WindowStateAnimatorProto.SURFACE; 57 import static com.android.server.wm.WindowStateAnimatorProto.SYSTEM_DECOR_RECT; 58 import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE; 59 60 import android.app.WindowConfiguration; 61 import android.content.Context; 62 import android.graphics.Matrix; 63 import android.graphics.PixelFormat; 64 import android.graphics.Point; 65 import android.graphics.Rect; 66 import android.graphics.Region; 67 import android.os.Debug; 68 import android.os.Trace; 69 import android.util.Slog; 70 import android.util.proto.ProtoOutputStream; 71 import android.view.DisplayInfo; 72 import android.view.Surface.OutOfResourcesException; 73 import android.view.SurfaceControl; 74 import android.view.WindowManager; 75 import android.view.WindowManager.LayoutParams; 76 import android.view.animation.Animation; 77 import android.view.animation.AnimationUtils; 78 79 import com.android.server.policy.WindowManagerPolicy; 80 import com.android.server.protolog.common.ProtoLog; 81 82 import java.io.PrintWriter; 83 84 /** 85 * Keep track of animations and surface operations for a single WindowState. 86 **/ 87 class WindowStateAnimator { 88 static final String TAG = TAG_WITH_CLASS_NAME ? "WindowStateAnimator" : TAG_WM; 89 static final int WINDOW_FREEZE_LAYER = TYPE_LAYER_MULTIPLIER * 200; 90 static final int PRESERVED_SURFACE_LAYER = 1; 91 92 /** 93 * Mode how the window gets clipped by the stack bounds during an animation: The clipping should 94 * be applied after applying the animation transformation, i.e. the stack bounds don't move 95 * during the animation. 96 */ 97 static final int STACK_CLIP_AFTER_ANIM = 0; 98 99 /** 100 * Mode how the window gets clipped by the stack bounds: The clipping should be applied before 101 * applying the animation transformation, i.e. the stack bounds move with the window. 102 */ 103 static final int STACK_CLIP_BEFORE_ANIM = 1; 104 105 /** 106 * Mode how window gets clipped by the stack bounds during an animation: Don't clip the window 107 * by the stack bounds. 108 */ 109 static final int STACK_CLIP_NONE = 2; 110 111 // Unchanging local convenience fields. 112 final WindowManagerService mService; 113 final WindowState mWin; 114 final WindowAnimator mAnimator; 115 final Session mSession; 116 final WindowManagerPolicy mPolicy; 117 final Context mContext; 118 final boolean mIsWallpaper; 119 private final WallpaperController mWallpaperControllerLocked; 120 121 boolean mAnimationIsEntrance; 122 123 /** 124 * Set when we have changed the size of the surface, to know that 125 * we must tell them application to resize (and thus redraw itself). 126 */ 127 boolean mSurfaceResized; 128 /** 129 * Whether we should inform the client on next relayoutWindow that 130 * the surface has been resized since last time. 131 */ 132 boolean mReportSurfaceResized; 133 WindowSurfaceController mSurfaceController; 134 private WindowSurfaceController mPendingDestroySurface; 135 136 /** 137 * Set if the client has asked that the destroy of its surface be delayed 138 * until it explicitly says it is okay. 139 */ 140 boolean mSurfaceDestroyDeferred; 141 142 private boolean mDestroyPreservedSurfaceUponRedraw; 143 float mShownAlpha = 0; 144 float mAlpha = 0; 145 float mLastAlpha = 0; 146 147 Rect mTmpClipRect = new Rect(); 148 Rect mLastClipRect = new Rect(); 149 Rect mLastFinalClipRect = new Rect(); 150 Rect mTmpStackBounds = new Rect(); 151 private Rect mTmpAnimatingBounds = new Rect(); 152 private Rect mTmpSourceBounds = new Rect(); 153 154 /** 155 * This is rectangle of the window's surface that is not covered by 156 * system decorations. 157 */ 158 private final Rect mSystemDecorRect = new Rect(); 159 160 float mDsDx=1, mDtDx=0, mDsDy=0, mDtDy=1; 161 private float mLastDsDx=1, mLastDtDx=0, mLastDsDy=0, mLastDtDy=1; 162 163 boolean mHaveMatrix; 164 165 // Set to true if, when the window gets displayed, it should perform 166 // an enter animation. 167 boolean mEnterAnimationPending; 168 169 /** Used to indicate that this window is undergoing an enter animation. Used for system 170 * windows to make the callback to View.dispatchOnWindowShownCallback(). Set when the 171 * window is first added or shown, cleared when the callback has been made. */ 172 boolean mEnteringAnimation; 173 174 private final SurfaceControl.Transaction mTmpTransaction; 175 176 /** The pixel format of the underlying SurfaceControl */ 177 int mSurfaceFormat; 178 179 /** This is set when there is no Surface */ 180 static final int NO_SURFACE = 0; 181 /** This is set after the Surface has been created but before the window has been drawn. During 182 * this time the surface is hidden. */ 183 static final int DRAW_PENDING = 1; 184 /** This is set after the window has finished drawing for the first time but before its surface 185 * is shown. The surface will be displayed when the next layout is run. */ 186 static final int COMMIT_DRAW_PENDING = 2; 187 /** This is set during the time after the window's drawing has been committed, and before its 188 * surface is actually shown. It is used to delay showing the surface until all windows in a 189 * token are ready to be shown. */ 190 static final int READY_TO_SHOW = 3; 191 /** Set when the window has been shown in the screen the first time. */ 192 static final int HAS_DRAWN = 4; 193 drawStateToString()194 String drawStateToString() { 195 switch (mDrawState) { 196 case NO_SURFACE: return "NO_SURFACE"; 197 case DRAW_PENDING: return "DRAW_PENDING"; 198 case COMMIT_DRAW_PENDING: return "COMMIT_DRAW_PENDING"; 199 case READY_TO_SHOW: return "READY_TO_SHOW"; 200 case HAS_DRAWN: return "HAS_DRAWN"; 201 default: return Integer.toString(mDrawState); 202 } 203 } 204 int mDrawState; 205 206 /** Was this window last hidden? */ 207 boolean mLastHidden; 208 209 int mAttrType; 210 211 boolean mForceScaleUntilResize; 212 213 // WindowState.mHScale and WindowState.mVScale contain the 214 // scale according to client specified layout parameters (e.g. 215 // one layout size, with another surface size, creates such scaling). 216 // Here we track an additional scaling factor used to follow stack 217 // scaling (as in the case of the Pinned stack animation). 218 float mExtraHScale = (float) 1.0; 219 float mExtraVScale = (float) 1.0; 220 221 // An offset in pixel of the surface contents from the window position. Used for Wallpaper 222 // to provide the effect of scrolling within a large surface. We just use these values as 223 // a cache. 224 int mXOffset = 0; 225 int mYOffset = 0; 226 227 // A scale factor for the surface contents, that will be applied from the center of the visible 228 // region. 229 float mWallpaperScale = 1f; 230 231 /** 232 * A flag to determine if the WSA needs to offset its position to compensate for the stack's 233 * position update before the WSA surface has resized. 234 */ 235 private boolean mOffsetPositionForStackResize; 236 237 private final Rect mTmpSize = new Rect(); 238 239 /** 240 * Handles surface changes synchronized to after the client has drawn the surface. This 241 * transaction is currently used to reparent the old surface children to the new surface once 242 * the client has completed drawing to the new surface. 243 * This transaction is also used to merge transactions parceled in by the client. The client 244 * uses the transaction to update the relative z of its children from the old parent surface 245 * to the new parent surface once window manager reparents its children. 246 */ 247 private final SurfaceControl.Transaction mPostDrawTransaction = 248 new SurfaceControl.Transaction(); 249 250 // Set to true after the first frame of the Pinned stack animation 251 // and reset after the last to ensure we only reset mForceScaleUntilResize 252 // once per animation. 253 boolean mPipAnimationStarted = false; 254 255 private final Point mTmpPos = new Point(); 256 WindowStateAnimator(final WindowState win)257 WindowStateAnimator(final WindowState win) { 258 final WindowManagerService service = win.mWmService; 259 260 mService = service; 261 mTmpTransaction = service.mTransactionFactory.get(); 262 mAnimator = service.mAnimator; 263 mPolicy = service.mPolicy; 264 mContext = service.mContext; 265 266 mWin = win; 267 mSession = win.mSession; 268 mAttrType = win.mAttrs.type; 269 mIsWallpaper = win.mIsWallpaper; 270 mWallpaperControllerLocked = win.getDisplayContent().mWallpaperController; 271 } 272 onAnimationFinished()273 void onAnimationFinished() { 274 // Done animating, clean up. 275 if (DEBUG_ANIM) Slog.v( 276 TAG, "Animation done in " + this + ": exiting=" + mWin.mAnimatingExit 277 + ", reportedVisible=" 278 + (mWin.mActivityRecord != null ? mWin.mActivityRecord.reportedVisible : false)); 279 280 mWin.checkPolicyVisibilityChange(); 281 final DisplayContent displayContent = mWin.getDisplayContent(); 282 if ((mAttrType == LayoutParams.TYPE_STATUS_BAR 283 || mAttrType == LayoutParams.TYPE_NOTIFICATION_SHADE) && mWin.isVisibleByPolicy()) { 284 // Upon completion of a not-visible to visible status bar animation a relayout is 285 // required. 286 displayContent.setLayoutNeeded(); 287 } 288 mWin.onExitAnimationDone(); 289 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM; 290 if (displayContent.mWallpaperController.isWallpaperTarget(mWin)) { 291 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 292 } 293 if (DEBUG_LAYOUT_REPEATS) { 294 mService.mWindowPlacerLocked.debugLayoutRepeats( 295 "WindowStateAnimator", displayContent.pendingLayoutChanges); 296 } 297 298 if (mWin.mActivityRecord != null) { 299 mWin.mActivityRecord.updateReportedVisibilityLocked(); 300 } 301 } 302 hide(SurfaceControl.Transaction transaction, String reason)303 void hide(SurfaceControl.Transaction transaction, String reason) { 304 if (!mLastHidden) { 305 //dump(); 306 mLastHidden = true; 307 308 // We may have a preserved surface which we no longer need. If there was a quick 309 // VISIBLE, GONE, VISIBLE, GONE sequence, the surface may never draw, so we don't mark 310 // it to be destroyed in prepareSurfaceLocked. 311 markPreservedSurfaceForDestroy(); 312 313 if (mSurfaceController != null) { 314 mSurfaceController.hide(transaction, reason); 315 } 316 } 317 } 318 hide(String reason)319 void hide(String reason) { 320 hide(mTmpTransaction, reason); 321 SurfaceControl.mergeToGlobalTransaction(mTmpTransaction); 322 } 323 finishDrawingLocked(SurfaceControl.Transaction postDrawTransaction)324 boolean finishDrawingLocked(SurfaceControl.Transaction postDrawTransaction) { 325 final boolean startingWindow = 326 mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; 327 if (startingWindow) { 328 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Finishing drawing window %s: mDrawState=%s", 329 mWin, drawStateToString()); 330 } 331 332 boolean layoutNeeded = false; 333 334 if (mDrawState == DRAW_PENDING) { 335 ProtoLog.v(WM_DEBUG_DRAW, 336 "finishDrawingLocked: mDrawState=COMMIT_DRAW_PENDING %s in %s", mWin, 337 mSurfaceController); 338 if (startingWindow) { 339 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Draw state now committed in %s", mWin); 340 } 341 mDrawState = COMMIT_DRAW_PENDING; 342 layoutNeeded = true; 343 344 if (postDrawTransaction != null) { 345 mPostDrawTransaction.merge(postDrawTransaction); 346 } 347 } else if (postDrawTransaction != null) { 348 // If draw state is not pending we may delay applying this transaction from the client, 349 // so apply it now. 350 postDrawTransaction.apply(); 351 } 352 353 return layoutNeeded; 354 } 355 356 // This must be called while inside a transaction. commitFinishDrawingLocked()357 boolean commitFinishDrawingLocked() { 358 if (DEBUG_STARTING_WINDOW_VERBOSE && 359 mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) { 360 Slog.i(TAG, "commitFinishDrawingLocked: " + mWin + " cur mDrawState=" 361 + drawStateToString()); 362 } 363 if (mDrawState != COMMIT_DRAW_PENDING && mDrawState != READY_TO_SHOW) { 364 return false; 365 } 366 if (DEBUG_ANIM) { 367 Slog.i(TAG, "commitFinishDrawingLocked: mDrawState=READY_TO_SHOW " + mSurfaceController); 368 } 369 mDrawState = READY_TO_SHOW; 370 boolean result = false; 371 final ActivityRecord activity = mWin.mActivityRecord; 372 if (activity == null || activity.canShowWindows() 373 || mWin.mAttrs.type == TYPE_APPLICATION_STARTING) { 374 result = mWin.performShowLocked(); 375 } 376 return result; 377 } 378 preserveSurfaceLocked()379 void preserveSurfaceLocked() { 380 if (mDestroyPreservedSurfaceUponRedraw) { 381 // This could happen when switching the surface mode very fast. For example, 382 // we preserved a surface when dragResizing changed to true. Then before the 383 // preserved surface is removed, dragResizing changed to false again. 384 // In this case, we need to leave the preserved surface alone, and destroy 385 // the actual surface, so that the createSurface call could create a surface 386 // of the proper size. The preserved surface will still be removed when client 387 // finishes drawing to the new surface. 388 mSurfaceDestroyDeferred = false; 389 390 // Make sure to reparent any children of the new surface back to the preserved 391 // surface before destroying it. 392 if (mSurfaceController != null && mPendingDestroySurface != null) { 393 mPostDrawTransaction.reparentChildren( 394 mSurfaceController.getClientViewRootSurface(), 395 mPendingDestroySurface.mSurfaceControl).apply(); 396 } 397 destroySurfaceLocked(); 398 mSurfaceDestroyDeferred = true; 399 return; 400 } 401 ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE SET FREEZE LAYER: %s", mWin); 402 if (mSurfaceController != null) { 403 // Our SurfaceControl is always at layer 0 within the parent Surface managed by 404 // window-state. We want this old Surface to stay on top of the new one 405 // until we do the swap, so we place it at a positive layer. 406 mSurfaceController.mSurfaceControl.setLayer(PRESERVED_SURFACE_LAYER); 407 } 408 mDestroyPreservedSurfaceUponRedraw = true; 409 mSurfaceDestroyDeferred = true; 410 destroySurfaceLocked(); 411 } 412 destroyPreservedSurfaceLocked()413 void destroyPreservedSurfaceLocked() { 414 if (!mDestroyPreservedSurfaceUponRedraw) { 415 return; 416 } 417 418 // If we are preserving a surface but we aren't relaunching that means 419 // we are just doing an in-place switch. In that case any SurfaceFlinger side 420 // child layers need to be reparented to the new surface to make this 421 // transparent to the app. 422 // If the children are detached, we don't want to reparent them to the new surface. 423 // Instead let the children get removed when the old surface is deleted. 424 if (mSurfaceController != null && mPendingDestroySurface != null 425 && !mPendingDestroySurface.mChildrenDetached 426 && (mWin.mActivityRecord == null || !mWin.mActivityRecord.isRelaunching())) { 427 mPostDrawTransaction.reparentChildren( 428 mPendingDestroySurface.getClientViewRootSurface(), 429 mSurfaceController.mSurfaceControl).apply(); 430 } 431 432 destroyDeferredSurfaceLocked(); 433 mDestroyPreservedSurfaceUponRedraw = false; 434 } 435 markPreservedSurfaceForDestroy()436 private void markPreservedSurfaceForDestroy() { 437 if (mDestroyPreservedSurfaceUponRedraw 438 && !mService.mDestroyPreservedSurface.contains(mWin)) { 439 mService.mDestroyPreservedSurface.add(mWin); 440 } 441 } 442 resetDrawState()443 void resetDrawState() { 444 mDrawState = DRAW_PENDING; 445 446 if (mWin.mActivityRecord == null) { 447 return; 448 } 449 450 if (!mWin.mActivityRecord.isAnimating(TRANSITION)) { 451 mWin.mActivityRecord.clearAllDrawn(); 452 } 453 } 454 createSurfaceLocked(int windowType, int ownerUid)455 WindowSurfaceController createSurfaceLocked(int windowType, int ownerUid) { 456 final WindowState w = mWin; 457 458 if (mSurfaceController != null) { 459 return mSurfaceController; 460 } 461 462 if ((mWin.mAttrs.privateFlags & PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY) != 0) { 463 windowType = SurfaceControl.WINDOW_TYPE_DONT_SCREENSHOT; 464 } 465 466 w.setHasSurface(false); 467 468 if (DEBUG_ANIM) { 469 Slog.i(TAG, "createSurface " + this + ": mDrawState=DRAW_PENDING"); 470 } 471 472 resetDrawState(); 473 474 mService.makeWindowFreezingScreenIfNeededLocked(w); 475 476 int flags = SurfaceControl.HIDDEN; 477 final WindowManager.LayoutParams attrs = w.mAttrs; 478 479 if (w.isSecureLocked()) { 480 flags |= SurfaceControl.SECURE; 481 } 482 483 calculateSurfaceBounds(w, attrs, mTmpSize); 484 final int width = mTmpSize.width(); 485 final int height = mTmpSize.height(); 486 487 if (DEBUG_VISIBILITY) { 488 Slog.v(TAG, "Creating surface in session " 489 + mSession.mSurfaceSession + " window " + this 490 + " w=" + width + " h=" + height 491 + " x=" + mTmpSize.left + " y=" + mTmpSize.top 492 + " format=" + attrs.format + " flags=" + flags); 493 } 494 495 // We may abort, so initialize to defaults. 496 mLastClipRect.set(0, 0, 0, 0); 497 498 // Set up surface control with initial size. 499 try { 500 501 final boolean isHwAccelerated = (attrs.flags & FLAG_HARDWARE_ACCELERATED) != 0; 502 final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format; 503 if (!PixelFormat.formatHasAlpha(attrs.format) 504 // Don't make surface with surfaceInsets opaque as they display a 505 // translucent shadow. 506 && attrs.surfaceInsets.left == 0 507 && attrs.surfaceInsets.top == 0 508 && attrs.surfaceInsets.right == 0 509 && attrs.surfaceInsets.bottom == 0 510 // Don't make surface opaque when resizing to reduce the amount of 511 // artifacts shown in areas the app isn't drawing content to. 512 && !w.isDragResizing()) { 513 flags |= SurfaceControl.OPAQUE; 514 } 515 516 mSurfaceController = new WindowSurfaceController(attrs.getTitle().toString(), width, 517 height, format, flags, this, windowType, ownerUid); 518 mSurfaceController.setColorSpaceAgnostic((attrs.privateFlags 519 & WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC) != 0); 520 521 setOffsetPositionForStackResize(false); 522 mSurfaceFormat = format; 523 524 w.setHasSurface(true); 525 526 ProtoLog.i(WM_SHOW_SURFACE_ALLOC, 527 " CREATE SURFACE %s IN SESSION %s: pid=%d format=%d flags=0x%x / %s", 528 mSurfaceController, mSession.mSurfaceSession, mSession.mPid, attrs.format, 529 flags, this); 530 } catch (OutOfResourcesException e) { 531 Slog.w(TAG, "OutOfResourcesException creating surface"); 532 mService.mRoot.reclaimSomeSurfaceMemory(this, "create", true); 533 mDrawState = NO_SURFACE; 534 return null; 535 } catch (Exception e) { 536 Slog.e(TAG, "Exception creating surface (parent dead?)", e); 537 mDrawState = NO_SURFACE; 538 return null; 539 } 540 541 if (DEBUG) { 542 Slog.v(TAG, "Got surface: " + mSurfaceController 543 + ", set left=" + w.getFrameLw().left + " top=" + w.getFrameLw().top); 544 } 545 546 if (SHOW_LIGHT_TRANSACTIONS) { 547 Slog.i(TAG, ">>> OPEN TRANSACTION createSurfaceLocked"); 548 WindowManagerService.logSurface(w, "CREATE pos=(" 549 + w.getFrameLw().left + "," + w.getFrameLw().top + ") (" 550 + width + "x" + height + ")" + " HIDE", false); 551 } 552 553 mLastHidden = true; 554 555 if (DEBUG) Slog.v(TAG, "Created surface " + this); 556 return mSurfaceController; 557 } 558 calculateSurfaceBounds(WindowState w, LayoutParams attrs, Rect outSize)559 private void calculateSurfaceBounds(WindowState w, LayoutParams attrs, Rect outSize) { 560 outSize.setEmpty(); 561 if ((attrs.flags & FLAG_SCALED) != 0) { 562 // For a scaled surface, we always want the requested size. 563 outSize.right = w.mRequestedWidth; 564 outSize.bottom = w.mRequestedHeight; 565 } else { 566 // When we're doing a drag-resizing, request a surface that's fullscreen size, 567 // so that we don't need to reallocate during the process. This also prevents 568 // buffer drops due to size mismatch. 569 if (w.isDragResizing()) { 570 final DisplayInfo displayInfo = w.getDisplayInfo(); 571 outSize.right = displayInfo.logicalWidth; 572 outSize.bottom = displayInfo.logicalHeight; 573 } else { 574 w.getCompatFrameSize(outSize); 575 } 576 } 577 578 // Something is wrong and SurfaceFlinger will not like this, try to revert to sane values. 579 // This doesn't necessarily mean that there is an error in the system. The sizes might be 580 // incorrect, because it is before the first layout or draw. 581 if (outSize.width() < 1) { 582 outSize.right = 1; 583 } 584 if (outSize.height() < 1) { 585 outSize.bottom = 1; 586 } 587 588 // Adjust for surface insets. 589 outSize.inset(-attrs.surfaceInsets.left, -attrs.surfaceInsets.top, 590 -attrs.surfaceInsets.right, -attrs.surfaceInsets.bottom); 591 } 592 hasSurface()593 boolean hasSurface() { 594 return mSurfaceController != null && mSurfaceController.hasSurface(); 595 } 596 destroySurfaceLocked()597 void destroySurfaceLocked() { 598 final ActivityRecord activity = mWin.mActivityRecord; 599 if (activity != null) { 600 if (mWin == activity.startingWindow) { 601 activity.startingDisplayed = false; 602 } 603 } 604 605 if (mSurfaceController == null) { 606 return; 607 } 608 609 // When destroying a surface we want to make sure child windows are hidden. If we are 610 // preserving the surface until redraw though we intend to swap it out with another surface 611 // for resizing. In this case the window always remains visible to the user and the child 612 // windows should likewise remain visible. 613 if (!mDestroyPreservedSurfaceUponRedraw) { 614 mWin.mHidden = true; 615 } 616 617 try { 618 if (DEBUG_VISIBILITY) logWithStack(TAG, "Window " + this + " destroying surface " 619 + mSurfaceController + ", session " + mSession); 620 if (mSurfaceDestroyDeferred) { 621 if (mSurfaceController != null && mPendingDestroySurface != mSurfaceController) { 622 if (mPendingDestroySurface != null) { 623 ProtoLog.i(WM_SHOW_SURFACE_ALLOC, "SURFACE DESTROY PENDING: %s. %s", 624 mWin, new RuntimeException().fillInStackTrace()); 625 mPendingDestroySurface.destroyNotInTransaction(); 626 } 627 mPendingDestroySurface = mSurfaceController; 628 } 629 } else { 630 ProtoLog.i(WM_SHOW_SURFACE_ALLOC, "SURFACE DESTROY: %s. %s", 631 mWin, new RuntimeException().fillInStackTrace()); 632 destroySurface(); 633 } 634 // Don't hide wallpaper if we're deferring the surface destroy 635 // because of a surface change. 636 if (!mDestroyPreservedSurfaceUponRedraw) { 637 mWallpaperControllerLocked.hideWallpapers(mWin); 638 } 639 } catch (RuntimeException e) { 640 Slog.w(TAG, "Exception thrown when destroying Window " + this 641 + " surface " + mSurfaceController + " session " + mSession + ": " + e.toString()); 642 } 643 644 // Whether the surface was preserved (and copied to mPendingDestroySurface) or not, it 645 // needs to be cleared to match the WindowState.mHasSurface state. It is also necessary 646 // so it can be recreated successfully in mPendingDestroySurface case. 647 mWin.setHasSurface(false); 648 if (mSurfaceController != null) { 649 mSurfaceController.setShown(false); 650 } 651 mSurfaceController = null; 652 mDrawState = NO_SURFACE; 653 } 654 destroyDeferredSurfaceLocked()655 void destroyDeferredSurfaceLocked() { 656 try { 657 if (mPendingDestroySurface != null) { 658 ProtoLog.i(WM_SHOW_SURFACE_ALLOC, "SURFACE DESTROY PENDING: %s. %s", 659 mWin, new RuntimeException().fillInStackTrace()); 660 mPendingDestroySurface.destroyNotInTransaction(); 661 // Don't hide wallpaper if we're destroying a deferred surface 662 // after a surface mode change. 663 if (!mDestroyPreservedSurfaceUponRedraw) { 664 mWallpaperControllerLocked.hideWallpapers(mWin); 665 } 666 } 667 } catch (RuntimeException e) { 668 Slog.w(TAG, "Exception thrown when destroying Window " 669 + this + " surface " + mPendingDestroySurface 670 + " session " + mSession + ": " + e.toString()); 671 } 672 mSurfaceDestroyDeferred = false; 673 mPendingDestroySurface = null; 674 } 675 computeShownFrameLocked()676 void computeShownFrameLocked() { 677 final ScreenRotationAnimation screenRotationAnimation = 678 mWin.getDisplayContent().getRotationAnimation(); 679 final boolean windowParticipatesInScreenRotationAnimation = 680 !mWin.mForceSeamlesslyRotate; 681 final boolean screenAnimation = screenRotationAnimation != null 682 && screenRotationAnimation.isAnimating() 683 && windowParticipatesInScreenRotationAnimation; 684 685 if (screenAnimation) { 686 // cache often used attributes locally 687 final Rect frame = mWin.getFrameLw(); 688 final float tmpFloats[] = mService.mTmpFloats; 689 final Matrix tmpMatrix = mWin.mTmpMatrix; 690 691 // Compute the desired transformation. 692 if (screenRotationAnimation.isRotating()) { 693 // If we are doing a screen animation, the global rotation 694 // applied to windows can result in windows that are carefully 695 // aligned with each other to slightly separate, allowing you 696 // to see what is behind them. An unsightly mess. This... 697 // thing... magically makes it call good: scale each window 698 // slightly (two pixels larger in each dimension, from the 699 // window's center). 700 final float w = frame.width(); 701 final float h = frame.height(); 702 if (w>=1 && h>=1) { 703 tmpMatrix.setScale(1 + 2/w, 1 + 2/h, w/2, h/2); 704 } else { 705 tmpMatrix.reset(); 706 } 707 } else { 708 tmpMatrix.reset(); 709 } 710 711 tmpMatrix.postScale(mWin.mGlobalScale, mWin.mGlobalScale); 712 713 // WindowState.prepareSurfaces expands for surface insets (in order they don't get 714 // clipped by the WindowState surface), so we need to go into the other direction here. 715 tmpMatrix.postTranslate(mWin.mAttrs.surfaceInsets.left, 716 mWin.mAttrs.surfaceInsets.top); 717 718 719 // "convert" it into SurfaceFlinger's format 720 // (a 2x2 matrix + an offset) 721 // Here we must not transform the position of the surface 722 // since it is already included in the transformation. 723 //Slog.i(TAG_WM, "Transform: " + matrix); 724 725 mHaveMatrix = true; 726 tmpMatrix.getValues(tmpFloats); 727 mDsDx = tmpFloats[Matrix.MSCALE_X]; 728 mDtDx = tmpFloats[Matrix.MSKEW_Y]; 729 mDtDy = tmpFloats[Matrix.MSKEW_X]; 730 mDsDy = tmpFloats[Matrix.MSCALE_Y]; 731 732 // Now set the alpha... but because our current hardware 733 // can't do alpha transformation on a non-opaque surface, 734 // turn it off if we are running an animation that is also 735 // transforming since it is more important to have that 736 // animation be smooth. 737 mShownAlpha = mAlpha; 738 if (!mService.mLimitedAlphaCompositing 739 || (!PixelFormat.formatHasAlpha(mWin.mAttrs.format) 740 || (mWin.isIdentityMatrix(mDsDx, mDtDx, mDtDy, mDsDy)))) { 741 mShownAlpha *= screenRotationAnimation.getEnterTransformation().getAlpha(); 742 } 743 744 if ((DEBUG_ANIM || DEBUG) && (mShownAlpha == 1.0 || mShownAlpha == 0.0)) { 745 Slog.v(TAG, "computeShownFrameLocked: Animating " + this + " mAlpha=" + mAlpha 746 + " screen=" + (screenAnimation 747 ? screenRotationAnimation.getEnterTransformation().getAlpha() : "null")); 748 } 749 return; 750 } else if (mIsWallpaper && mService.mRoot.mWallpaperActionPending) { 751 return; 752 } else if (mWin.isDragResizeChanged()) { 753 // This window is awaiting a relayout because user just started (or ended) 754 // drag-resizing. The shown frame (which affects surface size and pos) 755 // should not be updated until we get next finished draw with the new surface. 756 // Otherwise one or two frames rendered with old settings would be displayed 757 // with new geometry. 758 return; 759 } 760 761 if (DEBUG) { 762 Slog.v(TAG, "computeShownFrameLocked: " + this 763 + " not attached, mAlpha=" + mAlpha); 764 } 765 766 mShownAlpha = mAlpha; 767 mHaveMatrix = false; 768 mDsDx = mWin.mGlobalScale; 769 mDtDx = 0; 770 mDtDy = 0; 771 mDsDy = mWin.mGlobalScale; 772 } 773 774 /** 775 * Calculate the window-space crop rect and fill clipRect. 776 * @return true if clipRect has been filled otherwise, no window space crop should be applied. 777 */ calculateCrop(Rect clipRect)778 private boolean calculateCrop(Rect clipRect) { 779 final WindowState w = mWin; 780 final DisplayContent displayContent = w.getDisplayContent(); 781 clipRect.setEmpty(); 782 783 if (displayContent == null) { 784 return false; 785 } 786 787 if (w.getWindowConfiguration().tasksAreFloating() 788 || WindowConfiguration.isSplitScreenWindowingMode(w.getWindowingMode())) { 789 return false; 790 } 791 792 // During forced seamless rotation, the surface bounds get updated with the crop in the 793 // new rotation, which is not compatible with showing the surface in the old rotation. 794 // To work around that we disable cropping for such windows, as it is not necessary anyways. 795 if (w.mForceSeamlesslyRotate) { 796 return false; 797 } 798 799 // If we're animating, the wallpaper should only 800 // be updated at the end of the animation. 801 if (w.mAttrs.type == TYPE_WALLPAPER) { 802 return false; 803 } 804 805 if (DEBUG_WINDOW_CROP) Slog.d(TAG, 806 "Updating crop win=" + w + " mLastCrop=" + mLastClipRect); 807 808 w.calculatePolicyCrop(mSystemDecorRect); 809 810 if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Applying decor to crop win=" + w + " mDecorFrame=" 811 + w.getDecorFrame() + " mSystemDecorRect=" + mSystemDecorRect); 812 813 // We use the clip rect as provided by the tranformation for non-fullscreen windows to 814 // avoid premature clipping with the system decor rect. 815 clipRect.set(mSystemDecorRect); 816 if (DEBUG_WINDOW_CROP) Slog.d(TAG, "win=" + w + " Initial clip rect: " + clipRect); 817 818 w.expandForSurfaceInsets(clipRect); 819 820 // The clip rect was generated assuming (0,0) as the window origin, 821 // so we need to translate to match the actual surface coordinates. 822 clipRect.offset(w.mAttrs.surfaceInsets.left, w.mAttrs.surfaceInsets.top); 823 824 if (DEBUG_WINDOW_CROP) Slog.d(TAG, 825 "win=" + w + " Clip rect after stack adjustment=" + clipRect); 826 827 w.transformClipRectFromScreenToSurfaceSpace(clipRect); 828 829 return true; 830 } 831 applyCrop(Rect clipRect, boolean recoveringMemory)832 private void applyCrop(Rect clipRect, boolean recoveringMemory) { 833 if (DEBUG_WINDOW_CROP) Slog.d(TAG, "applyCrop: win=" + mWin 834 + " clipRect=" + clipRect); 835 if (clipRect != null) { 836 if (!clipRect.equals(mLastClipRect)) { 837 mLastClipRect.set(clipRect); 838 mSurfaceController.setCropInTransaction(clipRect, recoveringMemory); 839 } 840 } else { 841 mSurfaceController.clearCropInTransaction(recoveringMemory); 842 } 843 } 844 shouldConsumeMainWindowSizeTransaction()845 private boolean shouldConsumeMainWindowSizeTransaction() { 846 // We only consume the transaction when the client is calling relayout 847 // because this is the only time we know the frameNumber will be valid 848 // due to the client renderer being paused. Put otherwise, only when 849 // mInRelayout is true can we guarantee the next frame will contain 850 // the most recent configuration. 851 if (!mWin.mInRelayout) return false; 852 // Since we can only do this for one window, we focus on the main application window 853 if (mAttrType != TYPE_BASE_APPLICATION) return false; 854 final Task task = mWin.getTask(); 855 if (task == null) return false; 856 if (task.getMainWindowSizeChangeTransaction() == null) return false; 857 // Likewise we only focus on the task root, since we can only use one window 858 if (!mWin.mActivityRecord.isRootOfTask()) return false; 859 return true; 860 } 861 setSurfaceBoundariesLocked(final boolean recoveringMemory)862 void setSurfaceBoundariesLocked(final boolean recoveringMemory) { 863 if (mSurfaceController == null) { 864 return; 865 } 866 867 final WindowState w = mWin; 868 final LayoutParams attrs = mWin.getAttrs(); 869 final Task task = w.getTask(); 870 871 calculateSurfaceBounds(w, attrs, mTmpSize); 872 873 mExtraHScale = (float) 1.0; 874 mExtraVScale = (float) 1.0; 875 876 boolean wasForceScaled = mForceScaleUntilResize; 877 878 // Once relayout has been called at least once, we need to make sure 879 // we only resize the client surface during calls to relayout. For 880 // clients which use indeterminate measure specs (MATCH_PARENT), 881 // we may try and change their window size without a call to relayout. 882 // However, this would be unsafe, as the client may be in the middle 883 // of producing a frame at the old size, having just completed layout 884 // to find the surface size changed underneath it. 885 final boolean relayout = !w.mRelayoutCalled || w.mInRelayout; 886 if (relayout) { 887 mSurfaceResized = mSurfaceController.setBufferSizeInTransaction( 888 mTmpSize.width(), mTmpSize.height(), recoveringMemory); 889 } else { 890 mSurfaceResized = false; 891 } 892 mForceScaleUntilResize = mForceScaleUntilResize && !mSurfaceResized; 893 // If we are undergoing seamless rotation, the surface has already 894 // been set up to persist at it's old location. We need to freeze 895 // updates until a resize occurs. 896 897 Rect clipRect = null; 898 if (calculateCrop(mTmpClipRect)) { 899 clipRect = mTmpClipRect; 900 } 901 902 if (shouldConsumeMainWindowSizeTransaction()) { 903 task.getMainWindowSizeChangeTask().getSurfaceControl().deferTransactionUntil( 904 mWin.getClientViewRootSurface(), mWin.getFrameNumber()); 905 mSurfaceController.deferTransactionUntil(mWin.getClientViewRootSurface(), 906 mWin.getFrameNumber()); 907 SurfaceControl.mergeToGlobalTransaction(task.getMainWindowSizeChangeTransaction()); 908 task.setMainWindowSizeChangeTransaction(null); 909 } 910 911 float surfaceWidth = mSurfaceController.getWidth(); 912 float surfaceHeight = mSurfaceController.getHeight(); 913 914 final Rect insets = attrs.surfaceInsets; 915 916 if (isForceScaled()) { 917 int hInsets = insets.left + insets.right; 918 int vInsets = insets.top + insets.bottom; 919 float surfaceContentWidth = surfaceWidth - hInsets; 920 float surfaceContentHeight = surfaceHeight - vInsets; 921 if (!mForceScaleUntilResize) { 922 mSurfaceController.forceScaleableInTransaction(true); 923 } 924 925 int posX = 0; 926 int posY = 0; 927 task.getStack().getDimBounds(mTmpStackBounds); 928 929 boolean allowStretching = false; 930 task.getStack().getFinalAnimationSourceHintBounds(mTmpSourceBounds); 931 // If we don't have source bounds, we can attempt to use the content insets 932 // if we have content insets. 933 if (mTmpSourceBounds.isEmpty() && (mWin.mLastRelayoutContentInsets.width() > 0 934 || mWin.mLastRelayoutContentInsets.height() > 0)) { 935 mTmpSourceBounds.set(task.getStack().mPreAnimationBounds); 936 mTmpSourceBounds.inset(mWin.mLastRelayoutContentInsets); 937 allowStretching = true; 938 } 939 940 // Make sure that what we're animating to and from is actually the right size in case 941 // the window cannot take up the full screen. 942 mTmpStackBounds.intersectUnchecked(w.getParentFrame()); 943 mTmpSourceBounds.intersectUnchecked(w.getParentFrame()); 944 mTmpAnimatingBounds.intersectUnchecked(w.getParentFrame()); 945 946 if (!mTmpSourceBounds.isEmpty()) { 947 // Get the final target stack bounds, if we are not animating, this is just the 948 // current stack bounds 949 task.getStack().getFinalAnimationBounds(mTmpAnimatingBounds); 950 951 // Calculate the current progress and interpolate the difference between the target 952 // and source bounds 953 float finalWidth = mTmpAnimatingBounds.width(); 954 float initialWidth = mTmpSourceBounds.width(); 955 float tw = (surfaceContentWidth - mTmpStackBounds.width()) 956 / (surfaceContentWidth - mTmpAnimatingBounds.width()); 957 float th = tw; 958 mExtraHScale = (initialWidth + tw * (finalWidth - initialWidth)) / initialWidth; 959 if (allowStretching) { 960 float finalHeight = mTmpAnimatingBounds.height(); 961 float initialHeight = mTmpSourceBounds.height(); 962 th = (surfaceContentHeight - mTmpStackBounds.height()) 963 / (surfaceContentHeight - mTmpAnimatingBounds.height()); 964 mExtraVScale = (initialHeight + tw * (finalHeight - initialHeight)) 965 / initialHeight; 966 } else { 967 mExtraVScale = mExtraHScale; 968 } 969 970 // Adjust the position to account for the inset bounds 971 posX -= (int) (tw * mExtraHScale * mTmpSourceBounds.left); 972 posY -= (int) (th * mExtraVScale * mTmpSourceBounds.top); 973 974 // In pinned mode the clip rectangle applied to us by our stack has been 975 // expanded outwards to allow for shadows. However in case of source bounds set 976 // we need to crop to within the surface. The code above has scaled and positioned 977 // the surface to fit the unexpanded stack bounds, but now we need to reapply 978 // the cropping that the stack would have applied if it weren't expanded. This 979 // can be different in each direction based on the source bounds. 980 clipRect = mTmpClipRect; 981 clipRect.set((int)((insets.left + mTmpSourceBounds.left) * tw), 982 (int)((insets.top + mTmpSourceBounds.top) * th), 983 insets.left + (int)(surfaceWidth 984 - (tw* (surfaceWidth - mTmpSourceBounds.right))), 985 insets.top + (int)(surfaceHeight 986 - (th * (surfaceHeight - mTmpSourceBounds.bottom)))); 987 } else { 988 // We want to calculate the scaling based on the content area, not based on 989 // the entire surface, so that we scale in sync with windows that don't have insets. 990 mExtraHScale = mTmpStackBounds.width() / surfaceContentWidth; 991 mExtraVScale = mTmpStackBounds.height() / surfaceContentHeight; 992 993 // Since we are scaled to fit in our previously desired crop, we can now 994 // expose the whole window in buffer space, and not risk extending 995 // past where the system would have cropped us 996 clipRect = null; 997 } 998 999 // In the case of ForceScaleToStack we scale entire tasks together, 1000 // and so we need to scale our offsets relative to the task bounds 1001 // or parent and child windows would fall out of alignment. 1002 posX -= (int) (attrs.x * (1 - mExtraHScale)); 1003 posY -= (int) (attrs.y * (1 - mExtraVScale)); 1004 1005 // Imagine we are scaling down. As we scale the buffer down, we decrease the 1006 // distance between the surface top left, and the start of the surface contents 1007 // (previously it was surfaceInsets.left pixels in screen space but now it 1008 // will be surfaceInsets.left*mExtraHScale). This means in order to keep the 1009 // non inset content at the same position, we have to shift the whole window 1010 // forward. Likewise for scaling up, we've increased this distance, and we need 1011 // to shift by a negative number to compensate. 1012 posX += insets.left * (1 - mExtraHScale); 1013 posY += insets.top * (1 - mExtraVScale); 1014 1015 mSurfaceController.setPositionInTransaction((float) Math.floor(posX), 1016 (float) Math.floor(posY), recoveringMemory); 1017 1018 // Various surfaces in the scaled stack may resize at different times. 1019 // We need to ensure for each surface, that we disable transformation matrix 1020 // scaling in the same transaction which we resize the surface in. 1021 // As we are in SCALING_MODE_SCALE_TO_WINDOW, SurfaceFlinger will 1022 // then take over the scaling until the new buffer arrives, and things 1023 // will be seamless. 1024 if (mPipAnimationStarted == false) { 1025 mForceScaleUntilResize = true; 1026 mPipAnimationStarted = true; 1027 } 1028 } else { 1029 mPipAnimationStarted = false; 1030 1031 if (!w.mSeamlesslyRotated) { 1032 // Used to offset the WSA when stack position changes before a resize. 1033 int xOffset = mXOffset; 1034 int yOffset = mYOffset; 1035 if (mOffsetPositionForStackResize) { 1036 if (relayout) { 1037 // Once a relayout is called, reset the offset back to 0 and defer 1038 // setting it until a new frame with the updated size. This ensures that 1039 // the WS position is reset (so the stack position is shown) at the same 1040 // time that the buffer size changes. 1041 setOffsetPositionForStackResize(false); 1042 mSurfaceController.deferTransactionUntil(mWin.getClientViewRootSurface(), 1043 mWin.getFrameNumber()); 1044 } else { 1045 final ActivityStack stack = mWin.getRootTask(); 1046 mTmpPos.x = 0; 1047 mTmpPos.y = 0; 1048 if (stack != null) { 1049 stack.getRelativePosition(mTmpPos); 1050 } 1051 1052 xOffset = -mTmpPos.x; 1053 yOffset = -mTmpPos.y; 1054 1055 // Crop also needs to be extended so the bottom isn't cut off when the WSA 1056 // position is moved. 1057 if (clipRect != null) { 1058 clipRect.right += mTmpPos.x; 1059 clipRect.bottom += mTmpPos.y; 1060 } 1061 } 1062 } 1063 if (!mIsWallpaper) { 1064 mSurfaceController.setPositionInTransaction(xOffset, yOffset, recoveringMemory); 1065 } else { 1066 setWallpaperPositionAndScale( 1067 xOffset, yOffset, mWallpaperScale, recoveringMemory); 1068 } 1069 } 1070 } 1071 1072 // If we are ending the scaling mode. We switch to SCALING_MODE_FREEZE 1073 // to prevent further updates until buffer latch. 1074 // We also need to freeze the Surface geometry until a buffer 1075 // comes in at the new size (normally position and crop are unfrozen). 1076 // deferTransactionUntil accomplishes this for us. 1077 if (wasForceScaled && !mForceScaleUntilResize) { 1078 mSurfaceController.deferTransactionUntil(mWin.getClientViewRootSurface(), 1079 mWin.getFrameNumber()); 1080 mSurfaceController.forceScaleableInTransaction(false); 1081 } 1082 1083 1084 if (!w.mSeamlesslyRotated) { 1085 // Wallpaper is already updated above when calling setWallpaperPositionAndScale so 1086 // we only need to consider the non-wallpaper case here. 1087 if (!mIsWallpaper) { 1088 applyCrop(clipRect, recoveringMemory); 1089 mSurfaceController.setMatrixInTransaction( 1090 mDsDx * w.mHScale * mExtraHScale, 1091 mDtDx * w.mVScale * mExtraVScale, 1092 mDtDy * w.mHScale * mExtraHScale, 1093 mDsDy * w.mVScale * mExtraVScale, recoveringMemory); 1094 } 1095 } 1096 1097 if (mSurfaceResized) { 1098 mReportSurfaceResized = true; 1099 mWin.getDisplayContent().pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 1100 } 1101 } 1102 1103 /** 1104 * Get rect of the task this window is currently in. If there is no task, rect will be set to 1105 * empty. 1106 */ getContainerRect(Rect rect)1107 void getContainerRect(Rect rect) { 1108 final Task task = mWin.getTask(); 1109 if (task != null) { 1110 task.getDimBounds(rect); 1111 } else { 1112 rect.left = rect.top = rect.right = rect.bottom = 0; 1113 } 1114 } 1115 prepareSurfaceLocked(final boolean recoveringMemory)1116 void prepareSurfaceLocked(final boolean recoveringMemory) { 1117 final WindowState w = mWin; 1118 if (!hasSurface()) { 1119 1120 // There is no need to wait for an animation change if our window is gone for layout 1121 // already as we'll never be visible. 1122 if (w.getOrientationChanging() && w.isGoneForLayoutLw()) { 1123 ProtoLog.v(WM_DEBUG_ORIENTATION, "Orientation change skips hidden %s", w); 1124 w.setOrientationChanging(false); 1125 } 1126 return; 1127 } 1128 1129 boolean displayed = false; 1130 1131 computeShownFrameLocked(); 1132 1133 setSurfaceBoundariesLocked(recoveringMemory); 1134 1135 if (mIsWallpaper && !w.mWallpaperVisible) { 1136 // Wallpaper is no longer visible and there is no wp target => hide it. 1137 hide("prepareSurfaceLocked"); 1138 } else if (w.isParentWindowHidden() || !w.isOnScreen()) { 1139 hide("prepareSurfaceLocked"); 1140 mWallpaperControllerLocked.hideWallpapers(w); 1141 1142 // If we are waiting for this window to handle an orientation change. If this window is 1143 // really hidden (gone for layout), there is no point in still waiting for it. 1144 // Note that this does introduce a potential glitch if the window becomes unhidden 1145 // before it has drawn for the new orientation. 1146 if (w.getOrientationChanging() && w.isGoneForLayoutLw()) { 1147 w.setOrientationChanging(false); 1148 ProtoLog.v(WM_DEBUG_ORIENTATION, 1149 "Orientation change skips hidden %s", w); 1150 } 1151 } else if (mLastAlpha != mShownAlpha 1152 || mLastDsDx != mDsDx 1153 || mLastDtDx != mDtDx 1154 || mLastDsDy != mDsDy 1155 || mLastDtDy != mDtDy 1156 || w.mLastHScale != w.mHScale 1157 || w.mLastVScale != w.mVScale 1158 || mLastHidden) { 1159 displayed = true; 1160 mLastAlpha = mShownAlpha; 1161 mLastDsDx = mDsDx; 1162 mLastDtDx = mDtDx; 1163 mLastDsDy = mDsDy; 1164 mLastDtDy = mDtDy; 1165 w.mLastHScale = w.mHScale; 1166 w.mLastVScale = w.mVScale; 1167 ProtoLog.i(WM_SHOW_TRANSACTIONS, 1168 "SURFACE controller=%s alpha=%f matrix=[%f*%f,%f*%f][%f*%f,%f*%f]: %s", 1169 mSurfaceController, mShownAlpha, mDsDx, w.mHScale, mDtDx, w.mVScale, 1170 mDtDy, w.mHScale, mDsDy, w.mVScale, w); 1171 1172 boolean prepared = true; 1173 1174 if (mIsWallpaper) { 1175 setWallpaperPositionAndScale( 1176 mXOffset, mYOffset, mWallpaperScale, recoveringMemory); 1177 } else { 1178 prepared = 1179 mSurfaceController.prepareToShowInTransaction(mShownAlpha, 1180 mDsDx * w.mHScale * mExtraHScale, 1181 mDtDx * w.mVScale * mExtraVScale, 1182 mDtDy * w.mHScale * mExtraHScale, 1183 mDsDy * w.mVScale * mExtraVScale, 1184 recoveringMemory); 1185 } 1186 1187 if (prepared && mDrawState == HAS_DRAWN) { 1188 if (mLastHidden) { 1189 if (showSurfaceRobustlyLocked()) { 1190 markPreservedSurfaceForDestroy(); 1191 mAnimator.requestRemovalOfReplacedWindows(w); 1192 mLastHidden = false; 1193 if (mIsWallpaper) { 1194 w.dispatchWallpaperVisibility(true); 1195 } 1196 final DisplayContent displayContent = w.getDisplayContent(); 1197 if (!displayContent.getLastHasContent()) { 1198 // This draw means the difference between unique content and mirroring. 1199 // Run another pass through performLayout to set mHasContent in the 1200 // LogicalDisplay. 1201 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM; 1202 if (DEBUG_LAYOUT_REPEATS) { 1203 mService.mWindowPlacerLocked.debugLayoutRepeats( 1204 "showSurfaceRobustlyLocked " + w, 1205 displayContent.pendingLayoutChanges); 1206 } 1207 } 1208 } else { 1209 w.setOrientationChanging(false); 1210 } 1211 } 1212 } 1213 if (hasSurface()) { 1214 w.mToken.hasVisible = true; 1215 } 1216 } else { 1217 if (DEBUG_ANIM && mWin.isAnimating(TRANSITION | PARENTS)) { 1218 Slog.v(TAG, "prepareSurface: No changes in animation for " + this); 1219 } 1220 displayed = true; 1221 } 1222 1223 if (w.getOrientationChanging()) { 1224 if (!w.isDrawnLw()) { 1225 mAnimator.mBulkUpdateParams &= ~SET_ORIENTATION_CHANGE_COMPLETE; 1226 mAnimator.mLastWindowFreezeSource = w; 1227 ProtoLog.v(WM_DEBUG_ORIENTATION, 1228 "Orientation continue waiting for draw in %s", w); 1229 } else { 1230 w.setOrientationChanging(false); 1231 ProtoLog.v(WM_DEBUG_ORIENTATION, "Orientation change complete in %s", w); 1232 } 1233 } 1234 1235 if (displayed) { 1236 w.mToken.hasVisible = true; 1237 } 1238 } 1239 setTransparentRegionHintLocked(final Region region)1240 void setTransparentRegionHintLocked(final Region region) { 1241 if (mSurfaceController == null) { 1242 Slog.w(TAG, "setTransparentRegionHint: null mSurface after mHasSurface true"); 1243 return; 1244 } 1245 mSurfaceController.setTransparentRegionHint(region); 1246 } 1247 setWallpaperOffset(int dx, int dy, float scale)1248 boolean setWallpaperOffset(int dx, int dy, float scale) { 1249 if (mXOffset == dx && mYOffset == dy && Float.compare(mWallpaperScale, scale) == 0) { 1250 return false; 1251 } 1252 mXOffset = dx; 1253 mYOffset = dy; 1254 mWallpaperScale = scale; 1255 1256 if (mSurfaceController != null) { 1257 try { 1258 if (SHOW_LIGHT_TRANSACTIONS) { 1259 Slog.i(TAG, ">>> OPEN TRANSACTION setWallpaperOffset"); 1260 } 1261 mService.openSurfaceTransaction(); 1262 setWallpaperPositionAndScale(dx, dy, scale, false); 1263 } catch (RuntimeException e) { 1264 Slog.w(TAG, "Error positioning surface of " + mWin 1265 + " pos=(" + dx + "," + dy + ")", e); 1266 } finally { 1267 mService.closeSurfaceTransaction("setWallpaperOffset"); 1268 if (SHOW_LIGHT_TRANSACTIONS) { 1269 Slog.i(TAG, "<<< CLOSE TRANSACTION setWallpaperOffset"); 1270 } 1271 } 1272 } 1273 1274 return true; 1275 } 1276 setWallpaperPositionAndScale(int dx, int dy, float scale, boolean recoveringMemory)1277 private void setWallpaperPositionAndScale(int dx, int dy, float scale, 1278 boolean recoveringMemory) { 1279 DisplayInfo displayInfo = mWin.getDisplayInfo(); 1280 Matrix matrix = mWin.mTmpMatrix; 1281 matrix.setTranslate(dx, dy); 1282 matrix.postScale(scale, scale, displayInfo.logicalWidth / 2f, 1283 displayInfo.logicalHeight / 2f); 1284 matrix.getValues(mWin.mTmpMatrixArray); 1285 matrix.reset(); 1286 1287 mSurfaceController.setPositionInTransaction(mWin.mTmpMatrixArray[MTRANS_X], 1288 mWin.mTmpMatrixArray[MTRANS_Y], recoveringMemory); 1289 mSurfaceController.setMatrixInTransaction( 1290 mDsDx * mWin.mTmpMatrixArray[MSCALE_X] * mWin.mHScale * mExtraHScale, 1291 mDtDx * mWin.mTmpMatrixArray[MSKEW_Y] * mWin.mVScale * mExtraVScale, 1292 mDtDy * mWin.mTmpMatrixArray[MSKEW_X] * mWin.mHScale * mExtraHScale, 1293 mDsDy * mWin.mTmpMatrixArray[MSCALE_Y] * mWin.mVScale * mExtraVScale, 1294 recoveringMemory); 1295 applyCrop(null, recoveringMemory); 1296 } 1297 1298 /** 1299 * Try to change the pixel format without recreating the surface. This 1300 * will be common in the case of changing from PixelFormat.OPAQUE to 1301 * PixelFormat.TRANSLUCENT in the hardware-accelerated case as both 1302 * requested formats resolve to the same underlying SurfaceControl format 1303 * @return True if format was succesfully changed, false otherwise 1304 */ tryChangeFormatInPlaceLocked()1305 boolean tryChangeFormatInPlaceLocked() { 1306 if (mSurfaceController == null) { 1307 return false; 1308 } 1309 final LayoutParams attrs = mWin.getAttrs(); 1310 final boolean isHwAccelerated = (attrs.flags & FLAG_HARDWARE_ACCELERATED) != 0; 1311 final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format; 1312 if (format == mSurfaceFormat) { 1313 setOpaqueLocked(!PixelFormat.formatHasAlpha(attrs.format)); 1314 return true; 1315 } 1316 return false; 1317 } 1318 setOpaqueLocked(boolean isOpaque)1319 void setOpaqueLocked(boolean isOpaque) { 1320 if (mSurfaceController == null) { 1321 return; 1322 } 1323 mSurfaceController.setOpaque(isOpaque); 1324 } 1325 setSecureLocked(boolean isSecure)1326 void setSecureLocked(boolean isSecure) { 1327 if (mSurfaceController == null) { 1328 return; 1329 } 1330 mSurfaceController.setSecure(isSecure); 1331 } 1332 setColorSpaceAgnosticLocked(boolean agnostic)1333 void setColorSpaceAgnosticLocked(boolean agnostic) { 1334 if (mSurfaceController == null) { 1335 return; 1336 } 1337 mSurfaceController.setColorSpaceAgnostic(agnostic); 1338 } 1339 1340 /** 1341 * Have the surface flinger show a surface, robustly dealing with 1342 * error conditions. In particular, if there is not enough memory 1343 * to show the surface, then we will try to get rid of other surfaces 1344 * in order to succeed. 1345 * 1346 * @return Returns true if the surface was successfully shown. 1347 */ showSurfaceRobustlyLocked()1348 private boolean showSurfaceRobustlyLocked() { 1349 if (mWin.getWindowConfiguration().windowsAreScaleable()) { 1350 mSurfaceController.forceScaleableInTransaction(true); 1351 } 1352 1353 boolean shown = mSurfaceController.showRobustlyInTransaction(); 1354 if (!shown) 1355 return false; 1356 1357 // If we had a preserved surface it's no longer needed, and it may be harmful 1358 // if we are transparent. 1359 if (mPendingDestroySurface != null && mDestroyPreservedSurfaceUponRedraw) { 1360 final SurfaceControl pendingSurfaceControl = mPendingDestroySurface.mSurfaceControl; 1361 mPostDrawTransaction.reparent(pendingSurfaceControl, null); 1362 // If the children are detached, we don't want to reparent them to the new surface. 1363 // Instead let the children get removed when the old surface is deleted. 1364 if (!mPendingDestroySurface.mChildrenDetached) { 1365 mPostDrawTransaction.reparentChildren( 1366 mPendingDestroySurface.getClientViewRootSurface(), 1367 mSurfaceController.mSurfaceControl); 1368 } 1369 } 1370 1371 SurfaceControl.mergeToGlobalTransaction(mPostDrawTransaction); 1372 return true; 1373 } 1374 applyEnterAnimationLocked()1375 void applyEnterAnimationLocked() { 1376 // If we are the new part of a window replacement transition and we have requested 1377 // not to animate, we instead want to make it seamless, so we don't want to apply 1378 // an enter transition. 1379 if (mWin.mSkipEnterAnimationForSeamlessReplacement) { 1380 return; 1381 } 1382 1383 final int transit; 1384 if (mEnterAnimationPending) { 1385 mEnterAnimationPending = false; 1386 transit = WindowManagerPolicy.TRANSIT_ENTER; 1387 } else { 1388 transit = WindowManagerPolicy.TRANSIT_SHOW; 1389 } 1390 1391 // We don't apply animation for application main window here since this window type 1392 // should be controlled by AppWindowToken in general. 1393 if (mAttrType != TYPE_BASE_APPLICATION) { 1394 applyAnimationLocked(transit, true); 1395 } 1396 1397 if (mService.mAccessibilityController != null) { 1398 mService.mAccessibilityController.onWindowTransitionLocked(mWin, transit); 1399 } 1400 } 1401 1402 /** 1403 * Choose the correct animation and set it to the passed WindowState. 1404 * @param transit If AppTransition.TRANSIT_PREVIEW_DONE and the app window has been drawn 1405 * then the animation will be app_starting_exit. Any other value loads the animation from 1406 * the switch statement below. 1407 * @param isEntrance The animation type the last time this was called. Used to keep from 1408 * loading the same animation twice. 1409 * @return true if an animation has been loaded. 1410 */ applyAnimationLocked(int transit, boolean isEntrance)1411 boolean applyAnimationLocked(int transit, boolean isEntrance) { 1412 if (mWin.isAnimating() && mAnimationIsEntrance == isEntrance) { 1413 // If we are trying to apply an animation, but already running 1414 // an animation of the same type, then just leave that one alone. 1415 return true; 1416 } 1417 1418 final boolean isImeWindow = mWin.mAttrs.type == TYPE_INPUT_METHOD; 1419 if (isEntrance && isImeWindow) { 1420 mWin.getDisplayContent().adjustForImeIfNeeded(); 1421 mWin.setDisplayLayoutNeeded(); 1422 mService.mWindowPlacerLocked.requestTraversal(); 1423 } 1424 1425 // Only apply an animation if the display isn't frozen. If it is 1426 // frozen, there is no reason to animate and it can cause strange 1427 // artifacts when we unfreeze the display if some different animation 1428 // is running. 1429 if (mWin.mToken.okToAnimate()) { 1430 int anim = mWin.getDisplayContent().getDisplayPolicy().selectAnimation(mWin, transit); 1431 int attr = -1; 1432 Animation a = null; 1433 if (anim != DisplayPolicy.ANIMATION_STYLEABLE) { 1434 if (anim != DisplayPolicy.ANIMATION_NONE) { 1435 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "WSA#loadAnimation"); 1436 a = AnimationUtils.loadAnimation(mContext, anim); 1437 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 1438 } 1439 } else { 1440 switch (transit) { 1441 case WindowManagerPolicy.TRANSIT_ENTER: 1442 attr = com.android.internal.R.styleable.WindowAnimation_windowEnterAnimation; 1443 break; 1444 case WindowManagerPolicy.TRANSIT_EXIT: 1445 attr = com.android.internal.R.styleable.WindowAnimation_windowExitAnimation; 1446 break; 1447 case WindowManagerPolicy.TRANSIT_SHOW: 1448 attr = com.android.internal.R.styleable.WindowAnimation_windowShowAnimation; 1449 break; 1450 case WindowManagerPolicy.TRANSIT_HIDE: 1451 attr = com.android.internal.R.styleable.WindowAnimation_windowHideAnimation; 1452 break; 1453 } 1454 if (attr >= 0) { 1455 a = mWin.getDisplayContent().mAppTransition.loadAnimationAttr( 1456 mWin.mAttrs, attr, TRANSIT_NONE); 1457 } 1458 } 1459 if (DEBUG_ANIM) Slog.v(TAG, 1460 "applyAnimation: win=" + this 1461 + " anim=" + anim + " attr=0x" + Integer.toHexString(attr) 1462 + " a=" + a 1463 + " transit=" + transit 1464 + " type=" + mAttrType 1465 + " isEntrance=" + isEntrance + " Callers " + Debug.getCallers(3)); 1466 if (a != null) { 1467 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this); 1468 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "WSA#startAnimation"); 1469 mWin.startAnimation(a); 1470 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 1471 mAnimationIsEntrance = isEntrance; 1472 } 1473 } else if (!isImeWindow) { 1474 mWin.cancelAnimation(); 1475 } 1476 1477 if (!isEntrance && isImeWindow) { 1478 mWin.getDisplayContent().adjustForImeIfNeeded(); 1479 } 1480 1481 return mWin.isAnimating(PARENTS); 1482 } 1483 dumpDebug(ProtoOutputStream proto, long fieldId)1484 void dumpDebug(ProtoOutputStream proto, long fieldId) { 1485 final long token = proto.start(fieldId); 1486 mLastClipRect.dumpDebug(proto, LAST_CLIP_RECT); 1487 if (mSurfaceController != null) { 1488 mSurfaceController.dumpDebug(proto, SURFACE); 1489 } 1490 proto.write(DRAW_STATE, mDrawState); 1491 mSystemDecorRect.dumpDebug(proto, SYSTEM_DECOR_RECT); 1492 proto.end(token); 1493 } 1494 dump(PrintWriter pw, String prefix, boolean dumpAll)1495 public void dump(PrintWriter pw, String prefix, boolean dumpAll) { 1496 if (mAnimationIsEntrance) { 1497 pw.print(prefix); pw.print(" mAnimationIsEntrance="); pw.print(mAnimationIsEntrance); 1498 } 1499 if (mSurfaceController != null) { 1500 mSurfaceController.dump(pw, prefix, dumpAll); 1501 } 1502 if (dumpAll) { 1503 pw.print(prefix); pw.print("mDrawState="); pw.print(drawStateToString()); 1504 pw.print(prefix); pw.print(" mLastHidden="); pw.println(mLastHidden); 1505 pw.print(prefix); pw.print("mEnterAnimationPending=" + mEnterAnimationPending); 1506 pw.print(prefix); pw.print("mSystemDecorRect="); mSystemDecorRect.printShortString(pw); 1507 pw.print(" mLastClipRect="); mLastClipRect.printShortString(pw); 1508 1509 if (!mLastFinalClipRect.isEmpty()) { 1510 pw.print(" mLastFinalClipRect="); mLastFinalClipRect.printShortString(pw); 1511 } 1512 pw.println(); 1513 } 1514 1515 if (mPendingDestroySurface != null) { 1516 pw.print(prefix); pw.print("mPendingDestroySurface="); 1517 pw.println(mPendingDestroySurface); 1518 } 1519 if (mSurfaceResized || mSurfaceDestroyDeferred) { 1520 pw.print(prefix); pw.print("mSurfaceResized="); pw.print(mSurfaceResized); 1521 pw.print(" mSurfaceDestroyDeferred="); pw.println(mSurfaceDestroyDeferred); 1522 } 1523 if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) { 1524 pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha); 1525 pw.print(" mAlpha="); pw.print(mAlpha); 1526 pw.print(" mLastAlpha="); pw.println(mLastAlpha); 1527 } 1528 if (mHaveMatrix || mWin.mGlobalScale != 1) { 1529 pw.print(prefix); pw.print("mGlobalScale="); pw.print(mWin.mGlobalScale); 1530 pw.print(" mDsDx="); pw.print(mDsDx); 1531 pw.print(" mDtDx="); pw.print(mDtDx); 1532 pw.print(" mDtDy="); pw.print(mDtDy); 1533 pw.print(" mDsDy="); pw.println(mDsDy); 1534 } 1535 } 1536 1537 @Override toString()1538 public String toString() { 1539 StringBuffer sb = new StringBuffer("WindowStateAnimator{"); 1540 sb.append(Integer.toHexString(System.identityHashCode(this))); 1541 sb.append(' '); 1542 sb.append(mWin.mAttrs.getTitle()); 1543 sb.append('}'); 1544 return sb.toString(); 1545 } 1546 reclaimSomeSurfaceMemory(String operation, boolean secure)1547 void reclaimSomeSurfaceMemory(String operation, boolean secure) { 1548 mService.mRoot.reclaimSomeSurfaceMemory(this, operation, secure); 1549 } 1550 getShown()1551 boolean getShown() { 1552 if (mSurfaceController != null) { 1553 return mSurfaceController.getShown(); 1554 } 1555 return false; 1556 } 1557 destroySurface()1558 void destroySurface() { 1559 try { 1560 if (mSurfaceController != null) { 1561 mSurfaceController.destroyNotInTransaction(); 1562 } 1563 } catch (RuntimeException e) { 1564 Slog.w(TAG, "Exception thrown when destroying surface " + this 1565 + " surface " + mSurfaceController + " session " + mSession + ": " + e); 1566 } finally { 1567 mWin.setHasSurface(false); 1568 mSurfaceController = null; 1569 mDrawState = NO_SURFACE; 1570 } 1571 } 1572 1573 /** The force-scaled state for a given window can persist past 1574 * the state for it's stack as the windows complete resizing 1575 * independently of one another. 1576 */ isForceScaled()1577 boolean isForceScaled() { 1578 final Task task = mWin.getTask(); 1579 if (task != null && task.getStack().isForceScaled()) { 1580 return true; 1581 } 1582 return mForceScaleUntilResize; 1583 } 1584 detachChildren()1585 void detachChildren() { 1586 1587 // Do not detach children of starting windows, as their lifecycle is well under control and 1588 // it may lead to issues in case we relaunch when we just added the starting window. 1589 if (mWin.mAttrs.type == TYPE_APPLICATION_STARTING) { 1590 return; 1591 } 1592 if (mSurfaceController != null) { 1593 mSurfaceController.detachChildren(); 1594 } 1595 } 1596 setOffsetPositionForStackResize(boolean offsetPositionForStackResize)1597 void setOffsetPositionForStackResize(boolean offsetPositionForStackResize) { 1598 mOffsetPositionForStackResize = offsetPositionForStackResize; 1599 } 1600 getClientViewRootSurface()1601 SurfaceControl getClientViewRootSurface() { 1602 if (!hasSurface()) { 1603 return null; 1604 } 1605 return mSurfaceController.getClientViewRootSurface(); 1606 } 1607 } 1608