1// Copyright 2012 Google Inc. All Rights Reserved. 2 3package com.android.server.wm; 4 5import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; 6import static com.android.server.wm.WindowManagerService.LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE; 7import static com.android.server.wm.WindowManagerService.LayoutFields.SET_TURN_ON_SCREEN; 8 9import android.content.Context; 10import android.graphics.Matrix; 11import android.graphics.PixelFormat; 12import android.graphics.Point; 13import android.graphics.PointF; 14import android.graphics.Rect; 15import android.graphics.Region; 16import android.os.Debug; 17import android.os.UserHandle; 18import android.util.Slog; 19import android.view.DisplayInfo; 20import android.view.Surface; 21import android.view.SurfaceSession; 22import android.view.WindowManager; 23import android.view.WindowManagerPolicy; 24import android.view.WindowManager.LayoutParams; 25import android.view.animation.Animation; 26import android.view.animation.AnimationUtils; 27import android.view.animation.Transformation; 28 29import com.android.server.wm.WindowManagerService.H; 30 31import java.io.PrintWriter; 32import java.util.ArrayList; 33 34class WinAnimatorList extends ArrayList<WindowStateAnimator> { 35 public WinAnimatorList() { 36 super(); 37 } 38 39 public WinAnimatorList(WinAnimatorList other) { 40 super(other); 41 } 42} 43 44/** 45 * Keep track of animations and surface operations for a single WindowState. 46 **/ 47class WindowStateAnimator { 48 static final boolean DEBUG_VISIBILITY = WindowManagerService.DEBUG_VISIBILITY; 49 static final boolean DEBUG_ANIM = WindowManagerService.DEBUG_ANIM; 50 static final boolean DEBUG_LAYERS = WindowManagerService.DEBUG_LAYERS; 51 static final boolean DEBUG_STARTING_WINDOW = WindowManagerService.DEBUG_STARTING_WINDOW; 52 static final boolean SHOW_TRANSACTIONS = WindowManagerService.SHOW_TRANSACTIONS; 53 static final boolean SHOW_LIGHT_TRANSACTIONS = WindowManagerService.SHOW_LIGHT_TRANSACTIONS; 54 static final boolean SHOW_SURFACE_ALLOC = WindowManagerService.SHOW_SURFACE_ALLOC; 55 static final boolean localLOGV = WindowManagerService.localLOGV; 56 static final boolean DEBUG_ORIENTATION = WindowManagerService.DEBUG_ORIENTATION; 57 static final boolean DEBUG_SURFACE_TRACE = WindowManagerService.DEBUG_SURFACE_TRACE; 58 59 static final String TAG = "WindowStateAnimator"; 60 61 // Unchanging local convenience fields. 62 final WindowManagerService mService; 63 final WindowState mWin; 64 final WindowStateAnimator mAttachedWinAnimator; 65 final WindowAnimator mAnimator; 66 AppWindowAnimator mAppAnimator; 67 final Session mSession; 68 final WindowManagerPolicy mPolicy; 69 final Context mContext; 70 final boolean mIsWallpaper; 71 72 // If this is a universe background window, this is the transformation 73 // it is applying to the rest of the universe. 74 final Transformation mUniverseTransform = new Transformation(); 75 76 // Currently running animation. 77 boolean mAnimating; 78 boolean mLocalAnimating; 79 Animation mAnimation; 80 boolean mAnimationIsEntrance; 81 boolean mHasTransformation; 82 boolean mHasLocalTransformation; 83 final Transformation mTransformation = new Transformation(); 84 boolean mWasAnimating; // Were we animating going into the most recent animation step? 85 int mAnimLayer; 86 int mLastLayer; 87 88 Surface mSurface; 89 Surface mPendingDestroySurface; 90 91 /** 92 * Set when we have changed the size of the surface, to know that 93 * we must tell them application to resize (and thus redraw itself). 94 */ 95 boolean mSurfaceResized; 96 97 /** 98 * Set if the client has asked that the destroy of its surface be delayed 99 * until it explicitly says it is okay. 100 */ 101 boolean mSurfaceDestroyDeferred; 102 103 float mShownAlpha = 0; 104 float mAlpha = 0; 105 float mLastAlpha = 0; 106 107 // Used to save animation distances between the time they are calculated and when they are 108 // used. 109 int mAnimDw; 110 int mAnimDh; 111 float mDsDx=1, mDtDx=0, mDsDy=0, mDtDy=1; 112 float mLastDsDx=1, mLastDtDx=0, mLastDsDy=0, mLastDtDy=1; 113 114 boolean mHaveMatrix; 115 116 // For debugging, this is the last information given to the surface flinger. 117 boolean mSurfaceShown; 118 float mSurfaceX, mSurfaceY, mSurfaceW, mSurfaceH; 119 int mSurfaceLayer; 120 float mSurfaceAlpha; 121 122 // Set to true if, when the window gets displayed, it should perform 123 // an enter animation. 124 boolean mEnterAnimationPending; 125 126 /** This is set when there is no Surface */ 127 static final int NO_SURFACE = 0; 128 /** This is set after the Surface has been created but before the window has been drawn. During 129 * this time the surface is hidden. */ 130 static final int DRAW_PENDING = 1; 131 /** This is set after the window has finished drawing for the first time but before its surface 132 * is shown. The surface will be displayed when the next layout is run. */ 133 static final int COMMIT_DRAW_PENDING = 2; 134 /** This is set during the time after the window's drawing has been committed, and before its 135 * surface is actually shown. It is used to delay showing the surface until all windows in a 136 * token are ready to be shown. */ 137 static final int READY_TO_SHOW = 3; 138 /** Set when the window has been shown in the screen the first time. */ 139 static final int HAS_DRAWN = 4; 140 static String drawStateToString(int state) { 141 switch (state) { 142 case NO_SURFACE: return "NO_SURFACE"; 143 case DRAW_PENDING: return "DRAW_PENDING"; 144 case COMMIT_DRAW_PENDING: return "COMMIT_DRAW_PENDING"; 145 case READY_TO_SHOW: return "READY_TO_SHOW"; 146 case HAS_DRAWN: return "HAS_DRAWN"; 147 default: return Integer.toString(state); 148 } 149 } 150 int mDrawState; 151 152 /** Was this window last hidden? */ 153 boolean mLastHidden; 154 155 int mAttrFlags; 156 int mAttrType; 157 158 final int mLayerStack; 159 160 public WindowStateAnimator(final WindowState win) { 161 final WindowManagerService service = win.mService; 162 163 mService = service; 164 mAnimator = service.mAnimator; 165 mPolicy = service.mPolicy; 166 mContext = service.mContext; 167 final DisplayInfo displayInfo = win.mDisplayContent.getDisplayInfo(); 168 mAnimDw = displayInfo.appWidth; 169 mAnimDh = displayInfo.appHeight; 170 171 mWin = win; 172 mAttachedWinAnimator = win.mAttachedWindow == null 173 ? null : win.mAttachedWindow.mWinAnimator; 174 mAppAnimator = win.mAppToken == null ? null : win.mAppToken.mAppAnimator; 175 mSession = win.mSession; 176 mAttrFlags = win.mAttrs.flags; 177 mAttrType = win.mAttrs.type; 178 mIsWallpaper = win.mIsWallpaper; 179 mLayerStack = win.mDisplayContent.getDisplay().getLayerStack(); 180 } 181 182 public void setAnimation(Animation anim) { 183 if (localLOGV) Slog.v(TAG, "Setting animation in " + this + ": " + anim); 184 mAnimating = false; 185 mLocalAnimating = false; 186 mAnimation = anim; 187 mAnimation.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION); 188 mAnimation.scaleCurrentDuration(mService.mWindowAnimationScale); 189 // Start out animation gone if window is gone, or visible if window is visible. 190 mTransformation.clear(); 191 mTransformation.setAlpha(mLastHidden ? 0 : 1); 192 mHasLocalTransformation = true; 193 } 194 195 public void clearAnimation() { 196 if (mAnimation != null) { 197 mAnimating = true; 198 mLocalAnimating = false; 199 mAnimation.cancel(); 200 mAnimation = null; 201 } 202 } 203 204 /** Is the window or its container currently animating? */ 205 boolean isAnimating() { 206 return mAnimation != null 207 || (mAttachedWinAnimator != null && mAttachedWinAnimator.mAnimation != null) 208 || (mAppAnimator != null && 209 (mAppAnimator.animation != null 210 || mAppAnimator.mAppToken.inPendingTransaction)); 211 } 212 213 /** Is the window animating the DummyAnimation? */ 214 boolean isDummyAnimation() { 215 return mAppAnimator != null 216 && mAppAnimator.animation == AppWindowAnimator.sDummyAnimation; 217 } 218 219 /** Is this window currently animating? */ 220 boolean isWindowAnimating() { 221 return mAnimation != null; 222 } 223 224 void cancelExitAnimationForNextAnimationLocked() { 225 if (mAnimation != null) { 226 mAnimation.cancel(); 227 mAnimation = null; 228 mLocalAnimating = false; 229 destroySurfaceLocked(true); 230 } 231 } 232 233 private boolean stepAnimation(long currentTime) { 234 if ((mAnimation == null) || !mLocalAnimating) { 235 return false; 236 } 237 mTransformation.clear(); 238 final boolean more = mAnimation.getTransformation(currentTime, mTransformation); 239 if (false && DEBUG_ANIM) Slog.v( 240 TAG, "Stepped animation in " + this + 241 ": more=" + more + ", xform=" + mTransformation); 242 return more; 243 } 244 245 // This must be called while inside a transaction. Returns true if 246 // there is more animation to run. 247 boolean stepAnimationLocked(long currentTime) { 248 // Save the animation state as it was before this step so WindowManagerService can tell if 249 // we just started or just stopped animating by comparing mWasAnimating with isAnimating(). 250 mWasAnimating = mAnimating; 251 if (mService.okToDisplay()) { 252 // We will run animations as long as the display isn't frozen. 253 254 if (mWin.isDrawnLw() && mAnimation != null) { 255 mHasTransformation = true; 256 mHasLocalTransformation = true; 257 if (!mLocalAnimating) { 258 if (DEBUG_ANIM) Slog.v( 259 TAG, "Starting animation in " + this + 260 " @ " + currentTime + ": ww=" + mWin.mFrame.width() + 261 " wh=" + mWin.mFrame.height() + 262 " dw=" + mAnimDw + " dh=" + mAnimDh + 263 " scale=" + mService.mWindowAnimationScale); 264 mAnimation.initialize(mWin.mFrame.width(), mWin.mFrame.height(), 265 mAnimDw, mAnimDh); 266 final DisplayInfo displayInfo = mWin.mDisplayContent.getDisplayInfo(); 267 mAnimDw = displayInfo.appWidth; 268 mAnimDh = displayInfo.appHeight; 269 mAnimation.setStartTime(currentTime); 270 mLocalAnimating = true; 271 mAnimating = true; 272 } 273 if ((mAnimation != null) && mLocalAnimating) { 274 if (stepAnimation(currentTime)) { 275 return true; 276 } 277 } 278 if (DEBUG_ANIM) Slog.v( 279 TAG, "Finished animation in " + this + 280 " @ " + currentTime); 281 //WindowManagerService.this.dump(); 282 } 283 mHasLocalTransformation = false; 284 if ((!mLocalAnimating || mAnimationIsEntrance) && mAppAnimator != null 285 && mAppAnimator.animation != null) { 286 // When our app token is animating, we kind-of pretend like 287 // we are as well. Note the mLocalAnimating mAnimationIsEntrance 288 // part of this check means that we will only do this if 289 // our window is not currently exiting, or it is not 290 // locally animating itself. The idea being that one that 291 // is exiting and doing a local animation should be removed 292 // once that animation is done. 293 mAnimating = true; 294 mHasTransformation = true; 295 mTransformation.clear(); 296 return false; 297 } else if (mHasTransformation) { 298 // Little trick to get through the path below to act like 299 // we have finished an animation. 300 mAnimating = true; 301 } else if (isAnimating()) { 302 mAnimating = true; 303 } 304 } else if (mAnimation != null) { 305 // If the display is frozen, and there is a pending animation, 306 // clear it and make sure we run the cleanup code. 307 mAnimating = true; 308 } 309 310 if (!mAnimating && !mLocalAnimating) { 311 return false; 312 } 313 314 // Done animating, clean up. 315 if (DEBUG_ANIM) Slog.v( 316 TAG, "Animation done in " + this + ": exiting=" + mWin.mExiting 317 + ", reportedVisible=" 318 + (mWin.mAppToken != null ? mWin.mAppToken.reportedVisible : false)); 319 320 mAnimating = false; 321 mLocalAnimating = false; 322 if (mAnimation != null) { 323 mAnimation.cancel(); 324 mAnimation = null; 325 } 326 if (mAnimator.mWindowDetachedWallpaper == mWin) { 327 mAnimator.mWindowDetachedWallpaper = null; 328 } 329 mAnimLayer = mWin.mLayer; 330 if (mWin.mIsImWindow) { 331 mAnimLayer += mService.mInputMethodAnimLayerAdjustment; 332 } else if (mIsWallpaper) { 333 mAnimLayer += mService.mWallpaperAnimLayerAdjustment; 334 } 335 if (DEBUG_LAYERS) Slog.v(TAG, "Stepping win " + this 336 + " anim layer: " + mAnimLayer); 337 mHasTransformation = false; 338 mHasLocalTransformation = false; 339 if (mWin.mPolicyVisibility != mWin.mPolicyVisibilityAfterAnim) { 340 if (WindowState.DEBUG_VISIBILITY) { 341 Slog.v(TAG, "Policy visibility changing after anim in " + this + ": " 342 + mWin.mPolicyVisibilityAfterAnim); 343 } 344 mWin.mPolicyVisibility = mWin.mPolicyVisibilityAfterAnim; 345 mWin.mDisplayContent.layoutNeeded = true; 346 if (!mWin.mPolicyVisibility) { 347 if (mService.mCurrentFocus == mWin) { 348 mService.mFocusMayChange = true; 349 } 350 // Window is no longer visible -- make sure if we were waiting 351 // for it to be displayed before enabling the display, that 352 // we allow the display to be enabled now. 353 mService.enableScreenIfNeededLocked(); 354 } 355 } 356 mTransformation.clear(); 357 if (mDrawState == HAS_DRAWN 358 && mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING 359 && mWin.mAppToken != null 360 && mWin.mAppToken.firstWindowDrawn 361 && mWin.mAppToken.startingData != null) { 362 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Finish starting " 363 + mWin.mToken + ": first real window done animating"); 364 mService.mFinishedStarting.add(mWin.mAppToken); 365 mService.mH.sendEmptyMessage(H.FINISHED_STARTING); 366 } 367 368 finishExit(); 369 final int displayId = mWin.mDisplayContent.getDisplayId(); 370 mAnimator.setPendingLayoutChanges(displayId, WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM); 371 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) mService.debugLayoutRepeats( 372 "WindowStateAnimator", mAnimator.mPendingLayoutChanges.get(displayId)); 373 374 if (mWin.mAppToken != null) { 375 mWin.mAppToken.updateReportedVisibilityLocked(); 376 } 377 378 return false; 379 } 380 381 void finishExit() { 382 if (WindowManagerService.DEBUG_ANIM) Slog.v( 383 TAG, "finishExit in " + this 384 + ": exiting=" + mWin.mExiting 385 + " remove=" + mWin.mRemoveOnExit 386 + " windowAnimating=" + isWindowAnimating()); 387 388 final int N = mWin.mChildWindows.size(); 389 for (int i=0; i<N; i++) { 390 mWin.mChildWindows.get(i).mWinAnimator.finishExit(); 391 } 392 393 if (!mWin.mExiting) { 394 return; 395 } 396 397 if (isWindowAnimating()) { 398 return; 399 } 400 401 if (WindowManagerService.localLOGV) Slog.v( 402 TAG, "Exit animation finished in " + this 403 + ": remove=" + mWin.mRemoveOnExit); 404 if (mSurface != null) { 405 mService.mDestroySurface.add(mWin); 406 mWin.mDestroying = true; 407 if (WindowState.SHOW_TRANSACTIONS) WindowManagerService.logSurface( 408 mWin, "HIDE (finishExit)", null); 409 hide(); 410 } 411 mWin.mExiting = false; 412 if (mWin.mRemoveOnExit) { 413 mService.mPendingRemove.add(mWin); 414 mWin.mRemoveOnExit = false; 415 } 416 mAnimator.hideWallpapersLocked(mWin, true); 417 } 418 419 void hide() { 420 if (!mLastHidden) { 421 //dump(); 422 mLastHidden = true; 423 if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin, 424 "HIDE (performLayout)", null); 425 if (mSurface != null) { 426 mSurfaceShown = false; 427 try { 428 mSurface.hide(); 429 } catch (RuntimeException e) { 430 Slog.w(TAG, "Exception hiding surface in " + mWin); 431 } 432 } 433 } 434 } 435 436 boolean finishDrawingLocked() { 437 if (DEBUG_STARTING_WINDOW && 438 mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) { 439 Slog.v(TAG, "Finishing drawing window " + mWin + ": mDrawState=" 440 + drawStateToString(mDrawState)); 441 } 442 if (mDrawState == DRAW_PENDING) { 443 if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || SHOW_TRANSACTIONS || DEBUG_ORIENTATION) 444 Slog.v(TAG, "finishDrawingLocked: mDrawState=COMMIT_DRAW_PENDING " + this + " in " 445 + mSurface); 446 if (DEBUG_STARTING_WINDOW && 447 mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) { 448 Slog.v(TAG, "Draw state now committed in " + mWin); 449 } 450 mDrawState = COMMIT_DRAW_PENDING; 451 return true; 452 } 453 return false; 454 } 455 456 // This must be called while inside a transaction. 457 boolean commitFinishDrawingLocked(long currentTime) { 458 if (DEBUG_STARTING_WINDOW && 459 mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) { 460 Slog.i(TAG, "commitFinishDrawingLocked: " + mWin + " cur mDrawState=" 461 + drawStateToString(mDrawState)); 462 } 463 if (mDrawState != COMMIT_DRAW_PENDING) { 464 return false; 465 } 466 if (DEBUG_SURFACE_TRACE || DEBUG_ANIM) { 467 Slog.i(TAG, "commitFinishDrawingLocked: mDrawState=READY_TO_SHOW " + mSurface); 468 } 469 mDrawState = READY_TO_SHOW; 470 final boolean starting = mWin.mAttrs.type == TYPE_APPLICATION_STARTING; 471 final AppWindowToken atoken = mWin.mAppToken; 472 if (atoken == null || atoken.allDrawn || starting) { 473 performShowLocked(); 474 } 475 return true; 476 } 477 478 static class SurfaceTrace extends Surface { 479 private final static String SURFACE_TAG = "SurfaceTrace"; 480 final static ArrayList<SurfaceTrace> sSurfaces = new ArrayList<SurfaceTrace>(); 481 482 private float mSurfaceTraceAlpha = 0; 483 private int mLayer; 484 private final PointF mPosition = new PointF(); 485 private final Point mSize = new Point(); 486 private final Rect mWindowCrop = new Rect(); 487 private boolean mShown = false; 488 private int mLayerStack; 489 private String mName; 490 491 public SurfaceTrace(SurfaceSession s, 492 String name, int w, int h, int format, int flags) 493 throws OutOfResourcesException { 494 super(s, name, w, h, format, flags); 495 mName = name != null ? name : "Not named"; 496 mSize.set(w, h); 497 Slog.v(SURFACE_TAG, "ctor: " + this + ". Called by " 498 + Debug.getCallers(3)); 499 } 500 501 @Override 502 public void setAlpha(float alpha) { 503 super.setAlpha(alpha); 504 if (alpha != mSurfaceTraceAlpha) { 505 Slog.v(SURFACE_TAG, "setAlpha: " + this + ". Called by " 506 + Debug.getCallers(3)); 507 } 508 mSurfaceTraceAlpha = alpha; 509 } 510 511 @Override 512 public void setLayer(int zorder) { 513 super.setLayer(zorder); 514 if (zorder != mLayer) { 515 Slog.v(SURFACE_TAG, "setLayer: " + this + ". Called by " 516 + Debug.getCallers(3)); 517 } 518 mLayer = zorder; 519 520 sSurfaces.remove(this); 521 int i; 522 for (i = sSurfaces.size() - 1; i >= 0; i--) { 523 SurfaceTrace s = sSurfaces.get(i); 524 if (s.mLayer < zorder) { 525 break; 526 } 527 } 528 sSurfaces.add(i + 1, this); 529 } 530 531 @Override 532 public void setPosition(float x, float y) { 533 super.setPosition(x, y); 534 if (x != mPosition.x || y != mPosition.y) { 535 Slog.v(SURFACE_TAG, "setPosition: " + this + ". Called by " 536 + Debug.getCallers(3)); 537 } 538 mPosition.set(x, y); 539 } 540 541 @Override 542 public void setSize(int w, int h) { 543 super.setSize(w, h); 544 if (w != mSize.x || h != mSize.y) { 545 Slog.v(SURFACE_TAG, "setSize: " + this + ". Called by " 546 + Debug.getCallers(3)); 547 } 548 mSize.set(w, h); 549 } 550 551 @Override 552 public void setWindowCrop(Rect crop) { 553 super.setWindowCrop(crop); 554 if (crop != null) { 555 if (!crop.equals(mWindowCrop)) { 556 Slog.v(SURFACE_TAG, "setWindowCrop: " + this + ". Called by " 557 + Debug.getCallers(3)); 558 } 559 mWindowCrop.set(crop); 560 } 561 } 562 563 @Override 564 public void setLayerStack(int layerStack) { 565 super.setLayerStack(layerStack); 566 if (layerStack != mLayerStack) { 567 Slog.v(SURFACE_TAG, "setLayerStack: " + this + ". Called by " + Debug.getCallers(3)); 568 } 569 mLayerStack = layerStack; 570 } 571 572 @Override 573 public void hide() { 574 super.hide(); 575 if (mShown) { 576 Slog.v(SURFACE_TAG, "hide: " + this + ". Called by " 577 + Debug.getCallers(3)); 578 } 579 mShown = false; 580 } 581 @Override 582 public void show() { 583 super.show(); 584 if (!mShown) { 585 Slog.v(SURFACE_TAG, "show: " + this + ". Called by " 586 + Debug.getCallers(3)); 587 } 588 mShown = true; 589 } 590 591 @Override 592 public void destroy() { 593 super.destroy(); 594 Slog.v(SURFACE_TAG, "destroy: " + this + ". Called by " 595 + Debug.getCallers(3)); 596 sSurfaces.remove(this); 597 } 598 599 @Override 600 public void release() { 601 super.release(); 602 Slog.v(SURFACE_TAG, "release: " + this + ". Called by " 603 + Debug.getCallers(3)); 604 sSurfaces.remove(this); 605 } 606 607 static void dumpAllSurfaces() { 608 final int N = sSurfaces.size(); 609 for (int i = 0; i < N; i++) { 610 Slog.i(TAG, "SurfaceDump: " + sSurfaces.get(i)); 611 } 612 } 613 614 @Override 615 public String toString() { 616 return "Surface " + Integer.toHexString(System.identityHashCode(this)) + " " 617 + mName + " (" + mLayerStack + "): shown=" + mShown + " layer=" + mLayer 618 + " alpha=" + mSurfaceTraceAlpha + " " + mPosition.x + "," + mPosition.y 619 + " " + mSize.x + "x" + mSize.y 620 + " crop=" + mWindowCrop.toShortString(); 621 } 622 } 623 624 Surface createSurfaceLocked() { 625 if (mSurface == null) { 626 if (DEBUG_ANIM || DEBUG_ORIENTATION) Slog.i(TAG, 627 "createSurface " + this + ": mDrawState=DRAW_PENDING"); 628 mDrawState = DRAW_PENDING; 629 if (mWin.mAppToken != null) { 630 mWin.mAppToken.allDrawn = false; 631 } 632 633 mService.makeWindowFreezingScreenIfNeededLocked(mWin); 634 635 int flags = Surface.HIDDEN; 636 final WindowManager.LayoutParams attrs = mWin.mAttrs; 637 638 if ((attrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) { 639 flags |= Surface.SECURE; 640 } 641 if (WindowState.DEBUG_VISIBILITY) Slog.v( 642 TAG, "Creating surface in session " 643 + mSession.mSurfaceSession + " window " + this 644 + " w=" + mWin.mCompatFrame.width() 645 + " h=" + mWin.mCompatFrame.height() + " format=" 646 + attrs.format + " flags=" + flags); 647 648 int w = mWin.mCompatFrame.width(); 649 int h = mWin.mCompatFrame.height(); 650 if ((attrs.flags & LayoutParams.FLAG_SCALED) != 0) { 651 // for a scaled surface, we always want the requested 652 // size. 653 w = mWin.mRequestedWidth; 654 h = mWin.mRequestedHeight; 655 } 656 657 // Something is wrong and SurfaceFlinger will not like this, 658 // try to revert to sane values 659 if (w <= 0) w = 1; 660 if (h <= 0) h = 1; 661 662 mSurfaceShown = false; 663 mSurfaceLayer = 0; 664 mSurfaceAlpha = 0; 665 mSurfaceX = 0; 666 mSurfaceY = 0; 667 mSurfaceW = w; 668 mSurfaceH = h; 669 mWin.mLastSystemDecorRect.set(0, 0, 0, 0); 670 try { 671 final boolean isHwAccelerated = (attrs.flags & 672 WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0; 673 final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format; 674 if (!PixelFormat.formatHasAlpha(attrs.format)) { 675 flags |= Surface.OPAQUE; 676 } 677 if (DEBUG_SURFACE_TRACE) { 678 mSurface = new SurfaceTrace( 679 mSession.mSurfaceSession, 680 attrs.getTitle().toString(), 681 w, h, format, flags); 682 } else { 683 mSurface = new Surface( 684 mSession.mSurfaceSession, 685 attrs.getTitle().toString(), 686 w, h, format, flags); 687 } 688 mWin.mHasSurface = true; 689 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) Slog.i(TAG, 690 " CREATE SURFACE " 691 + mSurface + " IN SESSION " 692 + mSession.mSurfaceSession 693 + ": pid=" + mSession.mPid + " format=" 694 + attrs.format + " flags=0x" 695 + Integer.toHexString(flags) 696 + " / " + this); 697 } catch (Surface.OutOfResourcesException e) { 698 mWin.mHasSurface = false; 699 Slog.w(TAG, "OutOfResourcesException creating surface"); 700 mService.reclaimSomeSurfaceMemoryLocked(this, "create", true); 701 mDrawState = NO_SURFACE; 702 return null; 703 } catch (Exception e) { 704 mWin.mHasSurface = false; 705 Slog.e(TAG, "Exception creating surface", e); 706 mDrawState = NO_SURFACE; 707 return null; 708 } 709 710 if (WindowManagerService.localLOGV) Slog.v( 711 TAG, "Got surface: " + mSurface 712 + ", set left=" + mWin.mFrame.left + " top=" + mWin.mFrame.top 713 + ", animLayer=" + mAnimLayer); 714 if (SHOW_LIGHT_TRANSACTIONS) { 715 Slog.i(TAG, ">>> OPEN TRANSACTION createSurfaceLocked"); 716 WindowManagerService.logSurface(mWin, "CREATE pos=(" 717 + mWin.mFrame.left + "," + mWin.mFrame.top + ") (" 718 + mWin.mCompatFrame.width() + "x" + mWin.mCompatFrame.height() 719 + "), layer=" + mAnimLayer + " HIDE", null); 720 } 721 Surface.openTransaction(); 722 try { 723 try { 724 mSurfaceX = mWin.mFrame.left + mWin.mXOffset; 725 mSurfaceY = mWin.mFrame.top + mWin.mYOffset; 726 mSurface.setPosition(mSurfaceX, mSurfaceY); 727 mSurfaceLayer = mAnimLayer; 728 mSurface.setLayerStack(mLayerStack); 729 mSurface.setLayer(mAnimLayer); 730 mSurface.setAlpha(0); 731 mSurfaceShown = false; 732 } catch (RuntimeException e) { 733 Slog.w(TAG, "Error creating surface in " + w, e); 734 mService.reclaimSomeSurfaceMemoryLocked(this, "create-init", true); 735 } 736 mLastHidden = true; 737 } finally { 738 Surface.closeTransaction(); 739 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 740 "<<< CLOSE TRANSACTION createSurfaceLocked"); 741 } 742 if (WindowManagerService.localLOGV) Slog.v( 743 TAG, "Created surface " + this); 744 } 745 return mSurface; 746 } 747 748 void destroySurfaceLocked(boolean fromAnimator) { 749 if (mWin.mAppToken != null && mWin == mWin.mAppToken.startingWindow) { 750 mWin.mAppToken.startingDisplayed = false; 751 } 752 753 if (mSurface != null) { 754 755 int i = mWin.mChildWindows.size(); 756 while (i > 0) { 757 i--; 758 WindowState c = mWin.mChildWindows.get(i); 759 c.mAttachedHidden = true; 760 } 761 762 try { 763 if (DEBUG_VISIBILITY) { 764 RuntimeException e = null; 765 if (!WindowManagerService.HIDE_STACK_CRAWLS) { 766 e = new RuntimeException(); 767 e.fillInStackTrace(); 768 } 769 Slog.w(TAG, "Window " + this + " destroying surface " 770 + mSurface + ", session " + mSession, e); 771 } 772 if (mSurfaceDestroyDeferred) { 773 if (mSurface != null && mPendingDestroySurface != mSurface) { 774 if (mPendingDestroySurface != null) { 775 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) { 776 RuntimeException e = null; 777 if (!WindowManagerService.HIDE_STACK_CRAWLS) { 778 e = new RuntimeException(); 779 e.fillInStackTrace(); 780 } 781 WindowManagerService.logSurface(mWin, "DESTROY PENDING", e); 782 } 783 mPendingDestroySurface.destroy(); 784 } 785 mPendingDestroySurface = mSurface; 786 } 787 } else { 788 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) { 789 RuntimeException e = null; 790 if (!WindowManagerService.HIDE_STACK_CRAWLS) { 791 e = new RuntimeException(); 792 e.fillInStackTrace(); 793 } 794 WindowManagerService.logSurface(mWin, "DESTROY", e); 795 } 796 mSurface.destroy(); 797 } 798 mAnimator.hideWallpapersLocked(mWin, fromAnimator); 799 } catch (RuntimeException e) { 800 Slog.w(TAG, "Exception thrown when destroying Window " + this 801 + " surface " + mSurface + " session " + mSession 802 + ": " + e.toString()); 803 } 804 805 mSurfaceShown = false; 806 mSurface = null; 807 mWin.mHasSurface = false; 808 mDrawState = NO_SURFACE; 809 } 810 } 811 812 void destroyDeferredSurfaceLocked(boolean fromAnimator) { 813 try { 814 if (mPendingDestroySurface != null) { 815 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) { 816 RuntimeException e = null; 817 if (!WindowManagerService.HIDE_STACK_CRAWLS) { 818 e = new RuntimeException(); 819 e.fillInStackTrace(); 820 } 821 WindowManagerService.logSurface(mWin, "DESTROY PENDING", e); 822 } 823 mPendingDestroySurface.destroy(); 824 mAnimator.hideWallpapersLocked(mWin, fromAnimator); 825 } 826 } catch (RuntimeException e) { 827 Slog.w(TAG, "Exception thrown when destroying Window " 828 + this + " surface " + mPendingDestroySurface 829 + " session " + mSession + ": " + e.toString()); 830 } 831 mSurfaceDestroyDeferred = false; 832 mPendingDestroySurface = null; 833 } 834 835 void computeShownFrameLocked() { 836 final boolean selfTransformation = mHasLocalTransformation; 837 Transformation attachedTransformation = 838 (mAttachedWinAnimator != null && mAttachedWinAnimator.mHasLocalTransformation) 839 ? mAttachedWinAnimator.mTransformation : null; 840 Transformation appTransformation = (mAppAnimator != null && mAppAnimator.hasTransformation) 841 ? mAppAnimator.transformation : null; 842 843 // Wallpapers are animated based on the "real" window they 844 // are currently targeting. 845 if (mIsWallpaper && mAnimator.mLowerWallpaperTarget == null 846 && mAnimator.mWallpaperTarget != null) { 847 final WindowStateAnimator wallpaperAnimator = mAnimator.mWallpaperTarget.mWinAnimator; 848 if (wallpaperAnimator.mHasLocalTransformation && 849 wallpaperAnimator.mAnimation != null && 850 !wallpaperAnimator.mAnimation.getDetachWallpaper()) { 851 attachedTransformation = wallpaperAnimator.mTransformation; 852 if (WindowManagerService.DEBUG_WALLPAPER && attachedTransformation != null) { 853 Slog.v(TAG, "WP target attached xform: " + attachedTransformation); 854 } 855 } 856 final AppWindowAnimator wpAppAnimator = mAnimator.mWpAppAnimator; 857 if (wpAppAnimator != null && wpAppAnimator.hasTransformation 858 && wpAppAnimator.animation != null 859 && !wpAppAnimator.animation.getDetachWallpaper()) { 860 appTransformation = wpAppAnimator.transformation; 861 if (WindowManagerService.DEBUG_WALLPAPER && appTransformation != null) { 862 Slog.v(TAG, "WP target app xform: " + appTransformation); 863 } 864 } 865 } 866 867 final int displayId = mWin.getDisplayId(); 868 final ScreenRotationAnimation screenRotationAnimation = 869 mAnimator.getScreenRotationAnimationLocked(displayId); 870 final boolean screenAnimation = 871 screenRotationAnimation != null && screenRotationAnimation.isAnimating(); 872 if (selfTransformation || attachedTransformation != null 873 || appTransformation != null || screenAnimation) { 874 // cache often used attributes locally 875 final Rect frame = mWin.mFrame; 876 final float tmpFloats[] = mService.mTmpFloats; 877 final Matrix tmpMatrix = mWin.mTmpMatrix; 878 879 // Compute the desired transformation. 880 if (screenAnimation && screenRotationAnimation.isRotating()) { 881 // If we are doing a screen animation, the global rotation 882 // applied to windows can result in windows that are carefully 883 // aligned with each other to slightly separate, allowing you 884 // to see what is behind them. An unsightly mess. This... 885 // thing... magically makes it call good: scale each window 886 // slightly (two pixels larger in each dimension, from the 887 // window's center). 888 final float w = frame.width(); 889 final float h = frame.height(); 890 if (w>=1 && h>=1) { 891 tmpMatrix.setScale(1 + 2/w, 1 + 2/h, w/2, h/2); 892 } else { 893 tmpMatrix.reset(); 894 } 895 } else { 896 tmpMatrix.reset(); 897 } 898 tmpMatrix.postScale(mWin.mGlobalScale, mWin.mGlobalScale); 899 if (selfTransformation) { 900 tmpMatrix.postConcat(mTransformation.getMatrix()); 901 } 902 tmpMatrix.postTranslate(frame.left + mWin.mXOffset, frame.top + mWin.mYOffset); 903 if (attachedTransformation != null) { 904 tmpMatrix.postConcat(attachedTransformation.getMatrix()); 905 } 906 if (appTransformation != null) { 907 tmpMatrix.postConcat(appTransformation.getMatrix()); 908 } 909 if (mAnimator.mUniverseBackground != null) { 910 tmpMatrix.postConcat(mAnimator.mUniverseBackground.mUniverseTransform.getMatrix()); 911 } 912 if (screenAnimation) { 913 tmpMatrix.postConcat(screenRotationAnimation.getEnterTransformation().getMatrix()); 914 } 915 MagnificationSpec spec = mWin.getWindowMagnificationSpecLocked(); 916 if (spec != null && !spec.isNop()) { 917 tmpMatrix.postScale(spec.mScale, spec.mScale); 918 tmpMatrix.postTranslate(spec.mOffsetX, spec.mOffsetY); 919 } 920 921 // "convert" it into SurfaceFlinger's format 922 // (a 2x2 matrix + an offset) 923 // Here we must not transform the position of the surface 924 // since it is already included in the transformation. 925 //Slog.i(TAG, "Transform: " + matrix); 926 927 mHaveMatrix = true; 928 tmpMatrix.getValues(tmpFloats); 929 mDsDx = tmpFloats[Matrix.MSCALE_X]; 930 mDtDx = tmpFloats[Matrix.MSKEW_Y]; 931 mDsDy = tmpFloats[Matrix.MSKEW_X]; 932 mDtDy = tmpFloats[Matrix.MSCALE_Y]; 933 float x = tmpFloats[Matrix.MTRANS_X]; 934 float y = tmpFloats[Matrix.MTRANS_Y]; 935 int w = frame.width(); 936 int h = frame.height(); 937 mWin.mShownFrame.set(x, y, x+w, y+h); 938 939 // Now set the alpha... but because our current hardware 940 // can't do alpha transformation on a non-opaque surface, 941 // turn it off if we are running an animation that is also 942 // transforming since it is more important to have that 943 // animation be smooth. 944 mShownAlpha = mAlpha; 945 if (!mService.mLimitedAlphaCompositing 946 || (!PixelFormat.formatHasAlpha(mWin.mAttrs.format) 947 || (mWin.isIdentityMatrix(mDsDx, mDtDx, mDsDy, mDtDy) 948 && x == frame.left && y == frame.top))) { 949 //Slog.i(TAG, "Applying alpha transform"); 950 if (selfTransformation) { 951 mShownAlpha *= mTransformation.getAlpha(); 952 } 953 if (attachedTransformation != null) { 954 mShownAlpha *= attachedTransformation.getAlpha(); 955 } 956 if (appTransformation != null) { 957 mShownAlpha *= appTransformation.getAlpha(); 958 } 959 if (mAnimator.mUniverseBackground != null) { 960 mShownAlpha *= mAnimator.mUniverseBackground.mUniverseTransform.getAlpha(); 961 } 962 if (screenAnimation) { 963 mShownAlpha *= screenRotationAnimation.getEnterTransformation().getAlpha(); 964 } 965 } else { 966 //Slog.i(TAG, "Not applying alpha transform"); 967 } 968 969 if ((DEBUG_SURFACE_TRACE || WindowManagerService.localLOGV) 970 && (mShownAlpha == 1.0 || mShownAlpha == 0.0)) Slog.v( 971 TAG, "computeShownFrameLocked: Animating " + this + " mAlpha=" + mAlpha 972 + " self=" + (selfTransformation ? mTransformation.getAlpha() : "null") 973 + " attached=" + (attachedTransformation == null ? 974 "null" : attachedTransformation.getAlpha()) 975 + " app=" + (appTransformation == null ? "null" : appTransformation.getAlpha()) 976 + " screen=" + (screenAnimation ? 977 screenRotationAnimation.getEnterTransformation().getAlpha() : "null")); 978 return; 979 } else if (mIsWallpaper && 980 (mAnimator.mPendingActions & WindowAnimator.WALLPAPER_ACTION_PENDING) != 0) { 981 return; 982 } 983 984 if (WindowManagerService.localLOGV) Slog.v( 985 TAG, "computeShownFrameLocked: " + this + 986 " not attached, mAlpha=" + mAlpha); 987 988 final boolean applyUniverseTransformation = (mAnimator.mUniverseBackground != null 989 && mWin.mAttrs.type != WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND 990 && mWin.mBaseLayer < mAnimator.mAboveUniverseLayer); 991 MagnificationSpec spec = mWin.getWindowMagnificationSpecLocked(); 992 if (applyUniverseTransformation || spec != null) { 993 final Rect frame = mWin.mFrame; 994 final float tmpFloats[] = mService.mTmpFloats; 995 final Matrix tmpMatrix = mWin.mTmpMatrix; 996 997 tmpMatrix.setScale(mWin.mGlobalScale, mWin.mGlobalScale); 998 tmpMatrix.postTranslate(frame.left + mWin.mXOffset, frame.top + mWin.mYOffset); 999 1000 if (applyUniverseTransformation) { 1001 tmpMatrix.postConcat(mAnimator.mUniverseBackground.mUniverseTransform.getMatrix()); 1002 } 1003 1004 if (spec != null && !spec.isNop()) { 1005 tmpMatrix.postScale(spec.mScale, spec.mScale); 1006 tmpMatrix.postTranslate(spec.mOffsetX, spec.mOffsetY); 1007 } 1008 1009 tmpMatrix.getValues(tmpFloats); 1010 1011 mHaveMatrix = true; 1012 mDsDx = tmpFloats[Matrix.MSCALE_X]; 1013 mDtDx = tmpFloats[Matrix.MSKEW_Y]; 1014 mDsDy = tmpFloats[Matrix.MSKEW_X]; 1015 mDtDy = tmpFloats[Matrix.MSCALE_Y]; 1016 float x = tmpFloats[Matrix.MTRANS_X]; 1017 float y = tmpFloats[Matrix.MTRANS_Y]; 1018 int w = frame.width(); 1019 int h = frame.height(); 1020 mWin.mShownFrame.set(x, y, x + w, y + h); 1021 1022 mShownAlpha = mAlpha; 1023 if (applyUniverseTransformation) { 1024 mShownAlpha *= mAnimator.mUniverseBackground.mUniverseTransform.getAlpha(); 1025 } 1026 } else { 1027 mWin.mShownFrame.set(mWin.mFrame); 1028 if (mWin.mXOffset != 0 || mWin.mYOffset != 0) { 1029 mWin.mShownFrame.offset(mWin.mXOffset, mWin.mYOffset); 1030 } 1031 mShownAlpha = mAlpha; 1032 mHaveMatrix = false; 1033 mDsDx = mWin.mGlobalScale; 1034 mDtDx = 0; 1035 mDsDy = 0; 1036 mDtDy = mWin.mGlobalScale; 1037 } 1038 } 1039 1040 void applyDecorRect(final Rect decorRect) { 1041 final WindowState w = mWin; 1042 // Compute the offset of the window in relation to the decor rect. 1043 final int offX = w.mXOffset + w.mFrame.left; 1044 final int offY = w.mYOffset + w.mFrame.top; 1045 // Initialize the decor rect to the entire frame. 1046 w.mSystemDecorRect.set(0, 0, w.mFrame.width(), w.mFrame.height()); 1047 // Intersect with the decor rect, offsetted by window position. 1048 w.mSystemDecorRect.intersect(decorRect.left-offX, decorRect.top-offY, 1049 decorRect.right-offX, decorRect.bottom-offY); 1050 // If size compatibility is being applied to the window, the 1051 // surface is scaled relative to the screen. Also apply this 1052 // scaling to the crop rect. We aren't using the standard rect 1053 // scale function because we want to round things to make the crop 1054 // always round to a larger rect to ensure we don't crop too 1055 // much and hide part of the window that should be seen. 1056 if (w.mEnforceSizeCompat && w.mInvGlobalScale != 1.0f) { 1057 final float scale = w.mInvGlobalScale; 1058 w.mSystemDecorRect.left = (int) (w.mSystemDecorRect.left * scale - 0.5f); 1059 w.mSystemDecorRect.top = (int) (w.mSystemDecorRect.top * scale - 0.5f); 1060 w.mSystemDecorRect.right = (int) ((w.mSystemDecorRect.right+1) * scale - 0.5f); 1061 w.mSystemDecorRect.bottom = (int) ((w.mSystemDecorRect.bottom+1) * scale - 0.5f); 1062 } 1063 } 1064 1065 void updateSurfaceWindowCrop(final boolean recoveringMemory) { 1066 final WindowState w = mWin; 1067 DisplayInfo displayInfo = w.mDisplayContent.getDisplayInfo(); 1068 1069 // Need to recompute a new system decor rect each time. 1070 if ((w.mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) { 1071 // Currently can't do this cropping for scaled windows. We'll 1072 // just keep the crop rect the same as the source surface. 1073 w.mSystemDecorRect.set(0, 0, w.mRequestedWidth, w.mRequestedHeight); 1074 } else if (!w.isDefaultDisplay()) { 1075 // On a different display there is no system decor. Crop the window 1076 // by the screen boundaries. 1077 w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(), w.mCompatFrame.height()); 1078 w.mSystemDecorRect.intersect(-w.mCompatFrame.left, -w.mCompatFrame.top, 1079 displayInfo.logicalWidth - w.mCompatFrame.left, 1080 displayInfo.logicalHeight - w.mCompatFrame.top); 1081 } else if (w.mLayer >= mService.mSystemDecorLayer) { 1082 // Above the decor layer is easy, just use the entire window. 1083 // Unless we have a universe background... in which case all the 1084 // windows need to be cropped by the screen, so they don't cover 1085 // the universe background. 1086 if (mAnimator.mUniverseBackground == null) { 1087 w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(), 1088 w.mCompatFrame.height()); 1089 } else { 1090 applyDecorRect(mService.mScreenRect); 1091 } 1092 } else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND) { 1093 // The universe background isn't cropped. 1094 w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(), 1095 w.mCompatFrame.height()); 1096 } else { 1097 applyDecorRect(mService.mSystemDecorRect); 1098 } 1099 1100 if (!w.mSystemDecorRect.equals(w.mLastSystemDecorRect)) { 1101 w.mLastSystemDecorRect.set(w.mSystemDecorRect); 1102 try { 1103 if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w, 1104 "CROP " + w.mSystemDecorRect.toShortString(), null); 1105 mSurface.setWindowCrop(w.mSystemDecorRect); 1106 } catch (RuntimeException e) { 1107 Slog.w(TAG, "Error setting crop surface of " + w 1108 + " crop=" + w.mSystemDecorRect.toShortString(), e); 1109 if (!recoveringMemory) { 1110 mService.reclaimSomeSurfaceMemoryLocked(this, "crop", true); 1111 } 1112 } 1113 } 1114 } 1115 1116 void setSurfaceBoundariesLocked(final boolean recoveringMemory) { 1117 final WindowState w = mWin; 1118 int width, height; 1119 if ((w.mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) { 1120 // for a scaled surface, we just want to use 1121 // the requested size. 1122 width = w.mRequestedWidth; 1123 height = w.mRequestedHeight; 1124 } else { 1125 width = w.mCompatFrame.width(); 1126 height = w.mCompatFrame.height(); 1127 } 1128 1129 if (width < 1) { 1130 width = 1; 1131 } 1132 if (height < 1) { 1133 height = 1; 1134 } 1135 final boolean surfaceResized = mSurfaceW != width || mSurfaceH != height; 1136 if (surfaceResized) { 1137 mSurfaceW = width; 1138 mSurfaceH = height; 1139 } 1140 1141 final float left = w.mShownFrame.left; 1142 final float top = w.mShownFrame.top; 1143 if (mSurfaceX != left || mSurfaceY != top) { 1144 try { 1145 if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w, 1146 "POS " + left + ", " + top, null); 1147 mSurfaceX = left; 1148 mSurfaceY = top; 1149 mSurface.setPosition(left, top); 1150 } catch (RuntimeException e) { 1151 Slog.w(TAG, "Error positioning surface of " + w 1152 + " pos=(" + left 1153 + "," + top + ")", e); 1154 if (!recoveringMemory) { 1155 mService.reclaimSomeSurfaceMemoryLocked(this, "position", true); 1156 } 1157 } 1158 } 1159 1160 if (surfaceResized) { 1161 try { 1162 if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w, 1163 "SIZE " + width + "x" + height, null); 1164 mSurfaceResized = true; 1165 mSurface.setSize(width, height); 1166 final int displayId = w.mDisplayContent.getDisplayId(); 1167 mAnimator.setPendingLayoutChanges(displayId, 1168 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER); 1169 if ((w.mAttrs.flags & LayoutParams.FLAG_DIM_BEHIND) != 0) { 1170 final DisplayInfo displayInfo = mWin.mDisplayContent.getDisplayInfo(); 1171 mService.startDimmingLocked(this, w.mExiting ? 0 : w.mAttrs.dimAmount, 1172 displayInfo.appWidth, displayInfo.appHeight); 1173 } 1174 } catch (RuntimeException e) { 1175 // If something goes wrong with the surface (such 1176 // as running out of memory), don't take down the 1177 // entire system. 1178 Slog.e(TAG, "Error resizing surface of " + w 1179 + " size=(" + width + "x" + height + ")", e); 1180 if (!recoveringMemory) { 1181 mService.reclaimSomeSurfaceMemoryLocked(this, "size", true); 1182 } 1183 } 1184 } 1185 1186 updateSurfaceWindowCrop(recoveringMemory); 1187 } 1188 1189 public void prepareSurfaceLocked(final boolean recoveringMemory) { 1190 final WindowState w = mWin; 1191 if (mSurface == null) { 1192 if (w.mOrientationChanging) { 1193 if (DEBUG_ORIENTATION) { 1194 Slog.v(TAG, "Orientation change skips hidden " + w); 1195 } 1196 w.mOrientationChanging = false; 1197 } 1198 return; 1199 } 1200 1201 boolean displayed = false; 1202 1203 computeShownFrameLocked(); 1204 1205 setSurfaceBoundariesLocked(recoveringMemory); 1206 1207 if (mIsWallpaper && !mWin.mWallpaperVisible) { 1208 // Wallpaper is no longer visible and there is no wp target => hide it. 1209 hide(); 1210 } else if (w.mAttachedHidden || !w.isReadyForDisplay()) { 1211 hide(); 1212 mAnimator.hideWallpapersLocked(w, true); 1213 1214 // If we are waiting for this window to handle an 1215 // orientation change, well, it is hidden, so 1216 // doesn't really matter. Note that this does 1217 // introduce a potential glitch if the window 1218 // becomes unhidden before it has drawn for the 1219 // new orientation. 1220 if (w.mOrientationChanging) { 1221 w.mOrientationChanging = false; 1222 if (DEBUG_ORIENTATION) Slog.v(TAG, 1223 "Orientation change skips hidden " + w); 1224 } 1225 } else if (mLastLayer != mAnimLayer 1226 || mLastAlpha != mShownAlpha 1227 || mLastDsDx != mDsDx 1228 || mLastDtDx != mDtDx 1229 || mLastDsDy != mDsDy 1230 || mLastDtDy != mDtDy 1231 || w.mLastHScale != w.mHScale 1232 || w.mLastVScale != w.mVScale 1233 || mLastHidden) { 1234 displayed = true; 1235 mLastAlpha = mShownAlpha; 1236 mLastLayer = mAnimLayer; 1237 mLastDsDx = mDsDx; 1238 mLastDtDx = mDtDx; 1239 mLastDsDy = mDsDy; 1240 mLastDtDy = mDtDy; 1241 w.mLastHScale = w.mHScale; 1242 w.mLastVScale = w.mVScale; 1243 if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w, 1244 "alpha=" + mShownAlpha + " layer=" + mAnimLayer 1245 + " matrix=[" + (mDsDx*w.mHScale) 1246 + "," + (mDtDx*w.mVScale) 1247 + "][" + (mDsDy*w.mHScale) 1248 + "," + (mDtDy*w.mVScale) + "]", null); 1249 if (mSurface != null) { 1250 try { 1251 mSurfaceAlpha = mShownAlpha; 1252 mSurface.setAlpha(mShownAlpha); 1253 mSurfaceLayer = mAnimLayer; 1254 mSurface.setLayer(mAnimLayer); 1255 mSurface.setMatrix( 1256 mDsDx*w.mHScale, mDtDx*w.mVScale, 1257 mDsDy*w.mHScale, mDtDy*w.mVScale); 1258 1259 if (mLastHidden && mDrawState == HAS_DRAWN) { 1260 if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w, 1261 "SHOW (performLayout)", null); 1262 if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + w 1263 + " during relayout"); 1264 if (showSurfaceRobustlyLocked()) { 1265 mLastHidden = false; 1266 if (mIsWallpaper) { 1267 mService.dispatchWallpaperVisibility(w, true); 1268 } 1269 } else { 1270 w.mOrientationChanging = false; 1271 } 1272 } 1273 if (mSurface != null) { 1274 w.mToken.hasVisible = true; 1275 } 1276 } catch (RuntimeException e) { 1277 Slog.w(TAG, "Error updating surface in " + w, e); 1278 if (!recoveringMemory) { 1279 mService.reclaimSomeSurfaceMemoryLocked(this, "update", true); 1280 } 1281 } 1282 } 1283 } else { 1284 if (DEBUG_ANIM && isAnimating()) { 1285 Slog.v(TAG, "prepareSurface: No changes in animation for " + this); 1286 } 1287 displayed = true; 1288 } 1289 1290 if (displayed) { 1291 if (w.mOrientationChanging) { 1292 if (!w.isDrawnLw()) { 1293 mAnimator.mBulkUpdateParams &= ~SET_ORIENTATION_CHANGE_COMPLETE; 1294 if (DEBUG_ORIENTATION) Slog.v(TAG, 1295 "Orientation continue waiting for draw in " + w); 1296 } else { 1297 w.mOrientationChanging = false; 1298 if (DEBUG_ORIENTATION) Slog.v(TAG, "Orientation change complete in " + w); 1299 } 1300 } 1301 w.mToken.hasVisible = true; 1302 } 1303 } 1304 1305 void setTransparentRegionHint(final Region region) { 1306 if (mSurface == null) { 1307 Slog.w(TAG, "setTransparentRegionHint: null mSurface after mHasSurface true"); 1308 return; 1309 } 1310 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 1311 ">>> OPEN TRANSACTION setTransparentRegion"); 1312 Surface.openTransaction(); 1313 try { 1314 if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin, 1315 "transparentRegionHint=" + region, null); 1316 mSurface.setTransparentRegionHint(region); 1317 } finally { 1318 Surface.closeTransaction(); 1319 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 1320 "<<< CLOSE TRANSACTION setTransparentRegion"); 1321 } 1322 } 1323 1324 void setWallpaperOffset(int left, int top) { 1325 mSurfaceX = left; 1326 mSurfaceY = top; 1327 if (mAnimating) { 1328 // If this window (or its app token) is animating, then the position 1329 // of the surface will be re-computed on the next animation frame. 1330 // We can't poke it directly here because it depends on whatever 1331 // transformation is being applied by the animation. 1332 return; 1333 } 1334 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 1335 ">>> OPEN TRANSACTION setWallpaperOffset"); 1336 Surface.openTransaction(); 1337 try { 1338 if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin, 1339 "POS " + left + ", " + top, null); 1340 mSurface.setPosition(mWin.mFrame.left + left, mWin.mFrame.top + top); 1341 updateSurfaceWindowCrop(false); 1342 } catch (RuntimeException e) { 1343 Slog.w(TAG, "Error positioning surface of " + mWin 1344 + " pos=(" + left + "," + top + ")", e); 1345 } finally { 1346 Surface.closeTransaction(); 1347 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 1348 "<<< CLOSE TRANSACTION setWallpaperOffset"); 1349 } 1350 } 1351 1352 // This must be called while inside a transaction. 1353 boolean performShowLocked() { 1354 if (mWin.isHiddenFromUserLocked()) { 1355 Slog.w(TAG, "current user violation " + mService.mCurrentUserId + " trying to display " 1356 + this + ", type " + mWin.mAttrs.type + ", belonging to " + mWin.mOwnerUid); 1357 return false; 1358 } 1359 if (DEBUG_VISIBILITY || (DEBUG_STARTING_WINDOW && 1360 mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING)) { 1361 RuntimeException e = null; 1362 if (!WindowManagerService.HIDE_STACK_CRAWLS) { 1363 e = new RuntimeException(); 1364 e.fillInStackTrace(); 1365 } 1366 Slog.v(TAG, "performShow on " + this 1367 + ": mDrawState=" + mDrawState + " readyForDisplay=" 1368 + mWin.isReadyForDisplayIgnoringKeyguard() 1369 + " starting=" + (mWin.mAttrs.type == TYPE_APPLICATION_STARTING) 1370 + " during animation: policyVis=" + mWin.mPolicyVisibility 1371 + " attHidden=" + mWin.mAttachedHidden 1372 + " tok.hiddenRequested=" 1373 + (mWin.mAppToken != null ? mWin.mAppToken.hiddenRequested : false) 1374 + " tok.hidden=" 1375 + (mWin.mAppToken != null ? mWin.mAppToken.hidden : false) 1376 + " animating=" + mAnimating 1377 + " tok animating=" 1378 + (mAppAnimator != null ? mAppAnimator.animating : false), e); 1379 } 1380 if (mDrawState == READY_TO_SHOW && mWin.isReadyForDisplayIgnoringKeyguard()) { 1381 if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION) 1382 WindowManagerService.logSurface(mWin, "SHOW (performShowLocked)", null); 1383 if (DEBUG_VISIBILITY || (DEBUG_STARTING_WINDOW && 1384 mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING)) { 1385 Slog.v(TAG, "Showing " + this 1386 + " during animation: policyVis=" + mWin.mPolicyVisibility 1387 + " attHidden=" + mWin.mAttachedHidden 1388 + " tok.hiddenRequested=" 1389 + (mWin.mAppToken != null ? mWin.mAppToken.hiddenRequested : false) 1390 + " tok.hidden=" 1391 + (mWin.mAppToken != null ? mWin.mAppToken.hidden : false) 1392 + " animating=" + mAnimating 1393 + " tok animating=" 1394 + (mAppAnimator != null ? mAppAnimator.animating : false)); 1395 } 1396 1397 mService.enableScreenIfNeededLocked(); 1398 1399 applyEnterAnimationLocked(); 1400 1401 // Force the show in the next prepareSurfaceLocked() call. 1402 mLastAlpha = -1; 1403 if (DEBUG_SURFACE_TRACE || DEBUG_ANIM) 1404 Slog.v(TAG, "performShowLocked: mDrawState=HAS_DRAWN in " + this); 1405 mDrawState = HAS_DRAWN; 1406 mService.updateLayoutToAnimationLocked(); 1407 1408 int i = mWin.mChildWindows.size(); 1409 while (i > 0) { 1410 i--; 1411 WindowState c = mWin.mChildWindows.get(i); 1412 if (c.mAttachedHidden) { 1413 c.mAttachedHidden = false; 1414 if (c.mWinAnimator.mSurface != null) { 1415 c.mWinAnimator.performShowLocked(); 1416 // It hadn't been shown, which means layout not 1417 // performed on it, so now we want to make sure to 1418 // do a layout. If called from within the transaction 1419 // loop, this will cause it to restart with a new 1420 // layout. 1421 c.mDisplayContent.layoutNeeded = true; 1422 } 1423 } 1424 } 1425 1426 if (mWin.mAttrs.type != TYPE_APPLICATION_STARTING 1427 && mWin.mAppToken != null) { 1428 mWin.mAppToken.firstWindowDrawn = true; 1429 1430 if (mWin.mAppToken.startingData != null) { 1431 if (WindowManagerService.DEBUG_STARTING_WINDOW || 1432 WindowManagerService.DEBUG_ANIM) Slog.v(TAG, 1433 "Finish starting " + mWin.mToken 1434 + ": first real window is shown, no animation"); 1435 // If this initial window is animating, stop it -- we 1436 // will do an animation to reveal it from behind the 1437 // starting window, so there is no need for it to also 1438 // be doing its own stuff. 1439 clearAnimation(); 1440 mService.mFinishedStarting.add(mWin.mAppToken); 1441 mService.mH.sendEmptyMessage(H.FINISHED_STARTING); 1442 } 1443 mWin.mAppToken.updateReportedVisibilityLocked(); 1444 } 1445 1446 return true; 1447 } 1448 1449 return false; 1450 } 1451 1452 /** 1453 * Have the surface flinger show a surface, robustly dealing with 1454 * error conditions. In particular, if there is not enough memory 1455 * to show the surface, then we will try to get rid of other surfaces 1456 * in order to succeed. 1457 * 1458 * @return Returns true if the surface was successfully shown. 1459 */ 1460 boolean showSurfaceRobustlyLocked() { 1461 try { 1462 if (mSurface != null) { 1463 mSurfaceShown = true; 1464 mSurface.show(); 1465 if (mWin.mTurnOnScreen) { 1466 if (DEBUG_VISIBILITY) Slog.v(TAG, 1467 "Show surface turning screen on: " + mWin); 1468 mWin.mTurnOnScreen = false; 1469 mAnimator.mBulkUpdateParams |= SET_TURN_ON_SCREEN; 1470 } 1471 } 1472 return true; 1473 } catch (RuntimeException e) { 1474 Slog.w(TAG, "Failure showing surface " + mSurface + " in " + mWin, e); 1475 } 1476 1477 mService.reclaimSomeSurfaceMemoryLocked(this, "show", true); 1478 1479 return false; 1480 } 1481 1482 void applyEnterAnimationLocked() { 1483 final int transit; 1484 if (mEnterAnimationPending) { 1485 mEnterAnimationPending = false; 1486 transit = WindowManagerPolicy.TRANSIT_ENTER; 1487 } else { 1488 transit = WindowManagerPolicy.TRANSIT_SHOW; 1489 } 1490 applyAnimationLocked(transit, true); 1491 mService.scheduleNotifyWindowTranstionIfNeededLocked(mWin, transit); 1492 } 1493 1494 // TODO(cmautner): Move back to WindowState? 1495 /** 1496 * Choose the correct animation and set it to the passed WindowState. 1497 * @param transit If WindowManagerPolicy.TRANSIT_PREVIEW_DONE and the app window has been drawn 1498 * then the animation will be app_starting_exit. Any other value loads the animation from 1499 * the switch statement below. 1500 * @param isEntrance The animation type the last time this was called. Used to keep from 1501 * loading the same animation twice. 1502 * @return true if an animation has been loaded. 1503 */ 1504 boolean applyAnimationLocked(int transit, boolean isEntrance) { 1505 if (mLocalAnimating && mAnimationIsEntrance == isEntrance) { 1506 // If we are trying to apply an animation, but already running 1507 // an animation of the same type, then just leave that one alone. 1508 return true; 1509 } 1510 1511 // Only apply an animation if the display isn't frozen. If it is 1512 // frozen, there is no reason to animate and it can cause strange 1513 // artifacts when we unfreeze the display if some different animation 1514 // is running. 1515 if (mService.okToDisplay()) { 1516 int anim = mPolicy.selectAnimationLw(mWin, transit); 1517 int attr = -1; 1518 Animation a = null; 1519 if (anim != 0) { 1520 a = anim != -1 ? AnimationUtils.loadAnimation(mContext, anim) : null; 1521 } else { 1522 switch (transit) { 1523 case WindowManagerPolicy.TRANSIT_ENTER: 1524 attr = com.android.internal.R.styleable.WindowAnimation_windowEnterAnimation; 1525 break; 1526 case WindowManagerPolicy.TRANSIT_EXIT: 1527 attr = com.android.internal.R.styleable.WindowAnimation_windowExitAnimation; 1528 break; 1529 case WindowManagerPolicy.TRANSIT_SHOW: 1530 attr = com.android.internal.R.styleable.WindowAnimation_windowShowAnimation; 1531 break; 1532 case WindowManagerPolicy.TRANSIT_HIDE: 1533 attr = com.android.internal.R.styleable.WindowAnimation_windowHideAnimation; 1534 break; 1535 } 1536 if (attr >= 0) { 1537 a = mService.loadAnimation(UserHandle.getUserId(mWin.mOwnerUid), 1538 mWin.mAttrs, attr); 1539 } 1540 } 1541 if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG, 1542 "applyAnimation: win=" + this 1543 + " anim=" + anim + " attr=0x" + Integer.toHexString(attr) 1544 + " a=" + a 1545 + " transit=" + transit 1546 + " isEntrance=" + isEntrance + " Callers " + Debug.getCallers(3)); 1547 if (a != null) { 1548 if (WindowManagerService.DEBUG_ANIM) { 1549 RuntimeException e = null; 1550 if (!WindowManagerService.HIDE_STACK_CRAWLS) { 1551 e = new RuntimeException(); 1552 e.fillInStackTrace(); 1553 } 1554 Slog.v(TAG, "Loaded animation " + a + " for " + this, e); 1555 } 1556 setAnimation(a); 1557 mAnimationIsEntrance = isEntrance; 1558 } 1559 } else { 1560 clearAnimation(); 1561 } 1562 1563 return mAnimation != null; 1564 } 1565 1566 public void dump(PrintWriter pw, String prefix, boolean dumpAll) { 1567 if (mAnimating || mLocalAnimating || mAnimationIsEntrance 1568 || mAnimation != null) { 1569 pw.print(prefix); pw.print("mAnimating="); pw.print(mAnimating); 1570 pw.print(" mLocalAnimating="); pw.print(mLocalAnimating); 1571 pw.print(" mAnimationIsEntrance="); pw.print(mAnimationIsEntrance); 1572 pw.print(" mAnimation="); pw.println(mAnimation); 1573 } 1574 if (mHasTransformation || mHasLocalTransformation) { 1575 pw.print(prefix); pw.print("XForm: has="); 1576 pw.print(mHasTransformation); 1577 pw.print(" hasLocal="); pw.print(mHasLocalTransformation); 1578 pw.print(" "); mTransformation.printShortString(pw); 1579 pw.println(); 1580 } 1581 if (mSurface != null) { 1582 if (dumpAll) { 1583 pw.print(prefix); pw.print("mSurface="); pw.println(mSurface); 1584 pw.print(prefix); pw.print("mDrawState="); 1585 pw.print(drawStateToString(mDrawState)); 1586 pw.print(" mLastHidden="); pw.println(mLastHidden); 1587 } 1588 pw.print(prefix); pw.print("Surface: shown="); pw.print(mSurfaceShown); 1589 pw.print(" layer="); pw.print(mSurfaceLayer); 1590 pw.print(" alpha="); pw.print(mSurfaceAlpha); 1591 pw.print(" rect=("); pw.print(mSurfaceX); 1592 pw.print(","); pw.print(mSurfaceY); 1593 pw.print(") "); pw.print(mSurfaceW); 1594 pw.print(" x "); pw.println(mSurfaceH); 1595 } 1596 if (mPendingDestroySurface != null) { 1597 pw.print(prefix); pw.print("mPendingDestroySurface="); 1598 pw.println(mPendingDestroySurface); 1599 } 1600 if (mSurfaceResized || mSurfaceDestroyDeferred) { 1601 pw.print(prefix); pw.print("mSurfaceResized="); pw.print(mSurfaceResized); 1602 pw.print(" mSurfaceDestroyDeferred="); pw.println(mSurfaceDestroyDeferred); 1603 } 1604 if (mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND) { 1605 pw.print(prefix); pw.print("mUniverseTransform="); 1606 mUniverseTransform.printShortString(pw); 1607 pw.println(); 1608 } 1609 if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) { 1610 pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha); 1611 pw.print(" mAlpha="); pw.print(mAlpha); 1612 pw.print(" mLastAlpha="); pw.println(mLastAlpha); 1613 } 1614 if (mHaveMatrix || mWin.mGlobalScale != 1) { 1615 pw.print(prefix); pw.print("mGlobalScale="); pw.print(mWin.mGlobalScale); 1616 pw.print(" mDsDx="); pw.print(mDsDx); 1617 pw.print(" mDtDx="); pw.print(mDtDx); 1618 pw.print(" mDsDy="); pw.print(mDsDy); 1619 pw.print(" mDtDy="); pw.println(mDtDy); 1620 } 1621 } 1622 1623 @Override 1624 public String toString() { 1625 StringBuffer sb = new StringBuffer("WindowStateAnimator{"); 1626 sb.append(Integer.toHexString(System.identityHashCode(this))); 1627 sb.append(' '); 1628 sb.append(mWin.mAttrs.getTitle()); 1629 sb.append('}'); 1630 return sb.toString(); 1631 } 1632} 1633