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