Home | History | Annotate | Download | only in wm
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.server.wm;
     18 
     19 import static android.app.ActivityManager.StackId;
     20 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
     21 import static android.view.Display.DEFAULT_DISPLAY;
     22 import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
     23 import static android.view.WindowManager.LayoutParams.FLAG_SCALED;
     24 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
     25 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
     26 import static com.android.server.wm.AppWindowAnimator.sDummyAnimation;
     27 import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM;
     28 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
     29 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
     30 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
     31 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
     32 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
     33 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
     34 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE;
     35 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
     36 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
     37 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_CROP;
     38 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
     39 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC;
     40 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
     41 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
     42 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
     43 import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER;
     44 import static com.android.server.wm.WindowManagerService.localLOGV;
     45 import static com.android.server.wm.WindowManagerService.logWithStack;
     46 import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
     47 import static com.android.server.wm.WindowSurfacePlacer.SET_TURN_ON_SCREEN;
     48 
     49 import android.content.Context;
     50 import android.graphics.Matrix;
     51 import android.graphics.PixelFormat;
     52 import android.graphics.Point;
     53 import android.graphics.Rect;
     54 import android.graphics.Region;
     55 import android.os.Debug;
     56 import android.os.RemoteException;
     57 import android.util.Slog;
     58 import android.view.DisplayInfo;
     59 import android.view.MagnificationSpec;
     60 import android.view.Surface.OutOfResourcesException;
     61 import android.view.SurfaceControl;
     62 import android.view.WindowManager;
     63 import android.view.WindowManager.LayoutParams;
     64 import android.view.WindowManagerPolicy;
     65 import android.view.animation.Animation;
     66 import android.view.animation.AnimationSet;
     67 import android.view.animation.AnimationUtils;
     68 import android.view.animation.Transformation;
     69 
     70 import com.android.server.wm.WindowManagerService.H;
     71 
     72 import java.io.PrintWriter;
     73 
     74 /**
     75  * Keep track of animations and surface operations for a single WindowState.
     76  **/
     77 class WindowStateAnimator {
     78     static final String TAG = TAG_WITH_CLASS_NAME ? "WindowStateAnimator" : TAG_WM;
     79     static final int WINDOW_FREEZE_LAYER = TYPE_LAYER_MULTIPLIER * 200;
     80 
     81     /**
     82      * Mode how the window gets clipped by the stack bounds during an animation: The clipping should
     83      * be applied after applying the animation transformation, i.e. the stack bounds don't move
     84      * during the animation.
     85      */
     86     static final int STACK_CLIP_AFTER_ANIM = 0;
     87 
     88     /**
     89      * Mode how the window gets clipped by the stack bounds: The clipping should be applied before
     90      * applying the animation transformation, i.e. the stack bounds move with the window.
     91      */
     92     static final int STACK_CLIP_BEFORE_ANIM = 1;
     93 
     94     /**
     95      * Mode how window gets clipped by the stack bounds during an animation: Don't clip the window
     96      * by the stack bounds.
     97      */
     98     static final int STACK_CLIP_NONE = 2;
     99 
    100     // Unchanging local convenience fields.
    101     final WindowManagerService mService;
    102     final WindowState mWin;
    103     final WindowStateAnimator mAttachedWinAnimator;
    104     final WindowAnimator mAnimator;
    105     AppWindowAnimator mAppAnimator;
    106     final Session mSession;
    107     final WindowManagerPolicy mPolicy;
    108     final Context mContext;
    109     final boolean mIsWallpaper;
    110     final WallpaperController mWallpaperControllerLocked;
    111 
    112     // Currently running animation.
    113     boolean mAnimating;
    114     boolean mLocalAnimating;
    115     Animation mAnimation;
    116     boolean mAnimationIsEntrance;
    117     boolean mHasTransformation;
    118     boolean mHasLocalTransformation;
    119     final Transformation mTransformation = new Transformation();
    120     boolean mWasAnimating;      // Were we animating going into the most recent animation step?
    121     int mAnimLayer;
    122     int mLastLayer;
    123     long mAnimationStartTime;
    124     long mLastAnimationTime;
    125     int mStackClip = STACK_CLIP_BEFORE_ANIM;
    126 
    127     /**
    128      * Set when we have changed the size of the surface, to know that
    129      * we must tell them application to resize (and thus redraw itself).
    130      */
    131     boolean mSurfaceResized;
    132     /**
    133      * Whether we should inform the client on next relayoutWindow that
    134      * the surface has been resized since last time.
    135      */
    136     boolean mReportSurfaceResized;
    137     WindowSurfaceController mSurfaceController;
    138     private WindowSurfaceController mPendingDestroySurface;
    139 
    140     /**
    141      * Set if the client has asked that the destroy of its surface be delayed
    142      * until it explicitly says it is okay.
    143      */
    144     boolean mSurfaceDestroyDeferred;
    145 
    146     private boolean mDestroyPreservedSurfaceUponRedraw;
    147     float mShownAlpha = 0;
    148     float mAlpha = 0;
    149     float mLastAlpha = 0;
    150 
    151     boolean mHasClipRect;
    152     Rect mClipRect = new Rect();
    153     Rect mTmpClipRect = new Rect();
    154     Rect mTmpFinalClipRect = new Rect();
    155     Rect mLastClipRect = new Rect();
    156     Rect mLastFinalClipRect = new Rect();
    157     Rect mTmpStackBounds = new Rect();
    158 
    159     /**
    160      * This is rectangle of the window's surface that is not covered by
    161      * system decorations.
    162      */
    163     private final Rect mSystemDecorRect = new Rect();
    164     private final Rect mLastSystemDecorRect = new Rect();
    165 
    166     // Used to save animation distances between the time they are calculated and when they are used.
    167     private int mAnimDx;
    168     private int mAnimDy;
    169 
    170     /** Is the next animation to be started a window move animation? */
    171     private boolean mAnimateMove = false;
    172 
    173     float mDsDx=1, mDtDx=0, mDsDy=0, mDtDy=1;
    174     float mLastDsDx=1, mLastDtDx=0, mLastDsDy=0, mLastDtDy=1;
    175 
    176     boolean mHaveMatrix;
    177 
    178     // Set to true if, when the window gets displayed, it should perform
    179     // an enter animation.
    180     boolean mEnterAnimationPending;
    181 
    182     /** Used to indicate that this window is undergoing an enter animation. Used for system
    183      * windows to make the callback to View.dispatchOnWindowShownCallback(). Set when the
    184      * window is first added or shown, cleared when the callback has been made. */
    185     boolean mEnteringAnimation;
    186 
    187     private boolean mAnimationStartDelayed;
    188 
    189     boolean mKeyguardGoingAwayAnimation;
    190     boolean mKeyguardGoingAwayWithWallpaper;
    191 
    192     /** The pixel format of the underlying SurfaceControl */
    193     int mSurfaceFormat;
    194 
    195     /** This is set when there is no Surface */
    196     static final int NO_SURFACE = 0;
    197     /** This is set after the Surface has been created but before the window has been drawn. During
    198      * this time the surface is hidden. */
    199     static final int DRAW_PENDING = 1;
    200     /** This is set after the window has finished drawing for the first time but before its surface
    201      * is shown.  The surface will be displayed when the next layout is run. */
    202     static final int COMMIT_DRAW_PENDING = 2;
    203     /** This is set during the time after the window's drawing has been committed, and before its
    204      * surface is actually shown.  It is used to delay showing the surface until all windows in a
    205      * token are ready to be shown. */
    206     static final int READY_TO_SHOW = 3;
    207     /** Set when the window has been shown in the screen the first time. */
    208     static final int HAS_DRAWN = 4;
    209 
    210     String drawStateToString() {
    211         switch (mDrawState) {
    212             case NO_SURFACE: return "NO_SURFACE";
    213             case DRAW_PENDING: return "DRAW_PENDING";
    214             case COMMIT_DRAW_PENDING: return "COMMIT_DRAW_PENDING";
    215             case READY_TO_SHOW: return "READY_TO_SHOW";
    216             case HAS_DRAWN: return "HAS_DRAWN";
    217             default: return Integer.toString(mDrawState);
    218         }
    219     }
    220     int mDrawState;
    221 
    222     /** Was this window last hidden? */
    223     boolean mLastHidden;
    224 
    225     int mAttrType;
    226 
    227     static final long PENDING_TRANSACTION_FINISH_WAIT_TIME = 100;
    228     long mDeferTransactionUntilFrame = -1;
    229     long mDeferTransactionTime = -1;
    230 
    231     boolean mForceScaleUntilResize;
    232 
    233     // WindowState.mHScale and WindowState.mVScale contain the
    234     // scale according to client specified layout parameters (e.g.
    235     // one layout size, with another surface size, creates such scaling).
    236     // Here we track an additional scaling factor used to follow stack
    237     // scaling (as in the case of the Pinned stack animation).
    238     float mExtraHScale = (float) 1.0;
    239     float mExtraVScale = (float) 1.0;
    240 
    241     private final Rect mTmpSize = new Rect();
    242 
    243     WindowStateAnimator(final WindowState win) {
    244         final WindowManagerService service = win.mService;
    245 
    246         mService = service;
    247         mAnimator = service.mAnimator;
    248         mPolicy = service.mPolicy;
    249         mContext = service.mContext;
    250         final DisplayContent displayContent = win.getDisplayContent();
    251         if (displayContent != null) {
    252             final DisplayInfo displayInfo = displayContent.getDisplayInfo();
    253             mAnimDx = displayInfo.appWidth;
    254             mAnimDy = displayInfo.appHeight;
    255         } else {
    256             Slog.w(TAG, "WindowStateAnimator ctor: Display has been removed");
    257             // This is checked on return and dealt with.
    258         }
    259 
    260         mWin = win;
    261         mAttachedWinAnimator = win.mAttachedWindow == null
    262                 ? null : win.mAttachedWindow.mWinAnimator;
    263         mAppAnimator = win.mAppToken == null ? null : win.mAppToken.mAppAnimator;
    264         mSession = win.mSession;
    265         mAttrType = win.mAttrs.type;
    266         mIsWallpaper = win.mIsWallpaper;
    267         mWallpaperControllerLocked = mService.mWallpaperControllerLocked;
    268     }
    269 
    270     public void setAnimation(Animation anim, long startTime, int stackClip) {
    271         if (localLOGV) Slog.v(TAG, "Setting animation in " + this + ": " + anim);
    272         mAnimating = false;
    273         mLocalAnimating = false;
    274         mAnimation = anim;
    275         mAnimation.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION);
    276         mAnimation.scaleCurrentDuration(mService.getWindowAnimationScaleLocked());
    277         // Start out animation gone if window is gone, or visible if window is visible.
    278         mTransformation.clear();
    279         mTransformation.setAlpha(mLastHidden ? 0 : 1);
    280         mHasLocalTransformation = true;
    281         mAnimationStartTime = startTime;
    282         mStackClip = stackClip;
    283     }
    284 
    285     public void setAnimation(Animation anim, int stackClip) {
    286         setAnimation(anim, -1, stackClip);
    287     }
    288 
    289     public void setAnimation(Animation anim) {
    290         setAnimation(anim, -1, STACK_CLIP_AFTER_ANIM);
    291     }
    292 
    293     public void clearAnimation() {
    294         if (mAnimation != null) {
    295             mAnimating = true;
    296             mLocalAnimating = false;
    297             mAnimation.cancel();
    298             mAnimation = null;
    299             mKeyguardGoingAwayAnimation = false;
    300             mKeyguardGoingAwayWithWallpaper = false;
    301             mStackClip = STACK_CLIP_BEFORE_ANIM;
    302         }
    303     }
    304 
    305     /**
    306      * Is the window or its container currently set to animate or currently animating?
    307      */
    308     boolean isAnimationSet() {
    309         return mAnimation != null
    310                 || (mAttachedWinAnimator != null && mAttachedWinAnimator.mAnimation != null)
    311                 || (mAppAnimator != null && mAppAnimator.isAnimating());
    312     }
    313 
    314     /**
    315      * @return whether an animation is about to start, i.e. the animation is set already but we
    316      *         haven't processed the first frame yet.
    317      */
    318     boolean isAnimationStarting() {
    319         return isAnimationSet() && !mAnimating;
    320     }
    321 
    322     /** Is the window animating the DummyAnimation? */
    323     boolean isDummyAnimation() {
    324         return mAppAnimator != null
    325                 && mAppAnimator.animation == sDummyAnimation;
    326     }
    327 
    328     /**
    329      * Is this window currently set to animate or currently animating?
    330      */
    331     boolean isWindowAnimationSet() {
    332         return mAnimation != null;
    333     }
    334 
    335     /**
    336      * Is this window currently waiting to run an opening animation?
    337      */
    338     boolean isWaitingForOpening() {
    339         return mService.mAppTransition.isTransitionSet() && isDummyAnimation()
    340                 && mService.mOpeningApps.contains(mWin.mAppToken);
    341     }
    342 
    343     void cancelExitAnimationForNextAnimationLocked() {
    344         if (DEBUG_ANIM) Slog.d(TAG,
    345                 "cancelExitAnimationForNextAnimationLocked: " + mWin);
    346 
    347         if (mAnimation != null) {
    348             mAnimation.cancel();
    349             mAnimation = null;
    350             mLocalAnimating = false;
    351             mWin.destroyOrSaveSurface();
    352         }
    353     }
    354 
    355     private boolean stepAnimation(long currentTime) {
    356         if ((mAnimation == null) || !mLocalAnimating) {
    357             return false;
    358         }
    359         currentTime = getAnimationFrameTime(mAnimation, currentTime);
    360         mTransformation.clear();
    361         final boolean more = mAnimation.getTransformation(currentTime, mTransformation);
    362         if (mAnimationStartDelayed && mAnimationIsEntrance) {
    363             mTransformation.setAlpha(0f);
    364         }
    365         if (false && DEBUG_ANIM) Slog.v(TAG, "Stepped animation in " + this + ": more=" + more
    366                 + ", xform=" + mTransformation);
    367         return more;
    368     }
    369 
    370     // This must be called while inside a transaction.  Returns true if
    371     // there is more animation to run.
    372     boolean stepAnimationLocked(long currentTime) {
    373         // Save the animation state as it was before this step so WindowManagerService can tell if
    374         // we just started or just stopped animating by comparing mWasAnimating with isAnimationSet().
    375         mWasAnimating = mAnimating;
    376         final DisplayContent displayContent = mWin.getDisplayContent();
    377         if (displayContent != null && mService.okToDisplay()) {
    378             // We will run animations as long as the display isn't frozen.
    379 
    380             if (mWin.isDrawnLw() && mAnimation != null) {
    381                 mHasTransformation = true;
    382                 mHasLocalTransformation = true;
    383                 if (!mLocalAnimating) {
    384                     if (DEBUG_ANIM) Slog.v(
    385                         TAG, "Starting animation in " + this +
    386                         " @ " + currentTime + ": ww=" + mWin.mFrame.width() +
    387                         " wh=" + mWin.mFrame.height() +
    388                         " dx=" + mAnimDx + " dy=" + mAnimDy +
    389                         " scale=" + mService.getWindowAnimationScaleLocked());
    390                     final DisplayInfo displayInfo = displayContent.getDisplayInfo();
    391                     if (mAnimateMove) {
    392                         mAnimateMove = false;
    393                         mAnimation.initialize(mWin.mFrame.width(), mWin.mFrame.height(),
    394                                 mAnimDx, mAnimDy);
    395                     } else {
    396                         mAnimation.initialize(mWin.mFrame.width(), mWin.mFrame.height(),
    397                                 displayInfo.appWidth, displayInfo.appHeight);
    398                     }
    399                     mAnimDx = displayInfo.appWidth;
    400                     mAnimDy = displayInfo.appHeight;
    401                     mAnimation.setStartTime(mAnimationStartTime != -1
    402                             ? mAnimationStartTime
    403                             : currentTime);
    404                     mLocalAnimating = true;
    405                     mAnimating = true;
    406                 }
    407                 if ((mAnimation != null) && mLocalAnimating) {
    408                     mLastAnimationTime = currentTime;
    409                     if (stepAnimation(currentTime)) {
    410                         return true;
    411                     }
    412                 }
    413                 if (DEBUG_ANIM) Slog.v(
    414                     TAG, "Finished animation in " + this +
    415                     " @ " + currentTime);
    416                 //WindowManagerService.this.dump();
    417             }
    418             mHasLocalTransformation = false;
    419             if ((!mLocalAnimating || mAnimationIsEntrance) && mAppAnimator != null
    420                     && mAppAnimator.animation != null) {
    421                 // When our app token is animating, we kind-of pretend like
    422                 // we are as well.  Note the mLocalAnimating mAnimationIsEntrance
    423                 // part of this check means that we will only do this if
    424                 // our window is not currently exiting, or it is not
    425                 // locally animating itself.  The idea being that one that
    426                 // is exiting and doing a local animation should be removed
    427                 // once that animation is done.
    428                 mAnimating = true;
    429                 mHasTransformation = true;
    430                 mTransformation.clear();
    431                 return false;
    432             } else if (mHasTransformation) {
    433                 // Little trick to get through the path below to act like
    434                 // we have finished an animation.
    435                 mAnimating = true;
    436             } else if (isAnimationSet()) {
    437                 mAnimating = true;
    438             }
    439         } else if (mAnimation != null) {
    440             // If the display is frozen, and there is a pending animation,
    441             // clear it and make sure we run the cleanup code.
    442             mAnimating = true;
    443         }
    444 
    445         if (!mAnimating && !mLocalAnimating) {
    446             return false;
    447         }
    448 
    449         // Done animating, clean up.
    450         if (DEBUG_ANIM) Slog.v(
    451             TAG, "Animation done in " + this + ": exiting=" + mWin.mAnimatingExit
    452             + ", reportedVisible="
    453             + (mWin.mAppToken != null ? mWin.mAppToken.reportedVisible : false));
    454 
    455         mAnimating = false;
    456         mKeyguardGoingAwayAnimation = false;
    457         mKeyguardGoingAwayWithWallpaper = false;
    458         mLocalAnimating = false;
    459         if (mAnimation != null) {
    460             mAnimation.cancel();
    461             mAnimation = null;
    462         }
    463         if (mAnimator.mWindowDetachedWallpaper == mWin) {
    464             mAnimator.mWindowDetachedWallpaper = null;
    465         }
    466         mAnimLayer = mWin.mLayer
    467                 + mService.mLayersController.getSpecialWindowAnimLayerAdjustment(mWin);
    468         if (DEBUG_LAYERS) Slog.v(TAG, "Stepping win " + this + " anim layer: " + mAnimLayer);
    469         mHasTransformation = false;
    470         mHasLocalTransformation = false;
    471         mStackClip = STACK_CLIP_BEFORE_ANIM;
    472         mWin.checkPolicyVisibilityChange();
    473         mTransformation.clear();
    474         if (mDrawState == HAS_DRAWN
    475                 && mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
    476                 && mWin.mAppToken != null
    477                 && mWin.mAppToken.firstWindowDrawn
    478                 && mWin.mAppToken.startingData != null) {
    479             if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Finish starting "
    480                     + mWin.mToken + ": first real window done animating");
    481             mService.mFinishedStarting.add(mWin.mAppToken);
    482             mService.mH.sendEmptyMessage(H.FINISHED_STARTING);
    483         } else if (mAttrType == LayoutParams.TYPE_STATUS_BAR && mWin.mPolicyVisibility) {
    484             // Upon completion of a not-visible to visible status bar animation a relayout is
    485             // required.
    486             if (displayContent != null) {
    487                 displayContent.layoutNeeded = true;
    488             }
    489         }
    490 
    491         finishExit();
    492         final int displayId = mWin.getDisplayId();
    493         mAnimator.setPendingLayoutChanges(displayId, WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM);
    494         if (DEBUG_LAYOUT_REPEATS)
    495             mService.mWindowPlacerLocked.debugLayoutRepeats(
    496                     "WindowStateAnimator", mAnimator.getPendingLayoutChanges(displayId));
    497 
    498         if (mWin.mAppToken != null) {
    499             mWin.mAppToken.updateReportedVisibilityLocked();
    500         }
    501 
    502         return false;
    503     }
    504 
    505     void finishExit() {
    506         if (DEBUG_ANIM) Slog.v(
    507                 TAG, "finishExit in " + this
    508                 + ": exiting=" + mWin.mAnimatingExit
    509                 + " remove=" + mWin.mRemoveOnExit
    510                 + " windowAnimating=" + isWindowAnimationSet());
    511 
    512         if (!mWin.mChildWindows.isEmpty()) {
    513             // Copying to a different list as multiple children can be removed.
    514             final WindowList childWindows = new WindowList(mWin.mChildWindows);
    515             for (int i = childWindows.size() - 1; i >= 0; i--) {
    516                 childWindows.get(i).mWinAnimator.finishExit();
    517             }
    518         }
    519 
    520         if (mEnteringAnimation) {
    521             mEnteringAnimation = false;
    522             mService.requestTraversal();
    523             // System windows don't have an activity and an app token as a result, but need a way
    524             // to be informed about their entrance animation end.
    525             if (mWin.mAppToken == null) {
    526                 try {
    527                     mWin.mClient.dispatchWindowShown();
    528                 } catch (RemoteException e) {
    529                 }
    530             }
    531         }
    532 
    533         if (!isWindowAnimationSet()) {
    534             //TODO (multidisplay): Accessibility is supported only for the default display.
    535             if (mService.mAccessibilityController != null
    536                     && mWin.getDisplayId() == DEFAULT_DISPLAY) {
    537                 mService.mAccessibilityController.onSomeWindowResizedOrMovedLocked();
    538             }
    539         }
    540 
    541         if (!mWin.mAnimatingExit) {
    542             return;
    543         }
    544 
    545         if (isWindowAnimationSet()) {
    546             return;
    547         }
    548 
    549         if (WindowManagerService.localLOGV || DEBUG_ADD_REMOVE) Slog.v(TAG,
    550                 "Exit animation finished in " + this + ": remove=" + mWin.mRemoveOnExit);
    551 
    552 
    553         mWin.mDestroying = true;
    554 
    555         final boolean hasSurface = hasSurface();
    556         if (hasSurface) {
    557             hide("finishExit");
    558         }
    559 
    560         // If we have an app token, we ask it to destroy the surface for us,
    561         // so that it can take care to ensure the activity has actually stopped
    562         // and the surface is not still in use. Otherwise we add the service to
    563         // mDestroySurface and allow it to be processed in our next transaction.
    564         if (mWin.mAppToken != null) {
    565             mWin.mAppToken.destroySurfaces();
    566         } else {
    567             if (hasSurface) {
    568                 mService.mDestroySurface.add(mWin);
    569             }
    570             if (mWin.mRemoveOnExit) {
    571                 mService.mPendingRemove.add(mWin);
    572                 mWin.mRemoveOnExit = false;
    573             }
    574         }
    575         mWin.mAnimatingExit = false;
    576         mWallpaperControllerLocked.hideWallpapers(mWin);
    577     }
    578 
    579     void hide(String reason) {
    580         if (!mLastHidden) {
    581             //dump();
    582             mLastHidden = true;
    583             if (mSurfaceController != null) {
    584                 mSurfaceController.hideInTransaction(reason);
    585             }
    586         }
    587     }
    588 
    589     boolean finishDrawingLocked() {
    590         final boolean startingWindow =
    591                 mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
    592         if (DEBUG_STARTING_WINDOW && startingWindow) {
    593             Slog.v(TAG, "Finishing drawing window " + mWin + ": mDrawState="
    594                     + drawStateToString());
    595         }
    596 
    597         boolean layoutNeeded = mWin.clearAnimatingWithSavedSurface();
    598 
    599         if (mDrawState == DRAW_PENDING) {
    600             if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || SHOW_TRANSACTIONS || DEBUG_ORIENTATION)
    601                 Slog.v(TAG, "finishDrawingLocked: mDrawState=COMMIT_DRAW_PENDING " + mWin + " in "
    602                         + mSurfaceController);
    603             if (DEBUG_STARTING_WINDOW && startingWindow) {
    604                 Slog.v(TAG, "Draw state now committed in " + mWin);
    605             }
    606             mDrawState = COMMIT_DRAW_PENDING;
    607             layoutNeeded = true;
    608         }
    609 
    610         return layoutNeeded;
    611     }
    612 
    613     // This must be called while inside a transaction.
    614     boolean commitFinishDrawingLocked() {
    615         if (DEBUG_STARTING_WINDOW &&
    616                 mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
    617             Slog.i(TAG, "commitFinishDrawingLocked: " + mWin + " cur mDrawState="
    618                     + drawStateToString());
    619         }
    620         if (mDrawState != COMMIT_DRAW_PENDING && mDrawState != READY_TO_SHOW) {
    621             return false;
    622         }
    623         if (DEBUG_SURFACE_TRACE || DEBUG_ANIM) {
    624             Slog.i(TAG, "commitFinishDrawingLocked: mDrawState=READY_TO_SHOW " + mSurfaceController);
    625         }
    626         mDrawState = READY_TO_SHOW;
    627         boolean result = false;
    628         final AppWindowToken atoken = mWin.mAppToken;
    629         if (atoken == null || atoken.allDrawn || mWin.mAttrs.type == TYPE_APPLICATION_STARTING) {
    630             result = performShowLocked();
    631         }
    632         return result;
    633     }
    634 
    635     void preserveSurfaceLocked() {
    636         if (mDestroyPreservedSurfaceUponRedraw) {
    637             // This could happen when switching the surface mode very fast. For example,
    638             // we preserved a surface when dragResizing changed to true. Then before the
    639             // preserved surface is removed, dragResizing changed to false again.
    640             // In this case, we need to leave the preserved surface alone, and destroy
    641             // the actual surface, so that the createSurface call could create a surface
    642             // of the proper size. The preserved surface will still be removed when client
    643             // finishes drawing to the new surface.
    644             mSurfaceDestroyDeferred = false;
    645             destroySurfaceLocked();
    646             mSurfaceDestroyDeferred = true;
    647             return;
    648         }
    649         if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin, "SET FREEZE LAYER", false);
    650         if (mSurfaceController != null) {
    651             mSurfaceController.setLayer(mAnimLayer + 1);
    652         }
    653         mDestroyPreservedSurfaceUponRedraw = true;
    654         mSurfaceDestroyDeferred = true;
    655         destroySurfaceLocked();
    656     }
    657 
    658     void destroyPreservedSurfaceLocked() {
    659         if (!mDestroyPreservedSurfaceUponRedraw) {
    660             return;
    661         }
    662         destroyDeferredSurfaceLocked();
    663         mDestroyPreservedSurfaceUponRedraw = false;
    664     }
    665 
    666     void markPreservedSurfaceForDestroy() {
    667         if (mDestroyPreservedSurfaceUponRedraw
    668                 && !mService.mDestroyPreservedSurface.contains(mWin)) {
    669             mService.mDestroyPreservedSurface.add(mWin);
    670         }
    671     }
    672 
    673     WindowSurfaceController createSurfaceLocked() {
    674         final WindowState w = mWin;
    675         if (w.hasSavedSurface()) {
    676             if (DEBUG_ANIM) Slog.i(TAG,
    677                     "createSurface: " + this + ": called when we had a saved surface");
    678             w.restoreSavedSurface();
    679             return mSurfaceController;
    680         }
    681 
    682         if (mSurfaceController != null) {
    683             return mSurfaceController;
    684         }
    685 
    686         w.setHasSurface(false);
    687 
    688         if (DEBUG_ANIM || DEBUG_ORIENTATION) Slog.i(TAG,
    689                 "createSurface " + this + ": mDrawState=DRAW_PENDING");
    690 
    691         mDrawState = DRAW_PENDING;
    692         if (w.mAppToken != null) {
    693             if (w.mAppToken.mAppAnimator.animation == null) {
    694                 w.mAppToken.clearAllDrawn();
    695             } else {
    696                 // Currently animating, persist current state of allDrawn until animation
    697                 // is complete.
    698                 w.mAppToken.deferClearAllDrawn = true;
    699             }
    700         }
    701 
    702         mService.makeWindowFreezingScreenIfNeededLocked(w);
    703 
    704         int flags = SurfaceControl.HIDDEN;
    705         final WindowManager.LayoutParams attrs = w.mAttrs;
    706 
    707         if (mService.isSecureLocked(w)) {
    708             flags |= SurfaceControl.SECURE;
    709         }
    710 
    711         mTmpSize.set(w.mFrame.left + w.mXOffset, w.mFrame.top + w.mYOffset, 0, 0);
    712         calculateSurfaceBounds(w, attrs);
    713         final int width = mTmpSize.width();
    714         final int height = mTmpSize.height();
    715 
    716         if (DEBUG_VISIBILITY) {
    717             Slog.v(TAG, "Creating surface in session "
    718                     + mSession.mSurfaceSession + " window " + this
    719                     + " w=" + width + " h=" + height
    720                     + " x=" + mTmpSize.left + " y=" + mTmpSize.top
    721                     + " format=" + attrs.format + " flags=" + flags);
    722         }
    723 
    724         // We may abort, so initialize to defaults.
    725         mLastSystemDecorRect.set(0, 0, 0, 0);
    726         mHasClipRect = false;
    727         mClipRect.set(0, 0, 0, 0);
    728         mLastClipRect.set(0, 0, 0, 0);
    729 
    730         // Set up surface control with initial size.
    731         try {
    732 
    733             final boolean isHwAccelerated = (attrs.flags & FLAG_HARDWARE_ACCELERATED) != 0;
    734             final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format;
    735             if (!PixelFormat.formatHasAlpha(attrs.format)
    736                     // Don't make surface with surfaceInsets opaque as they display a
    737                     // translucent shadow.
    738                     && attrs.surfaceInsets.left == 0
    739                     && attrs.surfaceInsets.top == 0
    740                     && attrs.surfaceInsets.right == 0
    741                     && attrs.surfaceInsets.bottom == 0
    742                     // Don't make surface opaque when resizing to reduce the amount of
    743                     // artifacts shown in areas the app isn't drawing content to.
    744                     && !w.isDragResizing()) {
    745                 flags |= SurfaceControl.OPAQUE;
    746             }
    747 
    748             mSurfaceController = new WindowSurfaceController(mSession.mSurfaceSession,
    749                     attrs.getTitle().toString(),
    750                     width, height, format, flags, this);
    751 
    752             w.setHasSurface(true);
    753 
    754             if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
    755                 Slog.i(TAG, "  CREATE SURFACE "
    756                         + mSurfaceController + " IN SESSION "
    757                         + mSession.mSurfaceSession
    758                         + ": pid=" + mSession.mPid + " format="
    759                         + attrs.format + " flags=0x"
    760                         + Integer.toHexString(flags)
    761                         + " / " + this);
    762             }
    763         } catch (OutOfResourcesException e) {
    764             Slog.w(TAG, "OutOfResourcesException creating surface");
    765             mService.reclaimSomeSurfaceMemoryLocked(this, "create", true);
    766             mDrawState = NO_SURFACE;
    767             return null;
    768         } catch (Exception e) {
    769             Slog.e(TAG, "Exception creating surface", e);
    770             mDrawState = NO_SURFACE;
    771             return null;
    772         }
    773 
    774         if (WindowManagerService.localLOGV) Slog.v(TAG, "Got surface: " + mSurfaceController
    775                 + ", set left=" + w.mFrame.left + " top=" + w.mFrame.top
    776                 + ", animLayer=" + mAnimLayer);
    777 
    778         if (SHOW_LIGHT_TRANSACTIONS) {
    779             Slog.i(TAG, ">>> OPEN TRANSACTION createSurfaceLocked");
    780             WindowManagerService.logSurface(w, "CREATE pos=("
    781                     + w.mFrame.left + "," + w.mFrame.top + ") ("
    782                     + width + "x" + height + "), layer=" + mAnimLayer + " HIDE", false);
    783         }
    784 
    785         // Start a new transaction and apply position & offset.
    786         final int layerStack = w.getDisplayContent().getDisplay().getLayerStack();
    787         mSurfaceController.setPositionAndLayer(mTmpSize.left, mTmpSize.top, layerStack, mAnimLayer);
    788         mLastHidden = true;
    789 
    790         if (WindowManagerService.localLOGV) Slog.v(TAG, "Created surface " + this);
    791         return mSurfaceController;
    792     }
    793 
    794     private void calculateSurfaceBounds(WindowState w, LayoutParams attrs) {
    795         if ((attrs.flags & FLAG_SCALED) != 0) {
    796             // For a scaled surface, we always want the requested size.
    797             mTmpSize.right = mTmpSize.left + w.mRequestedWidth;
    798             mTmpSize.bottom = mTmpSize.top + w.mRequestedHeight;
    799         } else {
    800             // When we're doing a drag-resizing, request a surface that's fullscreen size,
    801             // so that we don't need to reallocate during the process. This also prevents
    802             // buffer drops due to size mismatch.
    803             if (w.isDragResizing()) {
    804                 if (w.getResizeMode() == DRAG_RESIZE_MODE_FREEFORM) {
    805                     mTmpSize.left = 0;
    806                     mTmpSize.top = 0;
    807                 }
    808                 final DisplayInfo displayInfo = w.getDisplayInfo();
    809                 mTmpSize.right = mTmpSize.left + displayInfo.logicalWidth;
    810                 mTmpSize.bottom = mTmpSize.top + displayInfo.logicalHeight;
    811             } else {
    812                 mTmpSize.right = mTmpSize.left + w.mCompatFrame.width();
    813                 mTmpSize.bottom = mTmpSize.top + w.mCompatFrame.height();
    814             }
    815         }
    816 
    817         // Something is wrong and SurfaceFlinger will not like this, try to revert to sane values.
    818         // This doesn't necessarily mean that there is an error in the system. The sizes might be
    819         // incorrect, because it is before the first layout or draw.
    820         if (mTmpSize.width() < 1) {
    821             mTmpSize.right = mTmpSize.left + 1;
    822         }
    823         if (mTmpSize.height() < 1) {
    824             mTmpSize.bottom = mTmpSize.top + 1;
    825         }
    826 
    827         // Adjust for surface insets.
    828         mTmpSize.left -= attrs.surfaceInsets.left;
    829         mTmpSize.top -= attrs.surfaceInsets.top;
    830         mTmpSize.right += attrs.surfaceInsets.right;
    831         mTmpSize.bottom += attrs.surfaceInsets.bottom;
    832     }
    833 
    834     boolean hasSurface() {
    835         return !mWin.hasSavedSurface()
    836                 && mSurfaceController != null && mSurfaceController.hasSurface();
    837     }
    838 
    839     void destroySurfaceLocked() {
    840         final AppWindowToken wtoken = mWin.mAppToken;
    841         if (wtoken != null) {
    842             if (mWin == wtoken.startingWindow) {
    843                 wtoken.startingDisplayed = false;
    844             }
    845         }
    846 
    847         mWin.clearHasSavedSurface();
    848 
    849         if (mSurfaceController == null) {
    850             return;
    851         }
    852 
    853         int i = mWin.mChildWindows.size();
    854         // When destroying a surface we want to make sure child windows are hidden. If we are
    855         // preserving the surface until redraw though we intend to swap it out with another surface
    856         // for resizing. In this case the window always remains visible to the user and the child
    857         // windows should likewise remain visible.
    858         while (!mDestroyPreservedSurfaceUponRedraw && i > 0) {
    859             i--;
    860             WindowState c = mWin.mChildWindows.get(i);
    861             c.mAttachedHidden = true;
    862         }
    863 
    864         try {
    865             if (DEBUG_VISIBILITY) logWithStack(TAG, "Window " + this + " destroying surface "
    866                     + mSurfaceController + ", session " + mSession);
    867             if (mSurfaceDestroyDeferred) {
    868                 if (mSurfaceController != null && mPendingDestroySurface != mSurfaceController) {
    869                     if (mPendingDestroySurface != null) {
    870                         if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
    871                             WindowManagerService.logSurface(mWin, "DESTROY PENDING", true);
    872                         }
    873                         mPendingDestroySurface.destroyInTransaction();
    874                     }
    875                     mPendingDestroySurface = mSurfaceController;
    876                 }
    877             } else {
    878                 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
    879                     WindowManagerService.logSurface(mWin, "DESTROY", true);
    880                 }
    881                 destroySurface();
    882             }
    883             // Don't hide wallpaper if we're deferring the surface destroy
    884             // because of a surface change.
    885             if (!mDestroyPreservedSurfaceUponRedraw) {
    886                 mWallpaperControllerLocked.hideWallpapers(mWin);
    887             }
    888         } catch (RuntimeException e) {
    889             Slog.w(TAG, "Exception thrown when destroying Window " + this
    890                 + " surface " + mSurfaceController + " session " + mSession + ": " + e.toString());
    891         }
    892 
    893         // Whether the surface was preserved (and copied to mPendingDestroySurface) or not, it
    894         // needs to be cleared to match the WindowState.mHasSurface state. It is also necessary
    895         // so it can be recreated successfully in mPendingDestroySurface case.
    896         mWin.setHasSurface(false);
    897         if (mSurfaceController != null) {
    898             mSurfaceController.setShown(false);
    899         }
    900         mSurfaceController = null;
    901         mDrawState = NO_SURFACE;
    902     }
    903 
    904     void destroyDeferredSurfaceLocked() {
    905         try {
    906             if (mPendingDestroySurface != null) {
    907                 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
    908                     WindowManagerService.logSurface(mWin, "DESTROY PENDING", true);
    909                 }
    910                 mPendingDestroySurface.destroyInTransaction();
    911                 // Don't hide wallpaper if we're destroying a deferred surface
    912                 // after a surface mode change.
    913                 if (!mDestroyPreservedSurfaceUponRedraw) {
    914                     mWallpaperControllerLocked.hideWallpapers(mWin);
    915                 }
    916             }
    917         } catch (RuntimeException e) {
    918             Slog.w(TAG, "Exception thrown when destroying Window "
    919                     + this + " surface " + mPendingDestroySurface
    920                     + " session " + mSession + ": " + e.toString());
    921         }
    922         mSurfaceDestroyDeferred = false;
    923         mPendingDestroySurface = null;
    924     }
    925 
    926     void computeShownFrameLocked() {
    927         final boolean selfTransformation = mHasLocalTransformation;
    928         Transformation attachedTransformation =
    929                 (mAttachedWinAnimator != null && mAttachedWinAnimator.mHasLocalTransformation)
    930                 ? mAttachedWinAnimator.mTransformation : null;
    931         Transformation appTransformation = (mAppAnimator != null && mAppAnimator.hasTransformation)
    932                 ? mAppAnimator.transformation : null;
    933 
    934         // Wallpapers are animated based on the "real" window they
    935         // are currently targeting.
    936         final WindowState wallpaperTarget = mWallpaperControllerLocked.getWallpaperTarget();
    937         if (mIsWallpaper && wallpaperTarget != null && mService.mAnimateWallpaperWithTarget) {
    938             final WindowStateAnimator wallpaperAnimator = wallpaperTarget.mWinAnimator;
    939             if (wallpaperAnimator.mHasLocalTransformation &&
    940                     wallpaperAnimator.mAnimation != null &&
    941                     !wallpaperAnimator.mAnimation.getDetachWallpaper()) {
    942                 attachedTransformation = wallpaperAnimator.mTransformation;
    943                 if (DEBUG_WALLPAPER && attachedTransformation != null) {
    944                     Slog.v(TAG, "WP target attached xform: " + attachedTransformation);
    945                 }
    946             }
    947             final AppWindowAnimator wpAppAnimator = wallpaperTarget.mAppToken == null ?
    948                     null : wallpaperTarget.mAppToken.mAppAnimator;
    949                 if (wpAppAnimator != null && wpAppAnimator.hasTransformation
    950                     && wpAppAnimator.animation != null
    951                     && !wpAppAnimator.animation.getDetachWallpaper()) {
    952                 appTransformation = wpAppAnimator.transformation;
    953                 if (DEBUG_WALLPAPER && appTransformation != null) {
    954                     Slog.v(TAG, "WP target app xform: " + appTransformation);
    955                 }
    956             }
    957         }
    958 
    959         final int displayId = mWin.getDisplayId();
    960         final ScreenRotationAnimation screenRotationAnimation =
    961                 mAnimator.getScreenRotationAnimationLocked(displayId);
    962         final boolean screenAnimation =
    963                 screenRotationAnimation != null && screenRotationAnimation.isAnimating();
    964 
    965         mHasClipRect = false;
    966         if (selfTransformation || attachedTransformation != null
    967                 || appTransformation != null || screenAnimation) {
    968             // cache often used attributes locally
    969             final Rect frame = mWin.mFrame;
    970             final float tmpFloats[] = mService.mTmpFloats;
    971             final Matrix tmpMatrix = mWin.mTmpMatrix;
    972 
    973             // Compute the desired transformation.
    974             if (screenAnimation && screenRotationAnimation.isRotating()) {
    975                 // If we are doing a screen animation, the global rotation
    976                 // applied to windows can result in windows that are carefully
    977                 // aligned with each other to slightly separate, allowing you
    978                 // to see what is behind them.  An unsightly mess.  This...
    979                 // thing...  magically makes it call good: scale each window
    980                 // slightly (two pixels larger in each dimension, from the
    981                 // window's center).
    982                 final float w = frame.width();
    983                 final float h = frame.height();
    984                 if (w>=1 && h>=1) {
    985                     tmpMatrix.setScale(1 + 2/w, 1 + 2/h, w/2, h/2);
    986                 } else {
    987                     tmpMatrix.reset();
    988                 }
    989             } else {
    990                 tmpMatrix.reset();
    991             }
    992             tmpMatrix.postScale(mWin.mGlobalScale, mWin.mGlobalScale);
    993             if (selfTransformation) {
    994                 tmpMatrix.postConcat(mTransformation.getMatrix());
    995             }
    996             if (attachedTransformation != null) {
    997                 tmpMatrix.postConcat(attachedTransformation.getMatrix());
    998             }
    999             if (appTransformation != null) {
   1000                 tmpMatrix.postConcat(appTransformation.getMatrix());
   1001             }
   1002 
   1003             // The translation that applies the position of the window needs to be applied at the
   1004             // end in case that other translations include scaling. Otherwise the scaling will
   1005             // affect this translation. But it needs to be set before the screen rotation animation
   1006             // so the pivot point is at the center of the screen for all windows.
   1007             tmpMatrix.postTranslate(frame.left + mWin.mXOffset, frame.top + mWin.mYOffset);
   1008             if (screenAnimation) {
   1009                 tmpMatrix.postConcat(screenRotationAnimation.getEnterTransformation().getMatrix());
   1010             }
   1011 
   1012             //TODO (multidisplay): Magnification is supported only for the default display.
   1013             if (mService.mAccessibilityController != null && displayId == DEFAULT_DISPLAY) {
   1014                 MagnificationSpec spec = mService.mAccessibilityController
   1015                         .getMagnificationSpecForWindowLocked(mWin);
   1016                 if (spec != null && !spec.isNop()) {
   1017                     tmpMatrix.postScale(spec.scale, spec.scale);
   1018                     tmpMatrix.postTranslate(spec.offsetX, spec.offsetY);
   1019                 }
   1020             }
   1021 
   1022             // "convert" it into SurfaceFlinger's format
   1023             // (a 2x2 matrix + an offset)
   1024             // Here we must not transform the position of the surface
   1025             // since it is already included in the transformation.
   1026             //Slog.i(TAG_WM, "Transform: " + matrix);
   1027 
   1028             mHaveMatrix = true;
   1029             tmpMatrix.getValues(tmpFloats);
   1030             mDsDx = tmpFloats[Matrix.MSCALE_X];
   1031             mDtDx = tmpFloats[Matrix.MSKEW_Y];
   1032             mDsDy = tmpFloats[Matrix.MSKEW_X];
   1033             mDtDy = tmpFloats[Matrix.MSCALE_Y];
   1034             float x = tmpFloats[Matrix.MTRANS_X];
   1035             float y = tmpFloats[Matrix.MTRANS_Y];
   1036             mWin.mShownPosition.set((int) x, (int) y);
   1037 
   1038             // Now set the alpha...  but because our current hardware
   1039             // can't do alpha transformation on a non-opaque surface,
   1040             // turn it off if we are running an animation that is also
   1041             // transforming since it is more important to have that
   1042             // animation be smooth.
   1043             mShownAlpha = mAlpha;
   1044             if (!mService.mLimitedAlphaCompositing
   1045                     || (!PixelFormat.formatHasAlpha(mWin.mAttrs.format)
   1046                     || (mWin.isIdentityMatrix(mDsDx, mDtDx, mDsDy, mDtDy)
   1047                             && x == frame.left && y == frame.top))) {
   1048                 //Slog.i(TAG_WM, "Applying alpha transform");
   1049                 if (selfTransformation) {
   1050                     mShownAlpha *= mTransformation.getAlpha();
   1051                 }
   1052                 if (attachedTransformation != null) {
   1053                     mShownAlpha *= attachedTransformation.getAlpha();
   1054                 }
   1055                 if (appTransformation != null) {
   1056                     mShownAlpha *= appTransformation.getAlpha();
   1057                     if (appTransformation.hasClipRect()) {
   1058                         mClipRect.set(appTransformation.getClipRect());
   1059                         mHasClipRect = true;
   1060                         // The app transformation clip will be in the coordinate space of the main
   1061                         // activity window, which the animation correctly assumes will be placed at
   1062                         // (0,0)+(insets) relative to the containing frame. This isn't necessarily
   1063                         // true for child windows though which can have an arbitrary frame position
   1064                         // relative to their containing frame. We need to offset the difference
   1065                         // between the containing frame as used to calculate the crop and our
   1066                         // bounds to compensate for this.
   1067                         if (mWin.layoutInParentFrame()) {
   1068                             mClipRect.offset( (mWin.mContainingFrame.left - mWin.mFrame.left),
   1069                                     mWin.mContainingFrame.top - mWin.mFrame.top );
   1070                         }
   1071                     }
   1072                 }
   1073                 if (screenAnimation) {
   1074                     mShownAlpha *= screenRotationAnimation.getEnterTransformation().getAlpha();
   1075                 }
   1076             } else {
   1077                 //Slog.i(TAG_WM, "Not applying alpha transform");
   1078             }
   1079 
   1080             if ((DEBUG_SURFACE_TRACE || WindowManagerService.localLOGV)
   1081                     && (mShownAlpha == 1.0 || mShownAlpha == 0.0)) Slog.v(
   1082                     TAG, "computeShownFrameLocked: Animating " + this + " mAlpha=" + mAlpha
   1083                     + " self=" + (selfTransformation ? mTransformation.getAlpha() : "null")
   1084                     + " attached=" + (attachedTransformation == null ?
   1085                             "null" : attachedTransformation.getAlpha())
   1086                     + " app=" + (appTransformation == null ? "null" : appTransformation.getAlpha())
   1087                     + " screen=" + (screenAnimation ?
   1088                             screenRotationAnimation.getEnterTransformation().getAlpha() : "null"));
   1089             return;
   1090         } else if (mIsWallpaper && mService.mWindowPlacerLocked.mWallpaperActionPending) {
   1091             return;
   1092         } else if (mWin.isDragResizeChanged()) {
   1093             // This window is awaiting a relayout because user just started (or ended)
   1094             // drag-resizing. The shown frame (which affects surface size and pos)
   1095             // should not be updated until we get next finished draw with the new surface.
   1096             // Otherwise one or two frames rendered with old settings would be displayed
   1097             // with new geometry.
   1098             return;
   1099         }
   1100 
   1101         if (WindowManagerService.localLOGV) Slog.v(
   1102                 TAG, "computeShownFrameLocked: " + this +
   1103                 " not attached, mAlpha=" + mAlpha);
   1104 
   1105         MagnificationSpec spec = null;
   1106         //TODO (multidisplay): Magnification is supported only for the default display.
   1107         if (mService.mAccessibilityController != null && displayId == DEFAULT_DISPLAY) {
   1108             spec = mService.mAccessibilityController.getMagnificationSpecForWindowLocked(mWin);
   1109         }
   1110         if (spec != null) {
   1111             final Rect frame = mWin.mFrame;
   1112             final float tmpFloats[] = mService.mTmpFloats;
   1113             final Matrix tmpMatrix = mWin.mTmpMatrix;
   1114 
   1115             tmpMatrix.setScale(mWin.mGlobalScale, mWin.mGlobalScale);
   1116             tmpMatrix.postTranslate(frame.left + mWin.mXOffset, frame.top + mWin.mYOffset);
   1117 
   1118             if (spec != null && !spec.isNop()) {
   1119                 tmpMatrix.postScale(spec.scale, spec.scale);
   1120                 tmpMatrix.postTranslate(spec.offsetX, spec.offsetY);
   1121             }
   1122 
   1123             tmpMatrix.getValues(tmpFloats);
   1124 
   1125             mHaveMatrix = true;
   1126             mDsDx = tmpFloats[Matrix.MSCALE_X];
   1127             mDtDx = tmpFloats[Matrix.MSKEW_Y];
   1128             mDsDy = tmpFloats[Matrix.MSKEW_X];
   1129             mDtDy = tmpFloats[Matrix.MSCALE_Y];
   1130             float x = tmpFloats[Matrix.MTRANS_X];
   1131             float y = tmpFloats[Matrix.MTRANS_Y];
   1132             mWin.mShownPosition.set((int) x, (int) y);
   1133 
   1134             mShownAlpha = mAlpha;
   1135         } else {
   1136             mWin.mShownPosition.set(mWin.mFrame.left, mWin.mFrame.top);
   1137             if (mWin.mXOffset != 0 || mWin.mYOffset != 0) {
   1138                 mWin.mShownPosition.offset(mWin.mXOffset, mWin.mYOffset);
   1139             }
   1140             mShownAlpha = mAlpha;
   1141             mHaveMatrix = false;
   1142             mDsDx = mWin.mGlobalScale;
   1143             mDtDx = 0;
   1144             mDsDy = 0;
   1145             mDtDy = mWin.mGlobalScale;
   1146         }
   1147     }
   1148 
   1149     private void calculateSystemDecorRect() {
   1150         final WindowState w = mWin;
   1151         final Rect decorRect = w.mDecorFrame;
   1152         final int width = w.mFrame.width();
   1153         final int height = w.mFrame.height();
   1154 
   1155         // Compute the offset of the window in relation to the decor rect.
   1156         final int left = w.mXOffset + w.mFrame.left;
   1157         final int top = w.mYOffset + w.mFrame.top;
   1158 
   1159         // Initialize the decor rect to the entire frame.
   1160         if (w.isDockedResizing() ||
   1161                 (w.isChildWindow() && w.mAttachedWindow.isDockedResizing())) {
   1162 
   1163             // If we are resizing with the divider, the task bounds might be smaller than the
   1164             // stack bounds. The system decor is used to clip to the task bounds, which we don't
   1165             // want in this case in order to avoid holes.
   1166             //
   1167             // We take care to not shrink the width, for surfaces which are larger than
   1168             // the display region. Of course this area will not eventually be visible
   1169             // but if we truncate the width now, we will calculate incorrectly
   1170             // when adjusting to the stack bounds.
   1171             final DisplayInfo displayInfo = w.getDisplayContent().getDisplayInfo();
   1172             mSystemDecorRect.set(0, 0,
   1173                     Math.max(width, displayInfo.logicalWidth),
   1174                     Math.max(height, displayInfo.logicalHeight));
   1175         } else {
   1176             mSystemDecorRect.set(0, 0, width, height);
   1177         }
   1178 
   1179         // If a freeform window is animating from a position where it would be cutoff, it would be
   1180         // cutoff during the animation. We don't want that, so for the duration of the animation
   1181         // we ignore the decor cropping and depend on layering to position windows correctly.
   1182         final boolean cropToDecor = !(w.inFreeformWorkspace() && w.isAnimatingLw());
   1183         if (cropToDecor) {
   1184             // Intersect with the decor rect, offsetted by window position.
   1185             mSystemDecorRect.intersect(decorRect.left - left, decorRect.top - top,
   1186                     decorRect.right - left, decorRect.bottom - top);
   1187         }
   1188 
   1189         // If size compatibility is being applied to the window, the
   1190         // surface is scaled relative to the screen.  Also apply this
   1191         // scaling to the crop rect.  We aren't using the standard rect
   1192         // scale function because we want to round things to make the crop
   1193         // always round to a larger rect to ensure we don't crop too
   1194         // much and hide part of the window that should be seen.
   1195         if (w.mEnforceSizeCompat && w.mInvGlobalScale != 1.0f) {
   1196             final float scale = w.mInvGlobalScale;
   1197             mSystemDecorRect.left = (int) (mSystemDecorRect.left * scale - 0.5f);
   1198             mSystemDecorRect.top = (int) (mSystemDecorRect.top * scale - 0.5f);
   1199             mSystemDecorRect.right = (int) ((mSystemDecorRect.right + 1) * scale - 0.5f);
   1200             mSystemDecorRect.bottom = (int) ((mSystemDecorRect.bottom + 1) * scale - 0.5f);
   1201         }
   1202     }
   1203 
   1204     void calculateSurfaceWindowCrop(Rect clipRect, Rect finalClipRect) {
   1205         final WindowState w = mWin;
   1206         final DisplayContent displayContent = w.getDisplayContent();
   1207         if (displayContent == null) {
   1208             clipRect.setEmpty();
   1209             finalClipRect.setEmpty();
   1210             return;
   1211         }
   1212         final DisplayInfo displayInfo = displayContent.getDisplayInfo();
   1213         if (DEBUG_WINDOW_CROP) Slog.d(TAG,
   1214                 "Updating crop win=" + w + " mLastCrop=" + mLastClipRect);
   1215 
   1216         // Need to recompute a new system decor rect each time.
   1217         if (!w.isDefaultDisplay()) {
   1218             // On a different display there is no system decor.  Crop the window
   1219             // by the screen boundaries.
   1220             mSystemDecorRect.set(0, 0, w.mCompatFrame.width(), w.mCompatFrame.height());
   1221             mSystemDecorRect.intersect(-w.mCompatFrame.left, -w.mCompatFrame.top,
   1222                     displayInfo.logicalWidth - w.mCompatFrame.left,
   1223                     displayInfo.logicalHeight - w.mCompatFrame.top);
   1224         } else if (w.mLayer >= mService.mSystemDecorLayer) {
   1225             // Above the decor layer is easy, just use the entire window.
   1226             mSystemDecorRect.set(0, 0, w.mCompatFrame.width(), w.mCompatFrame.height());
   1227         } else if (w.mDecorFrame.isEmpty()) {
   1228             // Windows without policy decor aren't cropped.
   1229             mSystemDecorRect.set(0, 0, w.mCompatFrame.width(), w.mCompatFrame.height());
   1230         } else if (w.mAttrs.type == LayoutParams.TYPE_WALLPAPER && mAnimator.isAnimating()) {
   1231             // If we're animating, the wallpaper crop should only be updated at the end of the
   1232             // animation.
   1233             mTmpClipRect.set(mSystemDecorRect);
   1234             calculateSystemDecorRect();
   1235             mSystemDecorRect.union(mTmpClipRect);
   1236         } else {
   1237             // Crop to the system decor specified by policy.
   1238             calculateSystemDecorRect();
   1239             if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Applying decor to crop win=" + w + " mDecorFrame="
   1240                     + w.mDecorFrame + " mSystemDecorRect=" + mSystemDecorRect);
   1241         }
   1242 
   1243         final boolean fullscreen = w.isFrameFullscreen(displayInfo);
   1244         final boolean isFreeformResizing =
   1245                 w.isDragResizing() && w.getResizeMode() == DRAG_RESIZE_MODE_FREEFORM;
   1246 
   1247         // We use the clip rect as provided by the tranformation for non-fullscreen windows to
   1248         // avoid premature clipping with the system decor rect.
   1249         clipRect.set((mHasClipRect && !fullscreen) ? mClipRect : mSystemDecorRect);
   1250         if (DEBUG_WINDOW_CROP) Slog.d(TAG, "win=" + w + " Initial clip rect: " + clipRect
   1251                 + " mHasClipRect=" + mHasClipRect + " fullscreen=" + fullscreen);
   1252 
   1253         if (isFreeformResizing && !w.isChildWindow()) {
   1254             // For freeform resizing non child windows, we are using the big surface positioned
   1255             // at 0,0. Thus we must express the crop in that coordinate space.
   1256             clipRect.offset(w.mShownPosition.x, w.mShownPosition.y);
   1257         }
   1258 
   1259         // Expand the clip rect for surface insets.
   1260         final WindowManager.LayoutParams attrs = w.mAttrs;
   1261         clipRect.left -= attrs.surfaceInsets.left;
   1262         clipRect.top -= attrs.surfaceInsets.top;
   1263         clipRect.right += attrs.surfaceInsets.right;
   1264         clipRect.bottom += attrs.surfaceInsets.bottom;
   1265 
   1266         if (mHasClipRect && fullscreen) {
   1267             // We intersect the clip rect specified by the transformation with the expanded system
   1268             // decor rect to prevent artifacts from drawing during animation if the transformation
   1269             // clip rect extends outside the system decor rect.
   1270             clipRect.intersect(mClipRect);
   1271         }
   1272         // The clip rect was generated assuming (0,0) as the window origin,
   1273         // so we need to translate to match the actual surface coordinates.
   1274         clipRect.offset(attrs.surfaceInsets.left, attrs.surfaceInsets.top);
   1275 
   1276         finalClipRect.setEmpty();
   1277         adjustCropToStackBounds(w, clipRect, finalClipRect, isFreeformResizing);
   1278         if (DEBUG_WINDOW_CROP) Slog.d(TAG,
   1279                 "win=" + w + " Clip rect after stack adjustment=" + clipRect);
   1280 
   1281         w.transformClipRectFromScreenToSurfaceSpace(clipRect);
   1282 
   1283         // See {@link WindowState#notifyMovedInStack} for why this is necessary.
   1284         if (w.hasJustMovedInStack() && mLastClipRect.isEmpty() && !clipRect.isEmpty()) {
   1285             clipRect.setEmpty();
   1286         }
   1287     }
   1288 
   1289     void updateSurfaceWindowCrop(Rect clipRect, Rect finalClipRect, boolean recoveringMemory) {
   1290         if (DEBUG_WINDOW_CROP) Slog.d(TAG, "updateSurfaceWindowCrop: win=" + mWin
   1291                 + " clipRect=" + clipRect + " finalClipRect=" + finalClipRect);
   1292         if (clipRect != null) {
   1293             if (!clipRect.equals(mLastClipRect)) {
   1294                 mLastClipRect.set(clipRect);
   1295                 mSurfaceController.setCropInTransaction(clipRect, recoveringMemory);
   1296             }
   1297         } else {
   1298             mSurfaceController.clearCropInTransaction(recoveringMemory);
   1299         }
   1300         if (!finalClipRect.equals(mLastFinalClipRect)) {
   1301             mLastFinalClipRect.set(finalClipRect);
   1302             mSurfaceController.setFinalCropInTransaction(finalClipRect);
   1303             if (mDestroyPreservedSurfaceUponRedraw && mPendingDestroySurface != null) {
   1304                 mPendingDestroySurface.setFinalCropInTransaction(finalClipRect);
   1305             }
   1306         }
   1307     }
   1308 
   1309     private int resolveStackClip() {
   1310         // App animation overrides window animation stack clip mode.
   1311         if (mAppAnimator != null && mAppAnimator.animation != null) {
   1312             return mAppAnimator.getStackClip();
   1313         } else {
   1314             return mStackClip;
   1315         }
   1316     }
   1317     private void adjustCropToStackBounds(WindowState w, Rect clipRect, Rect finalClipRect,
   1318             boolean isFreeformResizing) {
   1319 
   1320         final DisplayContent displayContent = w.getDisplayContent();
   1321         if (displayContent != null && !displayContent.isDefaultDisplay) {
   1322             // There are some windows that live on other displays while their app and main window
   1323             // live on the default display (e.g. casting...). We don't want to crop this windows
   1324             // to the stack bounds which is only currently supported on the default display.
   1325             // TODO(multi-display): Need to support cropping to stack bounds on other displays
   1326             // when we have stacks on other displays.
   1327             return;
   1328         }
   1329 
   1330         final Task task = w.getTask();
   1331         if (task == null || !task.cropWindowsToStackBounds()) {
   1332             return;
   1333         }
   1334 
   1335         final int stackClip = resolveStackClip();
   1336 
   1337         // It's animating and we don't want to clip it to stack bounds during animation - abort.
   1338         if (isAnimationSet() && stackClip == STACK_CLIP_NONE) {
   1339             return;
   1340         }
   1341 
   1342         final WindowState winShowWhenLocked = (WindowState) mPolicy.getWinShowWhenLockedLw();
   1343         if (w == winShowWhenLocked && mPolicy.isKeyguardShowingOrOccluded()) {
   1344             return;
   1345         }
   1346 
   1347         final TaskStack stack = task.mStack;
   1348         stack.getDimBounds(mTmpStackBounds);
   1349         final Rect surfaceInsets = w.getAttrs().surfaceInsets;
   1350         // When we resize we use the big surface approach, which means we can't trust the
   1351         // window frame bounds anymore. Instead, the window will be placed at 0, 0, but to avoid
   1352         // hardcoding it, we use surface coordinates.
   1353         final int frameX = isFreeformResizing ? (int) mSurfaceController.getX() :
   1354                 w.mFrame.left + mWin.mXOffset - surfaceInsets.left;
   1355         final int frameY = isFreeformResizing ? (int) mSurfaceController.getY() :
   1356                 w.mFrame.top + mWin.mYOffset - surfaceInsets.top;
   1357 
   1358         // If we are animating, we either apply the clip before applying all the animation
   1359         // transformation or after all the transformation.
   1360         final boolean useFinalClipRect = isAnimationSet() && stackClip == STACK_CLIP_AFTER_ANIM
   1361                 || mDestroyPreservedSurfaceUponRedraw;
   1362 
   1363         // We need to do some acrobatics with surface position, because their clip region is
   1364         // relative to the inside of the surface, but the stack bounds aren't.
   1365         if (useFinalClipRect) {
   1366             finalClipRect.set(mTmpStackBounds);
   1367         } else {
   1368             if (StackId.hasWindowShadow(stack.mStackId)
   1369                     && !StackId.isTaskResizeAllowed(stack.mStackId)) {
   1370                 // The windows in this stack display drop shadows and the fill the entire stack
   1371                 // area. Adjust the stack bounds we will use to cropping take into account the
   1372                 // offsets we use to display the drop shadow so it doesn't get cropped.
   1373                 mTmpStackBounds.inset(-surfaceInsets.left, -surfaceInsets.top,
   1374                         -surfaceInsets.right, -surfaceInsets.bottom);
   1375             }
   1376 
   1377             clipRect.left = Math.max(0,
   1378                     Math.max(mTmpStackBounds.left, frameX + clipRect.left) - frameX);
   1379             clipRect.top = Math.max(0,
   1380                     Math.max(mTmpStackBounds.top, frameY + clipRect.top) - frameY);
   1381             clipRect.right = Math.max(0,
   1382                     Math.min(mTmpStackBounds.right, frameX + clipRect.right) - frameX);
   1383             clipRect.bottom = Math.max(0,
   1384                     Math.min(mTmpStackBounds.bottom, frameY + clipRect.bottom) - frameY);
   1385         }
   1386     }
   1387 
   1388     void setSurfaceBoundariesLocked(final boolean recoveringMemory) {
   1389         final WindowState w = mWin;
   1390         final Task task = w.getTask();
   1391 
   1392         // We got resized, so block all updates until we got the new surface.
   1393         if (w.isResizedWhileNotDragResizing() && !w.isGoneForLayoutLw()) {
   1394             return;
   1395         }
   1396 
   1397         mTmpSize.set(w.mShownPosition.x, w.mShownPosition.y, 0, 0);
   1398         calculateSurfaceBounds(w, w.getAttrs());
   1399 
   1400         mExtraHScale = (float) 1.0;
   1401         mExtraVScale = (float) 1.0;
   1402 
   1403         // Once relayout has been called at least once, we need to make sure
   1404         // we only resize the client surface during calls to relayout. For
   1405         // clients which use indeterminate measure specs (MATCH_PARENT),
   1406         // we may try and change their window size without a call to relayout.
   1407         // However, this would be unsafe, as the client may be in the middle
   1408         // of producing a frame at the old size, having just completed layout
   1409         // to find the surface size changed underneath it.
   1410         //
   1411         // TODO: For N we only apply this fix to the pinned workspace. As we
   1412         // aren't observing known issues here outside of PiP resizing. (Typically
   1413         // the other windows that use -1 are PopupWindows which aren't likely
   1414         // to be rendering while we resize).
   1415 
   1416         boolean wasForceScaled = mForceScaleUntilResize;
   1417 
   1418         if (!w.inPinnedWorkspace() || (!w.mRelayoutCalled || w.mInRelayout)) {
   1419             mSurfaceResized = mSurfaceController.setSizeInTransaction(
   1420                     mTmpSize.width(), mTmpSize.height(), recoveringMemory);
   1421         } else {
   1422             mSurfaceResized = false;
   1423         }
   1424         mForceScaleUntilResize = mForceScaleUntilResize && !mSurfaceResized;
   1425 
   1426         calculateSurfaceWindowCrop(mTmpClipRect, mTmpFinalClipRect);
   1427 
   1428         float surfaceWidth = mSurfaceController.getWidth();
   1429         float surfaceHeight = mSurfaceController.getHeight();
   1430 
   1431         if ((task != null && task.mStack.getForceScaleToCrop()) || mForceScaleUntilResize) {
   1432             int hInsets = w.getAttrs().surfaceInsets.left + w.getAttrs().surfaceInsets.right;
   1433             int vInsets = w.getAttrs().surfaceInsets.top + w.getAttrs().surfaceInsets.bottom;
   1434             if (!mForceScaleUntilResize) {
   1435                 mSurfaceController.forceScaleableInTransaction(true);
   1436             }
   1437             // We want to calculate the scaling based on the content area, not based on
   1438             // the entire surface, so that we scale in sync with windows that don't have insets.
   1439             mExtraHScale = (mTmpClipRect.width() - hInsets) / (float)(surfaceWidth - hInsets);
   1440             mExtraVScale = (mTmpClipRect.height() - vInsets) / (float)(surfaceHeight - vInsets);
   1441 
   1442             // In the case of ForceScaleToCrop we scale entire tasks together,
   1443             // and so we need to scale our offsets relative to the task bounds
   1444             // or parent and child windows would fall out of alignment.
   1445             int posX = (int) (mTmpSize.left - w.mAttrs.x * (1 - mExtraHScale));
   1446             int posY = (int) (mTmpSize.top - w.mAttrs.y * (1 - mExtraVScale));
   1447             // Imagine we are scaling down. As we scale the buffer down, we decrease the
   1448             // distance between the surface top left, and the start of the surface contents
   1449             // (previously it was surfaceInsets.left pixels in screen space but now it
   1450             // will be surfaceInsets.left*mExtraHScale). This means in order to keep the
   1451             // non inset content at the same position, we have to shift the whole window
   1452             // forward. Likewise for scaling up, we've increased this distance, and we need
   1453             // to shift by a negative number to compensate.
   1454             posX += w.getAttrs().surfaceInsets.left * (1 - mExtraHScale);
   1455             posY += w.getAttrs().surfaceInsets.top * (1 - mExtraVScale);
   1456 
   1457             mSurfaceController.setPositionInTransaction((float)Math.floor(posX),
   1458                     (float)Math.floor(posY), recoveringMemory);
   1459 
   1460             // Since we are scaled to fit in our previously desired crop, we can now
   1461             // expose the whole window in buffer space, and not risk extending
   1462             // past where the system would have cropped us
   1463             mTmpClipRect.set(0, 0, (int)surfaceWidth, (int)surfaceHeight);
   1464             mTmpFinalClipRect.setEmpty();
   1465 
   1466             // Various surfaces in the scaled stack may resize at different times.
   1467             // We need to ensure for each surface, that we disable transformation matrix
   1468             // scaling in the same transaction which we resize the surface in.
   1469             // As we are in SCALING_MODE_SCALE_TO_WINDOW, SurfaceFlinger will
   1470             // then take over the scaling until the new buffer arrives, and things
   1471             // will be seamless.
   1472             mForceScaleUntilResize = true;
   1473         } else {
   1474             mSurfaceController.setPositionInTransaction(mTmpSize.left, mTmpSize.top,
   1475                     recoveringMemory);
   1476         }
   1477 
   1478         // If we are ending the scaling mode. We switch to SCALING_MODE_FREEZE
   1479         // to prevent further updates until buffer latch. Normally position
   1480         // would continue to apply immediately. But we need a different position
   1481         // before and after resize (since we have scaled the shadows, as discussed
   1482         // above).
   1483         if (wasForceScaled && !mForceScaleUntilResize) {
   1484             mSurfaceController.setPositionAppliesWithResizeInTransaction(true);
   1485             mSurfaceController.forceScaleableInTransaction(false);
   1486         }
   1487 
   1488         Rect clipRect = mTmpClipRect;
   1489         if (w.inPinnedWorkspace()) {
   1490             clipRect = null;
   1491             task.mStack.getDimBounds(mTmpFinalClipRect);
   1492             mTmpFinalClipRect.inset(-w.mAttrs.surfaceInsets.left, -w.mAttrs.surfaceInsets.top,
   1493                     -w.mAttrs.surfaceInsets.right, -w.mAttrs.surfaceInsets.bottom);
   1494         }
   1495 
   1496         updateSurfaceWindowCrop(clipRect, mTmpFinalClipRect, recoveringMemory);
   1497 
   1498         mSurfaceController.setMatrixInTransaction(mDsDx * w.mHScale * mExtraHScale,
   1499                 mDtDx * w.mVScale * mExtraVScale,
   1500                 mDsDy * w.mHScale * mExtraHScale,
   1501                 mDtDy * w.mVScale * mExtraVScale, recoveringMemory);
   1502 
   1503         if (mSurfaceResized) {
   1504             mReportSurfaceResized = true;
   1505             mAnimator.setPendingLayoutChanges(w.getDisplayId(),
   1506                     WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
   1507             w.applyDimLayerIfNeeded();
   1508         }
   1509 
   1510     }
   1511 
   1512     void prepareSurfaceLocked(final boolean recoveringMemory) {
   1513         final WindowState w = mWin;
   1514         if (!hasSurface()) {
   1515             if (w.mOrientationChanging) {
   1516                 if (DEBUG_ORIENTATION) {
   1517                     Slog.v(TAG, "Orientation change skips hidden " + w);
   1518                 }
   1519                 w.mOrientationChanging = false;
   1520             }
   1521             return;
   1522         }
   1523 
   1524         // Do not change surface properties of opening apps if we are waiting for the
   1525         // transition to be ready. transitionGoodToGo could be not ready even after all
   1526         // opening apps are drawn. It's only waiting on isFetchingAppTransitionsSpecs()
   1527         // to get the animation spec. (For example, go into Recents and immediately open
   1528         // the same app again before the app's surface is destroyed or saved, the surface
   1529         // is always ready in the whole process.) If we go ahead here, the opening app
   1530         // will be shown with the full size before the correct animation spec arrives.
   1531         if (isWaitingForOpening()) {
   1532             return;
   1533         }
   1534 
   1535         boolean displayed = false;
   1536 
   1537         computeShownFrameLocked();
   1538 
   1539         setSurfaceBoundariesLocked(recoveringMemory);
   1540 
   1541         if (mIsWallpaper && !mWin.mWallpaperVisible) {
   1542             // Wallpaper is no longer visible and there is no wp target => hide it.
   1543             hide("prepareSurfaceLocked");
   1544         } else if (w.mAttachedHidden || !w.isOnScreen()) {
   1545             hide("prepareSurfaceLocked");
   1546             mWallpaperControllerLocked.hideWallpapers(w);
   1547 
   1548             // If we are waiting for this window to handle an
   1549             // orientation change, well, it is hidden, so
   1550             // doesn't really matter.  Note that this does
   1551             // introduce a potential glitch if the window
   1552             // becomes unhidden before it has drawn for the
   1553             // new orientation.
   1554             if (w.mOrientationChanging) {
   1555                 w.mOrientationChanging = false;
   1556                 if (DEBUG_ORIENTATION) Slog.v(TAG,
   1557                         "Orientation change skips hidden " + w);
   1558             }
   1559         } else if (mLastLayer != mAnimLayer
   1560                 || mLastAlpha != mShownAlpha
   1561                 || mLastDsDx != mDsDx
   1562                 || mLastDtDx != mDtDx
   1563                 || mLastDsDy != mDsDy
   1564                 || mLastDtDy != mDtDy
   1565                 || w.mLastHScale != w.mHScale
   1566                 || w.mLastVScale != w.mVScale
   1567                 || mLastHidden) {
   1568             displayed = true;
   1569             mLastAlpha = mShownAlpha;
   1570             mLastLayer = mAnimLayer;
   1571             mLastDsDx = mDsDx;
   1572             mLastDtDx = mDtDx;
   1573             mLastDsDy = mDsDy;
   1574             mLastDtDy = mDtDy;
   1575             w.mLastHScale = w.mHScale;
   1576             w.mLastVScale = w.mVScale;
   1577             if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
   1578                     "controller=" + mSurfaceController +
   1579                     "alpha=" + mShownAlpha + " layer=" + mAnimLayer
   1580                     + " matrix=[" + mDsDx + "*" + w.mHScale
   1581                     + "," + mDtDx + "*" + w.mVScale
   1582                     + "][" + mDsDy + "*" + w.mHScale
   1583                     + "," + mDtDy + "*" + w.mVScale + "]", false);
   1584 
   1585             boolean prepared =
   1586                 mSurfaceController.prepareToShowInTransaction(mShownAlpha, mAnimLayer,
   1587                         mDsDx * w.mHScale * mExtraHScale,
   1588                         mDtDx * w.mVScale * mExtraVScale,
   1589                         mDsDy * w.mHScale * mExtraHScale,
   1590                         mDtDy * w.mVScale * mExtraVScale,
   1591                         recoveringMemory);
   1592 
   1593             if (prepared && mLastHidden && mDrawState == HAS_DRAWN) {
   1594                 if (showSurfaceRobustlyLocked()) {
   1595                     markPreservedSurfaceForDestroy();
   1596                     mAnimator.requestRemovalOfReplacedWindows(w);
   1597                     mLastHidden = false;
   1598                     if (mIsWallpaper) {
   1599                         mWallpaperControllerLocked.dispatchWallpaperVisibility(w, true);
   1600                     }
   1601                     // This draw means the difference between unique content and mirroring.
   1602                     // Run another pass through performLayout to set mHasContent in the
   1603                     // LogicalDisplay.
   1604                     mAnimator.setPendingLayoutChanges(w.getDisplayId(),
   1605                             WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM);
   1606                 } else {
   1607                     w.mOrientationChanging = false;
   1608                 }
   1609             }
   1610             if (hasSurface()) {
   1611                 w.mToken.hasVisible = true;
   1612             }
   1613         } else {
   1614             if (DEBUG_ANIM && isAnimationSet()) {
   1615                 Slog.v(TAG, "prepareSurface: No changes in animation for " + this);
   1616             }
   1617             displayed = true;
   1618         }
   1619 
   1620         if (displayed) {
   1621             if (w.mOrientationChanging) {
   1622                 if (!w.isDrawnLw()) {
   1623                     mAnimator.mBulkUpdateParams &= ~SET_ORIENTATION_CHANGE_COMPLETE;
   1624                     mAnimator.mLastWindowFreezeSource = w;
   1625                     if (DEBUG_ORIENTATION) Slog.v(TAG,
   1626                             "Orientation continue waiting for draw in " + w);
   1627                 } else {
   1628                     w.mOrientationChanging = false;
   1629                     if (DEBUG_ORIENTATION) Slog.v(TAG, "Orientation change complete in " + w);
   1630                 }
   1631             }
   1632             w.mToken.hasVisible = true;
   1633         }
   1634     }
   1635 
   1636     void setTransparentRegionHintLocked(final Region region) {
   1637         if (mSurfaceController == null) {
   1638             Slog.w(TAG, "setTransparentRegionHint: null mSurface after mHasSurface true");
   1639             return;
   1640         }
   1641         mSurfaceController.setTransparentRegionHint(region);
   1642     }
   1643 
   1644     void setWallpaperOffset(Point shownPosition) {
   1645         final LayoutParams attrs = mWin.getAttrs();
   1646         final int left = shownPosition.x - attrs.surfaceInsets.left;
   1647         final int top = shownPosition.y - attrs.surfaceInsets.top;
   1648 
   1649         try {
   1650             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setWallpaperOffset");
   1651             SurfaceControl.openTransaction();
   1652             mSurfaceController.setPositionInTransaction(mWin.mFrame.left + left,
   1653                     mWin.mFrame.top + top, false);
   1654             calculateSurfaceWindowCrop(mTmpClipRect, mTmpFinalClipRect);
   1655             updateSurfaceWindowCrop(mTmpClipRect, mTmpFinalClipRect, false);
   1656         } catch (RuntimeException e) {
   1657             Slog.w(TAG, "Error positioning surface of " + mWin
   1658                     + " pos=(" + left + "," + top + ")", e);
   1659         } finally {
   1660             SurfaceControl.closeTransaction();
   1661             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
   1662                     "<<< CLOSE TRANSACTION setWallpaperOffset");
   1663         }
   1664     }
   1665 
   1666     /**
   1667      * Try to change the pixel format without recreating the surface. This
   1668      * will be common in the case of changing from PixelFormat.OPAQUE to
   1669      * PixelFormat.TRANSLUCENT in the hardware-accelerated case as both
   1670      * requested formats resolve to the same underlying SurfaceControl format
   1671      * @return True if format was succesfully changed, false otherwise
   1672      */
   1673     boolean tryChangeFormatInPlaceLocked() {
   1674         if (mSurfaceController == null) {
   1675             return false;
   1676         }
   1677         final LayoutParams attrs = mWin.getAttrs();
   1678         final boolean isHwAccelerated = (attrs.flags & FLAG_HARDWARE_ACCELERATED) != 0;
   1679         final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format;
   1680         if (format == mSurfaceFormat) {
   1681             setOpaqueLocked(!PixelFormat.formatHasAlpha(attrs.format));
   1682             return true;
   1683         }
   1684         return false;
   1685     }
   1686 
   1687     void setOpaqueLocked(boolean isOpaque) {
   1688         if (mSurfaceController == null) {
   1689             return;
   1690         }
   1691         mSurfaceController.setOpaque(isOpaque);
   1692     }
   1693 
   1694     void setSecureLocked(boolean isSecure) {
   1695         if (mSurfaceController == null) {
   1696             return;
   1697         }
   1698         mSurfaceController.setSecure(isSecure);
   1699     }
   1700 
   1701     // This must be called while inside a transaction.
   1702     boolean performShowLocked() {
   1703         if (mWin.isHiddenFromUserLocked()) {
   1704             if (DEBUG_VISIBILITY) Slog.w(TAG, "hiding " + mWin + ", belonging to " + mWin.mOwnerUid);
   1705             mWin.hideLw(false);
   1706             return false;
   1707         }
   1708         if (DEBUG_VISIBILITY || (DEBUG_STARTING_WINDOW &&
   1709                 mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING)) {
   1710             Slog.v(TAG, "performShow on " + this
   1711                     + ": mDrawState=" + drawStateToString() + " readyForDisplay="
   1712                     + mWin.isReadyForDisplayIgnoringKeyguard()
   1713                     + " starting=" + (mWin.mAttrs.type == TYPE_APPLICATION_STARTING)
   1714                     + " during animation: policyVis=" + mWin.mPolicyVisibility
   1715                     + " attHidden=" + mWin.mAttachedHidden
   1716                     + " tok.hiddenRequested="
   1717                     + (mWin.mAppToken != null ? mWin.mAppToken.hiddenRequested : false)
   1718                     + " tok.hidden="
   1719                     + (mWin.mAppToken != null ? mWin.mAppToken.hidden : false)
   1720                     + " animating=" + mAnimating
   1721                     + " tok animating="
   1722                     + (mAppAnimator != null ? mAppAnimator.animating : false) + " Callers="
   1723                     + Debug.getCallers(3));
   1724         }
   1725         if (mDrawState == READY_TO_SHOW && mWin.isReadyForDisplayIgnoringKeyguard()) {
   1726             if (DEBUG_VISIBILITY || (DEBUG_STARTING_WINDOW &&
   1727                     mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING)) {
   1728                 Slog.v(TAG, "Showing " + this
   1729                         + " during animation: policyVis=" + mWin.mPolicyVisibility
   1730                         + " attHidden=" + mWin.mAttachedHidden
   1731                         + " tok.hiddenRequested="
   1732                         + (mWin.mAppToken != null ? mWin.mAppToken.hiddenRequested : false)
   1733                         + " tok.hidden="
   1734                         + (mWin.mAppToken != null ? mWin.mAppToken.hidden : false)
   1735                         + " animating=" + mAnimating
   1736                         + " tok animating="
   1737                         + (mAppAnimator != null ? mAppAnimator.animating : false));
   1738             }
   1739 
   1740             mService.enableScreenIfNeededLocked();
   1741 
   1742             applyEnterAnimationLocked();
   1743 
   1744             // Force the show in the next prepareSurfaceLocked() call.
   1745             mLastAlpha = -1;
   1746             if (DEBUG_SURFACE_TRACE || DEBUG_ANIM)
   1747                 Slog.v(TAG, "performShowLocked: mDrawState=HAS_DRAWN in " + mWin);
   1748             mDrawState = HAS_DRAWN;
   1749             mService.scheduleAnimationLocked();
   1750 
   1751             int i = mWin.mChildWindows.size();
   1752             while (i > 0) {
   1753                 i--;
   1754                 WindowState c = mWin.mChildWindows.get(i);
   1755                 if (c.mAttachedHidden) {
   1756                     c.mAttachedHidden = false;
   1757                     if (c.mWinAnimator.mSurfaceController != null) {
   1758                         c.mWinAnimator.performShowLocked();
   1759                         // It hadn't been shown, which means layout not
   1760                         // performed on it, so now we want to make sure to
   1761                         // do a layout.  If called from within the transaction
   1762                         // loop, this will cause it to restart with a new
   1763                         // layout.
   1764                         final DisplayContent displayContent = c.getDisplayContent();
   1765                         if (displayContent != null) {
   1766                             displayContent.layoutNeeded = true;
   1767                         }
   1768                     }
   1769                 }
   1770             }
   1771 
   1772             if (mWin.mAttrs.type != TYPE_APPLICATION_STARTING && mWin.mAppToken != null) {
   1773                 mWin.mAppToken.onFirstWindowDrawn(mWin, this);
   1774             }
   1775 
   1776             if (mWin.mAttrs.type == TYPE_INPUT_METHOD) {
   1777                 mWin.mDisplayContent.mDividerControllerLocked.resetImeHideRequested();
   1778             }
   1779 
   1780             return true;
   1781         }
   1782         return false;
   1783     }
   1784 
   1785     /**
   1786      * Have the surface flinger show a surface, robustly dealing with
   1787      * error conditions.  In particular, if there is not enough memory
   1788      * to show the surface, then we will try to get rid of other surfaces
   1789      * in order to succeed.
   1790      *
   1791      * @return Returns true if the surface was successfully shown.
   1792      */
   1793     private boolean showSurfaceRobustlyLocked() {
   1794         final Task task = mWin.getTask();
   1795         if (task != null && StackId.windowsAreScaleable(task.mStack.mStackId)) {
   1796             mSurfaceController.forceScaleableInTransaction(true);
   1797         }
   1798 
   1799         boolean shown = mSurfaceController.showRobustlyInTransaction();
   1800         if (!shown)
   1801             return false;
   1802 
   1803         if (mWin.mTurnOnScreen) {
   1804             if (DEBUG_VISIBILITY) Slog.v(TAG, "Show surface turning screen on: " + mWin);
   1805             mWin.mTurnOnScreen = false;
   1806             mAnimator.mBulkUpdateParams |= SET_TURN_ON_SCREEN;
   1807         }
   1808         return true;
   1809     }
   1810 
   1811     void applyEnterAnimationLocked() {
   1812         // If we are the new part of a window replacement transition and we have requested
   1813         // not to animate, we instead want to make it seamless, so we don't want to apply
   1814         // an enter transition.
   1815         if (mWin.mSkipEnterAnimationForSeamlessReplacement) {
   1816             return;
   1817         }
   1818         final int transit;
   1819         if (mEnterAnimationPending) {
   1820             mEnterAnimationPending = false;
   1821             transit = WindowManagerPolicy.TRANSIT_ENTER;
   1822         } else {
   1823             transit = WindowManagerPolicy.TRANSIT_SHOW;
   1824         }
   1825         applyAnimationLocked(transit, true);
   1826         //TODO (multidisplay): Magnification is supported only for the default display.
   1827         if (mService.mAccessibilityController != null
   1828                 && mWin.getDisplayId() == DEFAULT_DISPLAY) {
   1829             mService.mAccessibilityController.onWindowTransitionLocked(mWin, transit);
   1830         }
   1831     }
   1832 
   1833     /**
   1834      * Choose the correct animation and set it to the passed WindowState.
   1835      * @param transit If AppTransition.TRANSIT_PREVIEW_DONE and the app window has been drawn
   1836      *      then the animation will be app_starting_exit. Any other value loads the animation from
   1837      *      the switch statement below.
   1838      * @param isEntrance The animation type the last time this was called. Used to keep from
   1839      *      loading the same animation twice.
   1840      * @return true if an animation has been loaded.
   1841      */
   1842     boolean applyAnimationLocked(int transit, boolean isEntrance) {
   1843         if ((mLocalAnimating && mAnimationIsEntrance == isEntrance)
   1844                 || mKeyguardGoingAwayAnimation) {
   1845             // If we are trying to apply an animation, but already running
   1846             // an animation of the same type, then just leave that one alone.
   1847 
   1848             // If we are in a keyguard exit animation, and the window should animate away, modify
   1849             // keyguard exit animation such that it also fades out.
   1850             if (mAnimation != null && mKeyguardGoingAwayAnimation
   1851                     && transit == WindowManagerPolicy.TRANSIT_PREVIEW_DONE) {
   1852                 applyFadeoutDuringKeyguardExitAnimation();
   1853             }
   1854             return true;
   1855         }
   1856 
   1857         // Only apply an animation if the display isn't frozen.  If it is
   1858         // frozen, there is no reason to animate and it can cause strange
   1859         // artifacts when we unfreeze the display if some different animation
   1860         // is running.
   1861         if (mService.okToDisplay()) {
   1862             int anim = mPolicy.selectAnimationLw(mWin, transit);
   1863             int attr = -1;
   1864             Animation a = null;
   1865             if (anim != 0) {
   1866                 a = anim != -1 ? AnimationUtils.loadAnimation(mContext, anim) : null;
   1867             } else {
   1868                 switch (transit) {
   1869                     case WindowManagerPolicy.TRANSIT_ENTER:
   1870                         attr = com.android.internal.R.styleable.WindowAnimation_windowEnterAnimation;
   1871                         break;
   1872                     case WindowManagerPolicy.TRANSIT_EXIT:
   1873                         attr = com.android.internal.R.styleable.WindowAnimation_windowExitAnimation;
   1874                         break;
   1875                     case WindowManagerPolicy.TRANSIT_SHOW:
   1876                         attr = com.android.internal.R.styleable.WindowAnimation_windowShowAnimation;
   1877                         break;
   1878                     case WindowManagerPolicy.TRANSIT_HIDE:
   1879                         attr = com.android.internal.R.styleable.WindowAnimation_windowHideAnimation;
   1880                         break;
   1881                 }
   1882                 if (attr >= 0) {
   1883                     a = mService.mAppTransition.loadAnimationAttr(mWin.mAttrs, attr);
   1884                 }
   1885             }
   1886             if (DEBUG_ANIM) Slog.v(TAG,
   1887                     "applyAnimation: win=" + this
   1888                     + " anim=" + anim + " attr=0x" + Integer.toHexString(attr)
   1889                     + " a=" + a
   1890                     + " transit=" + transit
   1891                     + " isEntrance=" + isEntrance + " Callers " + Debug.getCallers(3));
   1892             if (a != null) {
   1893                 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this);
   1894                 setAnimation(a);
   1895                 mAnimationIsEntrance = isEntrance;
   1896             }
   1897         } else {
   1898             clearAnimation();
   1899         }
   1900         if (mWin.mAttrs.type == TYPE_INPUT_METHOD) {
   1901             mService.adjustForImeIfNeeded(mWin.mDisplayContent);
   1902             if (isEntrance) {
   1903                 mWin.setDisplayLayoutNeeded();
   1904                 mService.mWindowPlacerLocked.requestTraversal();
   1905             }
   1906         }
   1907         return mAnimation != null;
   1908     }
   1909 
   1910     private void applyFadeoutDuringKeyguardExitAnimation() {
   1911         long startTime = mAnimation.getStartTime();
   1912         long duration = mAnimation.getDuration();
   1913         long elapsed = mLastAnimationTime - startTime;
   1914         long fadeDuration = duration - elapsed;
   1915         if (fadeDuration <= 0) {
   1916             // Never mind, this would be no visible animation, so abort the animation change.
   1917             return;
   1918         }
   1919         AnimationSet newAnimation = new AnimationSet(false /* shareInterpolator */);
   1920         newAnimation.setDuration(duration);
   1921         newAnimation.setStartTime(startTime);
   1922         newAnimation.addAnimation(mAnimation);
   1923         Animation fadeOut = AnimationUtils.loadAnimation(
   1924                 mContext, com.android.internal.R.anim.app_starting_exit);
   1925         fadeOut.setDuration(fadeDuration);
   1926         fadeOut.setStartOffset(elapsed);
   1927         newAnimation.addAnimation(fadeOut);
   1928         newAnimation.initialize(mWin.mFrame.width(), mWin.mFrame.height(), mAnimDx, mAnimDy);
   1929         mAnimation = newAnimation;
   1930     }
   1931 
   1932     public void dump(PrintWriter pw, String prefix, boolean dumpAll) {
   1933         if (mAnimating || mLocalAnimating || mAnimationIsEntrance
   1934                 || mAnimation != null) {
   1935             pw.print(prefix); pw.print("mAnimating="); pw.print(mAnimating);
   1936                     pw.print(" mLocalAnimating="); pw.print(mLocalAnimating);
   1937                     pw.print(" mAnimationIsEntrance="); pw.print(mAnimationIsEntrance);
   1938                     pw.print(" mAnimation="); pw.print(mAnimation);
   1939                     pw.print(" mStackClip="); pw.println(mStackClip);
   1940         }
   1941         if (mHasTransformation || mHasLocalTransformation) {
   1942             pw.print(prefix); pw.print("XForm: has=");
   1943                     pw.print(mHasTransformation);
   1944                     pw.print(" hasLocal="); pw.print(mHasLocalTransformation);
   1945                     pw.print(" "); mTransformation.printShortString(pw);
   1946                     pw.println();
   1947         }
   1948         if (mSurfaceController != null) {
   1949             mSurfaceController.dump(pw, prefix, dumpAll);
   1950         }
   1951         if (dumpAll) {
   1952             pw.print(prefix); pw.print("mDrawState="); pw.print(drawStateToString());
   1953             pw.print(prefix); pw.print(" mLastHidden="); pw.println(mLastHidden);
   1954             pw.print(prefix); pw.print("mSystemDecorRect="); mSystemDecorRect.printShortString(pw);
   1955             pw.print(" last="); mLastSystemDecorRect.printShortString(pw);
   1956             pw.print(" mHasClipRect="); pw.print(mHasClipRect);
   1957             pw.print(" mLastClipRect="); mLastClipRect.printShortString(pw);
   1958 
   1959             if (!mLastFinalClipRect.isEmpty()) {
   1960                 pw.print(" mLastFinalClipRect="); mLastFinalClipRect.printShortString(pw);
   1961             }
   1962             pw.println();
   1963         }
   1964 
   1965         if (mPendingDestroySurface != null) {
   1966             pw.print(prefix); pw.print("mPendingDestroySurface=");
   1967                     pw.println(mPendingDestroySurface);
   1968         }
   1969         if (mSurfaceResized || mSurfaceDestroyDeferred) {
   1970             pw.print(prefix); pw.print("mSurfaceResized="); pw.print(mSurfaceResized);
   1971                     pw.print(" mSurfaceDestroyDeferred="); pw.println(mSurfaceDestroyDeferred);
   1972         }
   1973         if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) {
   1974             pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha);
   1975                     pw.print(" mAlpha="); pw.print(mAlpha);
   1976                     pw.print(" mLastAlpha="); pw.println(mLastAlpha);
   1977         }
   1978         if (mHaveMatrix || mWin.mGlobalScale != 1) {
   1979             pw.print(prefix); pw.print("mGlobalScale="); pw.print(mWin.mGlobalScale);
   1980                     pw.print(" mDsDx="); pw.print(mDsDx);
   1981                     pw.print(" mDtDx="); pw.print(mDtDx);
   1982                     pw.print(" mDsDy="); pw.print(mDsDy);
   1983                     pw.print(" mDtDy="); pw.println(mDtDy);
   1984         }
   1985         if (mAnimationStartDelayed) {
   1986             pw.print(prefix); pw.print("mAnimationStartDelayed="); pw.print(mAnimationStartDelayed);
   1987         }
   1988     }
   1989 
   1990     @Override
   1991     public String toString() {
   1992         StringBuffer sb = new StringBuffer("WindowStateAnimator{");
   1993         sb.append(Integer.toHexString(System.identityHashCode(this)));
   1994         sb.append(' ');
   1995         sb.append(mWin.mAttrs.getTitle());
   1996         sb.append('}');
   1997         return sb.toString();
   1998     }
   1999 
   2000     void reclaimSomeSurfaceMemory(String operation, boolean secure) {
   2001         mService.reclaimSomeSurfaceMemoryLocked(this, operation, secure);
   2002     }
   2003 
   2004     boolean getShown() {
   2005         if (mSurfaceController != null) {
   2006             return mSurfaceController.getShown();
   2007         }
   2008         return false;
   2009     }
   2010 
   2011     void destroySurface() {
   2012         try {
   2013             if (mSurfaceController != null) {
   2014                 mSurfaceController.destroyInTransaction();
   2015             }
   2016         } catch (RuntimeException e) {
   2017             Slog.w(TAG, "Exception thrown when destroying surface " + this
   2018                     + " surface " + mSurfaceController + " session " + mSession + ": " + e);
   2019         } finally {
   2020             mWin.setHasSurface(false);
   2021             mSurfaceController = null;
   2022             mDrawState = NO_SURFACE;
   2023         }
   2024     }
   2025 
   2026     void setMoveAnimation(int left, int top) {
   2027         final Animation a = AnimationUtils.loadAnimation(mContext,
   2028                 com.android.internal.R.anim.window_move_from_decor);
   2029         setAnimation(a);
   2030         mAnimDx = mWin.mLastFrame.left - left;
   2031         mAnimDy = mWin.mLastFrame.top - top;
   2032         mAnimateMove = true;
   2033     }
   2034 
   2035     void deferTransactionUntilParentFrame(long frameNumber) {
   2036         if (!mWin.isChildWindow()) {
   2037             return;
   2038         }
   2039         mDeferTransactionUntilFrame = frameNumber;
   2040         mDeferTransactionTime = System.currentTimeMillis();
   2041         mSurfaceController.deferTransactionUntil(
   2042                 mWin.mAttachedWindow.mWinAnimator.mSurfaceController.getHandle(),
   2043                 frameNumber);
   2044     }
   2045 
   2046     // Defer the current transaction to the frame number of the last saved transaction.
   2047     // We do this to avoid shooting through an unsynchronized transaction while something is
   2048     // pending. This is generally fine, as either we will get in on the synchronization,
   2049     // or SurfaceFlinger will see that the frame has already occured. The only
   2050     // potential problem is in frame number resets so we reset things with a timeout
   2051     // every so often to be careful.
   2052     void deferToPendingTransaction() {
   2053         if (mDeferTransactionUntilFrame < 0) {
   2054             return;
   2055         }
   2056         long time = System.currentTimeMillis();
   2057         if (time > mDeferTransactionTime + PENDING_TRANSACTION_FINISH_WAIT_TIME) {
   2058             mDeferTransactionTime = -1;
   2059             mDeferTransactionUntilFrame = -1;
   2060         } else {
   2061             mSurfaceController.deferTransactionUntil(
   2062                     mWin.mAttachedWindow.mWinAnimator.mSurfaceController.getHandle(),
   2063                     mDeferTransactionUntilFrame);
   2064         }
   2065     }
   2066 
   2067     /**
   2068      * Sometimes we need to synchronize the first frame of animation with some external event.
   2069      * To achieve this, we prolong the start of the animation and keep producing the first frame of
   2070      * the animation.
   2071      */
   2072     private long getAnimationFrameTime(Animation animation, long currentTime) {
   2073         if (mAnimationStartDelayed) {
   2074             animation.setStartTime(currentTime);
   2075             return currentTime + 1;
   2076         }
   2077         return currentTime;
   2078     }
   2079 
   2080     void startDelayingAnimationStart() {
   2081         mAnimationStartDelayed = true;
   2082     }
   2083 
   2084     void endDelayingAnimationStart() {
   2085         mAnimationStartDelayed = false;
   2086     }
   2087 }
   2088