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