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