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