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