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