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