WindowStateAnimator.java revision f8d77da969edc2f191d349f7d9a30d02edcbd388
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 (!mWin.mExiting) {
459            return;
460        }
461
462        if (isWindowAnimating()) {
463            return;
464        }
465
466        if (WindowManagerService.localLOGV) Slog.v(
467                TAG, "Exit animation finished in " + this
468                + ": remove=" + mWin.mRemoveOnExit);
469        if (mSurfaceControl != null) {
470            mService.mDestroySurface.add(mWin);
471            mWin.mDestroying = true;
472            if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(
473                mWin, "HIDE (finishExit)", null);
474            hide();
475        }
476        mWin.mExiting = false;
477        if (mWin.mRemoveOnExit) {
478            mService.mPendingRemove.add(mWin);
479            mWin.mRemoveOnExit = false;
480        }
481        mAnimator.hideWallpapersLocked(mWin);
482    }
483
484    void hide() {
485        if (!mLastHidden) {
486            //dump();
487            mLastHidden = true;
488            if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin,
489                    "HIDE (performLayout)", null);
490            if (mSurfaceControl != null) {
491                mSurfaceShown = false;
492                try {
493                    mSurfaceControl.hide();
494                } catch (RuntimeException e) {
495                    Slog.w(TAG, "Exception hiding surface in " + mWin);
496                }
497            }
498        }
499    }
500
501    boolean finishDrawingLocked() {
502        final boolean startingWindow =
503                mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
504        if (DEBUG_STARTING_WINDOW && startingWindow) {
505            Slog.v(TAG, "Finishing drawing window " + mWin + ": mDrawState="
506                    + drawStateToString());
507        }
508        if (mDrawState == DRAW_PENDING) {
509            if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || SHOW_TRANSACTIONS || DEBUG_ORIENTATION)
510                Slog.v(TAG, "finishDrawingLocked: mDrawState=COMMIT_DRAW_PENDING " + this + " in "
511                        + mSurfaceControl);
512            if (DEBUG_STARTING_WINDOW && startingWindow) {
513                Slog.v(TAG, "Draw state now committed in " + mWin);
514            }
515            mDrawState = COMMIT_DRAW_PENDING;
516            return true;
517        }
518        return false;
519    }
520
521    // This must be called while inside a transaction.
522    boolean commitFinishDrawingLocked(long currentTime) {
523        if (DEBUG_STARTING_WINDOW &&
524                mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
525            Slog.i(TAG, "commitFinishDrawingLocked: " + mWin + " cur mDrawState="
526                    + drawStateToString());
527        }
528        if (mDrawState != COMMIT_DRAW_PENDING && mDrawState != READY_TO_SHOW) {
529            return false;
530        }
531        if (DEBUG_SURFACE_TRACE || DEBUG_ANIM) {
532            Slog.i(TAG, "commitFinishDrawingLocked: mDrawState=READY_TO_SHOW " + mSurfaceControl);
533        }
534        mDrawState = READY_TO_SHOW;
535        final AppWindowToken atoken = mWin.mAppToken;
536        if (atoken == null || atoken.allDrawn || mWin.mAttrs.type == TYPE_APPLICATION_STARTING) {
537            performShowLocked();
538        }
539        return true;
540    }
541
542    static class SurfaceTrace extends SurfaceControl {
543        private final static String SURFACE_TAG = "SurfaceTrace";
544        private final static boolean logSurfaceTrace = DEBUG_SURFACE_TRACE;
545        final static ArrayList<SurfaceTrace> sSurfaces = new ArrayList<SurfaceTrace>();
546
547        private float mSurfaceTraceAlpha = 0;
548        private int mLayer;
549        private final PointF mPosition = new PointF();
550        private final Point mSize = new Point();
551        private final Rect mWindowCrop = new Rect();
552        private boolean mShown = false;
553        private int mLayerStack;
554        private boolean mIsOpaque;
555        private float mDsdx, mDtdx, mDsdy, mDtdy;
556        private final String mName;
557
558        public SurfaceTrace(SurfaceSession s,
559                       String name, int w, int h, int format, int flags)
560                   throws OutOfResourcesException {
561            super(s, name, w, h, format, flags);
562            mName = name != null ? name : "Not named";
563            mSize.set(w, h);
564            if (logSurfaceTrace) Slog.v(SURFACE_TAG, "ctor: " + this + ". Called by "
565                    + Debug.getCallers(3));
566            synchronized (sSurfaces) {
567                sSurfaces.add(0, this);
568            }
569        }
570
571        @Override
572        public void setAlpha(float alpha) {
573            if (mSurfaceTraceAlpha != alpha) {
574                if (logSurfaceTrace) Slog.v(SURFACE_TAG, "setAlpha(" + alpha + "): OLD:" + this +
575                        ". Called by " + Debug.getCallers(3));
576                mSurfaceTraceAlpha = alpha;
577            }
578            super.setAlpha(alpha);
579        }
580
581        @Override
582        public void setLayer(int zorder) {
583            if (zorder != mLayer) {
584                if (logSurfaceTrace) Slog.v(SURFACE_TAG, "setLayer(" + zorder + "): OLD:" + this
585                        + ". Called by " + Debug.getCallers(3));
586                mLayer = zorder;
587            }
588            super.setLayer(zorder);
589
590            synchronized (sSurfaces) {
591                sSurfaces.remove(this);
592                int i;
593                for (i = sSurfaces.size() - 1; i >= 0; i--) {
594                    SurfaceTrace s = sSurfaces.get(i);
595                    if (s.mLayer < zorder) {
596                        break;
597                    }
598                }
599                sSurfaces.add(i + 1, this);
600            }
601        }
602
603        @Override
604        public void setPosition(float x, float y) {
605            if (x != mPosition.x || y != mPosition.y) {
606                if (logSurfaceTrace) Slog.v(SURFACE_TAG, "setPosition(" + x + "," + y + "): OLD:"
607                        + this + ". Called by " + Debug.getCallers(3));
608                mPosition.set(x, y);
609            }
610            super.setPosition(x, y);
611        }
612
613        @Override
614        public void setSize(int w, int h) {
615            if (w != mSize.x || h != mSize.y) {
616                if (logSurfaceTrace) Slog.v(SURFACE_TAG, "setSize(" + w + "," + h + "): OLD:"
617                        + this + ". Called by " + Debug.getCallers(3));
618                mSize.set(w, h);
619            }
620            super.setSize(w, h);
621        }
622
623        @Override
624        public void setWindowCrop(Rect crop) {
625            if (crop != null) {
626                if (!crop.equals(mWindowCrop)) {
627                    if (logSurfaceTrace) Slog.v(SURFACE_TAG, "setWindowCrop("
628                            + crop.toShortString() + "): OLD:" + this + ". Called by "
629                            + Debug.getCallers(3));
630                    mWindowCrop.set(crop);
631                }
632            }
633            super.setWindowCrop(crop);
634        }
635
636        @Override
637        public void setLayerStack(int layerStack) {
638            if (layerStack != mLayerStack) {
639                if (logSurfaceTrace) Slog.v(SURFACE_TAG, "setLayerStack(" + layerStack + "): OLD:"
640                        + this + ". Called by " + Debug.getCallers(3));
641                mLayerStack = layerStack;
642            }
643            super.setLayerStack(layerStack);
644        }
645
646        @Override
647        public void setOpaque(boolean isOpaque) {
648            if (isOpaque != mIsOpaque) {
649                if (logSurfaceTrace) Slog.v(SURFACE_TAG, "setOpaque(" + isOpaque + "): OLD:"
650                        + this + ". Called by " + Debug.getCallers(3));
651                mIsOpaque = isOpaque;
652            }
653            super.setOpaque(isOpaque);
654        }
655
656        @Override
657        public void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
658            if (dsdx != mDsdx || dtdx != mDtdx || dsdy != mDsdy || dtdy != mDtdy) {
659                if (logSurfaceTrace) Slog.v(SURFACE_TAG, "setMatrix(" + dsdx + "," + dtdx + ","
660                        + dsdy + "," + dtdy + "): OLD:" + this + ". Called by "
661                        + Debug.getCallers(3));
662                mDsdx = dsdx;
663                mDtdx = dtdx;
664                mDsdy = dsdy;
665                mDtdy = dtdy;
666            }
667            super.setMatrix(dsdx, dtdx, dsdy, dtdy);
668        }
669
670        @Override
671        public void hide() {
672            if (mShown) {
673                if (logSurfaceTrace) Slog.v(SURFACE_TAG, "hide: OLD:" + this + ". Called by "
674                        + Debug.getCallers(3));
675                mShown = false;
676            }
677            super.hide();
678        }
679
680        @Override
681        public void show() {
682            if (!mShown) {
683                if (logSurfaceTrace) Slog.v(SURFACE_TAG, "show: OLD:" + this + ". Called by "
684                        + Debug.getCallers(3));
685                mShown = true;
686            }
687            super.show();
688        }
689
690        @Override
691        public void destroy() {
692            super.destroy();
693            if (logSurfaceTrace) Slog.v(SURFACE_TAG, "destroy: " + this + ". Called by "
694                    + Debug.getCallers(3));
695            synchronized (sSurfaces) {
696                sSurfaces.remove(this);
697            }
698        }
699
700        @Override
701        public void release() {
702            super.release();
703            if (logSurfaceTrace) Slog.v(SURFACE_TAG, "release: " + this + ". Called by "
704                    + Debug.getCallers(3));
705            synchronized (sSurfaces) {
706                sSurfaces.remove(this);
707            }
708        }
709
710        static void dumpAllSurfaces(PrintWriter pw, String header) {
711            synchronized (sSurfaces) {
712                final int N = sSurfaces.size();
713                if (N <= 0) {
714                    return;
715                }
716                if (header != null) {
717                    pw.println(header);
718                }
719                pw.println("WINDOW MANAGER SURFACES (dumpsys window surfaces)");
720                for (int i = 0; i < N; i++) {
721                    SurfaceTrace s = sSurfaces.get(i);
722                    pw.print("  Surface #"); pw.print(i); pw.print(": #");
723                            pw.print(Integer.toHexString(System.identityHashCode(s)));
724                            pw.print(" "); pw.println(s.mName);
725                    pw.print("    mLayerStack="); pw.print(s.mLayerStack);
726                            pw.print(" mLayer="); pw.println(s.mLayer);
727                    pw.print("    mShown="); pw.print(s.mShown); pw.print(" mAlpha=");
728                            pw.print(s.mSurfaceTraceAlpha); pw.print(" mIsOpaque=");
729                            pw.println(s.mIsOpaque);
730                    pw.print("    mPosition="); pw.print(s.mPosition.x); pw.print(",");
731                            pw.print(s.mPosition.y);
732                            pw.print(" mSize="); pw.print(s.mSize.x); pw.print("x");
733                            pw.println(s.mSize.y);
734                    pw.print("    mCrop="); s.mWindowCrop.printShortString(pw); pw.println();
735                    pw.print("    Transform: ("); pw.print(s.mDsdx); pw.print(", ");
736                            pw.print(s.mDtdx); pw.print(", "); pw.print(s.mDsdy);
737                            pw.print(", "); pw.print(s.mDtdy); pw.println(")");
738                }
739            }
740        }
741
742        @Override
743        public String toString() {
744            return "Surface " + Integer.toHexString(System.identityHashCode(this)) + " "
745                    + mName + " (" + mLayerStack + "): shown=" + mShown + " layer=" + mLayer
746                    + " alpha=" + mSurfaceTraceAlpha + " " + mPosition.x + "," + mPosition.y
747                    + " " + mSize.x + "x" + mSize.y
748                    + " crop=" + mWindowCrop.toShortString()
749                    + " opaque=" + mIsOpaque
750                    + " (" + mDsdx + "," + mDtdx + "," + mDsdy + "," + mDtdy + ")";
751        }
752    }
753
754    SurfaceControl createSurfaceLocked() {
755        final WindowState w = mWin;
756        if (mSurfaceControl == null) {
757            if (DEBUG_ANIM || DEBUG_ORIENTATION) Slog.i(TAG,
758                    "createSurface " + this + ": mDrawState=DRAW_PENDING");
759            mDrawState = DRAW_PENDING;
760            if (w.mAppToken != null) {
761                if (w.mAppToken.mAppAnimator.animation == null) {
762                    w.mAppToken.allDrawn = false;
763                    w.mAppToken.deferClearAllDrawn = false;
764                } else {
765                    // Currently animating, persist current state of allDrawn until animation
766                    // is complete.
767                    w.mAppToken.deferClearAllDrawn = true;
768                }
769            }
770
771            mService.makeWindowFreezingScreenIfNeededLocked(w);
772
773            int flags = SurfaceControl.HIDDEN;
774            final WindowManager.LayoutParams attrs = w.mAttrs;
775
776            if ((attrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
777                flags |= SurfaceControl.SECURE;
778            }
779
780            if (mService.isScreenCaptureDisabledLocked(UserHandle.getUserId(mWin.mOwnerUid))) {
781                flags |= SurfaceControl.SECURE;
782            }
783
784            int width;
785            int height;
786            if ((attrs.flags & LayoutParams.FLAG_SCALED) != 0) {
787                // for a scaled surface, we always want the requested
788                // size.
789                width = w.mRequestedWidth;
790                height = w.mRequestedHeight;
791            } else {
792                width = w.mCompatFrame.width();
793                height = w.mCompatFrame.height();
794            }
795
796            // Something is wrong and SurfaceFlinger will not like this,
797            // try to revert to sane values
798            if (width <= 0) {
799                width = 1;
800            }
801            if (height <= 0) {
802                height = 1;
803            }
804
805            float left = w.mFrame.left + w.mXOffset;
806            float top = w.mFrame.top + w.mYOffset;
807
808            // Adjust for surface insets.
809            width += attrs.surfaceInsets.left + attrs.surfaceInsets.right;
810            height += attrs.surfaceInsets.top + attrs.surfaceInsets.bottom;
811            left -= attrs.surfaceInsets.left;
812            top -= attrs.surfaceInsets.top;
813
814            if (DEBUG_VISIBILITY) {
815                Slog.v(TAG, "Creating surface in session "
816                        + mSession.mSurfaceSession + " window " + this
817                        + " w=" + width + " h=" + height
818                        + " x=" + left + " y=" + top
819                        + " format=" + attrs.format + " flags=" + flags);
820            }
821
822            // We may abort, so initialize to defaults.
823            mSurfaceShown = false;
824            mSurfaceLayer = 0;
825            mSurfaceAlpha = 0;
826            mSurfaceX = 0;
827            mSurfaceY = 0;
828            w.mLastSystemDecorRect.set(0, 0, 0, 0);
829            mLastClipRect.set(0, 0, 0, 0);
830
831            // Set up surface control with initial size.
832            try {
833                mSurfaceW = width;
834                mSurfaceH = height;
835
836                final boolean isHwAccelerated = (attrs.flags &
837                        WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0;
838                final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format;
839                if (!PixelFormat.formatHasAlpha(attrs.format)
840                        && attrs.surfaceInsets.left == 0
841                        && attrs.surfaceInsets.top == 0
842                        && attrs.surfaceInsets.right == 0
843                        && attrs.surfaceInsets.bottom  == 0) {
844                    flags |= SurfaceControl.OPAQUE;
845                }
846
847                if (DEBUG_SURFACE_TRACE) {
848                    mSurfaceControl = new SurfaceTrace(
849                            mSession.mSurfaceSession,
850                            attrs.getTitle().toString(),
851                            width, height, format, flags);
852                } else {
853                    mSurfaceControl = new SurfaceControl(
854                        mSession.mSurfaceSession,
855                        attrs.getTitle().toString(),
856                        width, height, format, flags);
857                }
858
859                w.mHasSurface = true;
860
861                if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
862                    Slog.i(TAG, "  CREATE SURFACE "
863                            + mSurfaceControl + " IN SESSION "
864                            + mSession.mSurfaceSession
865                            + ": pid=" + mSession.mPid + " format="
866                            + attrs.format + " flags=0x"
867                            + Integer.toHexString(flags)
868                            + " / " + this);
869                }
870            } catch (OutOfResourcesException e) {
871                w.mHasSurface = false;
872                Slog.w(TAG, "OutOfResourcesException creating surface");
873                mService.reclaimSomeSurfaceMemoryLocked(this, "create", true);
874                mDrawState = NO_SURFACE;
875                return null;
876            } catch (Exception e) {
877                w.mHasSurface = false;
878                Slog.e(TAG, "Exception creating surface", e);
879                mDrawState = NO_SURFACE;
880                return null;
881            }
882
883            if (WindowManagerService.localLOGV) {
884                Slog.v(TAG, "Got surface: " + mSurfaceControl
885                        + ", set left=" + w.mFrame.left + " top=" + w.mFrame.top
886                        + ", animLayer=" + mAnimLayer);
887            }
888
889            if (SHOW_LIGHT_TRANSACTIONS) {
890                Slog.i(TAG, ">>> OPEN TRANSACTION createSurfaceLocked");
891                WindowManagerService.logSurface(w, "CREATE pos=("
892                        + w.mFrame.left + "," + w.mFrame.top + ") ("
893                        + w.mCompatFrame.width() + "x" + w.mCompatFrame.height()
894                        + "), layer=" + mAnimLayer + " HIDE", null);
895            }
896
897            // Start a new transaction and apply position & offset.
898            SurfaceControl.openTransaction();
899            try {
900                mSurfaceX = left;
901                mSurfaceY = top;
902
903                try {
904                    mSurfaceControl.setPosition(left, top);
905                    mSurfaceLayer = mAnimLayer;
906                    final DisplayContent displayContent = w.getDisplayContent();
907                    if (displayContent != null) {
908                        mSurfaceControl.setLayerStack(displayContent.getDisplay().getLayerStack());
909                    }
910                    mSurfaceControl.setLayer(mAnimLayer);
911                    mSurfaceControl.setAlpha(0);
912                    mSurfaceShown = false;
913                } catch (RuntimeException e) {
914                    Slog.w(TAG, "Error creating surface in " + w, e);
915                    mService.reclaimSomeSurfaceMemoryLocked(this, "create-init", true);
916                }
917                mLastHidden = true;
918            } finally {
919                SurfaceControl.closeTransaction();
920                if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
921                        "<<< CLOSE TRANSACTION createSurfaceLocked");
922            }
923            if (WindowManagerService.localLOGV) Slog.v(
924                    TAG, "Created surface " + this);
925        }
926        return mSurfaceControl;
927    }
928
929    void destroySurfaceLocked() {
930        if (mWin.mAppToken != null && mWin == mWin.mAppToken.startingWindow) {
931            mWin.mAppToken.startingDisplayed = false;
932        }
933
934        if (mSurfaceControl != null) {
935
936            int i = mWin.mChildWindows.size();
937            while (i > 0) {
938                i--;
939                WindowState c = mWin.mChildWindows.get(i);
940                c.mAttachedHidden = true;
941            }
942
943            try {
944                if (DEBUG_VISIBILITY) {
945                    RuntimeException e = null;
946                    if (!WindowManagerService.HIDE_STACK_CRAWLS) {
947                        e = new RuntimeException();
948                        e.fillInStackTrace();
949                    }
950                    Slog.w(TAG, "Window " + this + " destroying surface "
951                            + mSurfaceControl + ", session " + mSession, e);
952                }
953                if (mSurfaceDestroyDeferred) {
954                    if (mSurfaceControl != null && mPendingDestroySurface != mSurfaceControl) {
955                        if (mPendingDestroySurface != null) {
956                            if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
957                                RuntimeException e = null;
958                                if (!WindowManagerService.HIDE_STACK_CRAWLS) {
959                                    e = new RuntimeException();
960                                    e.fillInStackTrace();
961                                }
962                                WindowManagerService.logSurface(mWin, "DESTROY PENDING", e);
963                            }
964                            mPendingDestroySurface.destroy();
965                        }
966                        mPendingDestroySurface = mSurfaceControl;
967                    }
968                } else {
969                    if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
970                        RuntimeException e = null;
971                        if (!WindowManagerService.HIDE_STACK_CRAWLS) {
972                            e = new RuntimeException();
973                            e.fillInStackTrace();
974                        }
975                        WindowManagerService.logSurface(mWin, "DESTROY", e);
976                    }
977                    mSurfaceControl.destroy();
978                }
979                mAnimator.hideWallpapersLocked(mWin);
980            } catch (RuntimeException e) {
981                Slog.w(TAG, "Exception thrown when destroying Window " + this
982                    + " surface " + mSurfaceControl + " session " + mSession
983                    + ": " + e.toString());
984            }
985
986            mSurfaceShown = false;
987            mSurfaceControl = null;
988            mWin.mHasSurface = false;
989            mDrawState = NO_SURFACE;
990        }
991    }
992
993    void destroyDeferredSurfaceLocked() {
994        try {
995            if (mPendingDestroySurface != null) {
996                if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
997                    RuntimeException e = null;
998                    if (!WindowManagerService.HIDE_STACK_CRAWLS) {
999                        e = new RuntimeException();
1000                        e.fillInStackTrace();
1001                    }
1002                    WindowManagerService.logSurface(mWin, "DESTROY PENDING", e);
1003                }
1004                mPendingDestroySurface.destroy();
1005                mAnimator.hideWallpapersLocked(mWin);
1006            }
1007        } catch (RuntimeException e) {
1008            Slog.w(TAG, "Exception thrown when destroying Window "
1009                    + this + " surface " + mPendingDestroySurface
1010                    + " session " + mSession + ": " + e.toString());
1011        }
1012        mSurfaceDestroyDeferred = false;
1013        mPendingDestroySurface = null;
1014    }
1015
1016    void computeShownFrameLocked() {
1017        final boolean selfTransformation = mHasLocalTransformation;
1018        Transformation attachedTransformation =
1019                (mAttachedWinAnimator != null && mAttachedWinAnimator.mHasLocalTransformation)
1020                ? mAttachedWinAnimator.mTransformation : null;
1021        Transformation appTransformation = (mAppAnimator != null && mAppAnimator.hasTransformation)
1022                ? mAppAnimator.transformation : null;
1023
1024        // Wallpapers are animated based on the "real" window they
1025        // are currently targeting.
1026        final WindowState wallpaperTarget = mService.mWallpaperTarget;
1027        if (mIsWallpaper && wallpaperTarget != null && mService.mAnimateWallpaperWithTarget) {
1028            final WindowStateAnimator wallpaperAnimator = wallpaperTarget.mWinAnimator;
1029            if (wallpaperAnimator.mHasLocalTransformation &&
1030                    wallpaperAnimator.mAnimation != null &&
1031                    !wallpaperAnimator.mAnimation.getDetachWallpaper()) {
1032                attachedTransformation = wallpaperAnimator.mTransformation;
1033                if (WindowManagerService.DEBUG_WALLPAPER && attachedTransformation != null) {
1034                    Slog.v(TAG, "WP target attached xform: " + attachedTransformation);
1035                }
1036            }
1037            final AppWindowAnimator wpAppAnimator = wallpaperTarget.mAppToken == null ?
1038                    null : wallpaperTarget.mAppToken.mAppAnimator;
1039                if (wpAppAnimator != null && wpAppAnimator.hasTransformation
1040                    && wpAppAnimator.animation != null
1041                    && !wpAppAnimator.animation.getDetachWallpaper()) {
1042                appTransformation = wpAppAnimator.transformation;
1043                if (WindowManagerService.DEBUG_WALLPAPER && appTransformation != null) {
1044                    Slog.v(TAG, "WP target app xform: " + appTransformation);
1045                }
1046            }
1047        }
1048
1049        final int displayId = mWin.getDisplayId();
1050        final ScreenRotationAnimation screenRotationAnimation =
1051                mAnimator.getScreenRotationAnimationLocked(displayId);
1052        final boolean screenAnimation =
1053                screenRotationAnimation != null && screenRotationAnimation.isAnimating();
1054        if (selfTransformation || attachedTransformation != null
1055                || appTransformation != null || screenAnimation) {
1056            // cache often used attributes locally
1057            final Rect frame = mWin.mFrame;
1058            final float tmpFloats[] = mService.mTmpFloats;
1059            final Matrix tmpMatrix = mWin.mTmpMatrix;
1060
1061            // Compute the desired transformation.
1062            if (screenAnimation && screenRotationAnimation.isRotating()) {
1063                // If we are doing a screen animation, the global rotation
1064                // applied to windows can result in windows that are carefully
1065                // aligned with each other to slightly separate, allowing you
1066                // to see what is behind them.  An unsightly mess.  This...
1067                // thing...  magically makes it call good: scale each window
1068                // slightly (two pixels larger in each dimension, from the
1069                // window's center).
1070                final float w = frame.width();
1071                final float h = frame.height();
1072                if (w>=1 && h>=1) {
1073                    tmpMatrix.setScale(1 + 2/w, 1 + 2/h, w/2, h/2);
1074                } else {
1075                    tmpMatrix.reset();
1076                }
1077            } else {
1078                tmpMatrix.reset();
1079            }
1080            tmpMatrix.postScale(mWin.mGlobalScale, mWin.mGlobalScale);
1081            if (selfTransformation) {
1082                tmpMatrix.postConcat(mTransformation.getMatrix());
1083            }
1084            tmpMatrix.postTranslate(frame.left + mWin.mXOffset, frame.top + mWin.mYOffset);
1085            if (attachedTransformation != null) {
1086                tmpMatrix.postConcat(attachedTransformation.getMatrix());
1087            }
1088            if (appTransformation != null) {
1089                tmpMatrix.postConcat(appTransformation.getMatrix());
1090            }
1091            if (mAnimator.mUniverseBackground != null) {
1092                tmpMatrix.postConcat(mAnimator.mUniverseBackground.mUniverseTransform.getMatrix());
1093            }
1094            if (screenAnimation) {
1095                tmpMatrix.postConcat(screenRotationAnimation.getEnterTransformation().getMatrix());
1096            }
1097
1098            //TODO (multidisplay): Magnification is supported only for the default display.
1099            if (mService.mAccessibilityController != null && displayId == Display.DEFAULT_DISPLAY) {
1100                MagnificationSpec spec = mService.mAccessibilityController
1101                        .getMagnificationSpecForWindowLocked(mWin);
1102                if (spec != null && !spec.isNop()) {
1103                    tmpMatrix.postScale(spec.scale, spec.scale);
1104                    tmpMatrix.postTranslate(spec.offsetX, spec.offsetY);
1105                }
1106            }
1107
1108            // "convert" it into SurfaceFlinger's format
1109            // (a 2x2 matrix + an offset)
1110            // Here we must not transform the position of the surface
1111            // since it is already included in the transformation.
1112            //Slog.i(TAG, "Transform: " + matrix);
1113
1114            mHaveMatrix = true;
1115            tmpMatrix.getValues(tmpFloats);
1116            mDsDx = tmpFloats[Matrix.MSCALE_X];
1117            mDtDx = tmpFloats[Matrix.MSKEW_Y];
1118            mDsDy = tmpFloats[Matrix.MSKEW_X];
1119            mDtDy = tmpFloats[Matrix.MSCALE_Y];
1120            float x = tmpFloats[Matrix.MTRANS_X];
1121            float y = tmpFloats[Matrix.MTRANS_Y];
1122            int w = frame.width();
1123            int h = frame.height();
1124            mWin.mShownFrame.set(x, y, x+w, y+h);
1125
1126            // Now set the alpha...  but because our current hardware
1127            // can't do alpha transformation on a non-opaque surface,
1128            // turn it off if we are running an animation that is also
1129            // transforming since it is more important to have that
1130            // animation be smooth.
1131            mShownAlpha = mAlpha;
1132            mHasClipRect = false;
1133            if (!mService.mLimitedAlphaCompositing
1134                    || (!PixelFormat.formatHasAlpha(mWin.mAttrs.format)
1135                    || (mWin.isIdentityMatrix(mDsDx, mDtDx, mDsDy, mDtDy)
1136                            && x == frame.left && y == frame.top))) {
1137                //Slog.i(TAG, "Applying alpha transform");
1138                if (selfTransformation) {
1139                    mShownAlpha *= mTransformation.getAlpha();
1140                }
1141                if (attachedTransformation != null) {
1142                    mShownAlpha *= attachedTransformation.getAlpha();
1143                }
1144                if (appTransformation != null) {
1145                    mShownAlpha *= appTransformation.getAlpha();
1146                    if (appTransformation.hasClipRect()) {
1147                        mClipRect.set(appTransformation.getClipRect());
1148                        if (mWin.mHScale > 0) {
1149                            mClipRect.left /= mWin.mHScale;
1150                            mClipRect.right /= mWin.mHScale;
1151                        }
1152                        if (mWin.mVScale > 0) {
1153                            mClipRect.top /= mWin.mVScale;
1154                            mClipRect.bottom /= mWin.mVScale;
1155                        }
1156                        mHasClipRect = true;
1157                    }
1158                }
1159                if (mAnimator.mUniverseBackground != null) {
1160                    mShownAlpha *= mAnimator.mUniverseBackground.mUniverseTransform.getAlpha();
1161                }
1162                if (screenAnimation) {
1163                    mShownAlpha *= screenRotationAnimation.getEnterTransformation().getAlpha();
1164                }
1165            } else {
1166                //Slog.i(TAG, "Not applying alpha transform");
1167            }
1168
1169            if ((DEBUG_SURFACE_TRACE || WindowManagerService.localLOGV)
1170                    && (mShownAlpha == 1.0 || mShownAlpha == 0.0)) Slog.v(
1171                    TAG, "computeShownFrameLocked: Animating " + this + " mAlpha=" + mAlpha
1172                    + " self=" + (selfTransformation ? mTransformation.getAlpha() : "null")
1173                    + " attached=" + (attachedTransformation == null ?
1174                            "null" : attachedTransformation.getAlpha())
1175                    + " app=" + (appTransformation == null ? "null" : appTransformation.getAlpha())
1176                    + " screen=" + (screenAnimation ?
1177                            screenRotationAnimation.getEnterTransformation().getAlpha() : "null"));
1178            return;
1179        } else if (mIsWallpaper && mService.mInnerFields.mWallpaperActionPending) {
1180            return;
1181        }
1182
1183        if (WindowManagerService.localLOGV) Slog.v(
1184                TAG, "computeShownFrameLocked: " + this +
1185                " not attached, mAlpha=" + mAlpha);
1186
1187        final boolean applyUniverseTransformation = (mAnimator.mUniverseBackground != null
1188                && mWin.mAttrs.type != WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND
1189                && mWin.mBaseLayer < mAnimator.mAboveUniverseLayer);
1190        MagnificationSpec spec = null;
1191        //TODO (multidisplay): Magnification is supported only for the default display.
1192        if (mService.mAccessibilityController != null && displayId == Display.DEFAULT_DISPLAY) {
1193            spec = mService.mAccessibilityController.getMagnificationSpecForWindowLocked(mWin);
1194        }
1195        if (applyUniverseTransformation || spec != null) {
1196            final Rect frame = mWin.mFrame;
1197            final float tmpFloats[] = mService.mTmpFloats;
1198            final Matrix tmpMatrix = mWin.mTmpMatrix;
1199
1200            tmpMatrix.setScale(mWin.mGlobalScale, mWin.mGlobalScale);
1201            tmpMatrix.postTranslate(frame.left + mWin.mXOffset, frame.top + mWin.mYOffset);
1202
1203            if (applyUniverseTransformation) {
1204                tmpMatrix.postConcat(mAnimator.mUniverseBackground.mUniverseTransform.getMatrix());
1205            }
1206
1207            if (spec != null && !spec.isNop()) {
1208                tmpMatrix.postScale(spec.scale, spec.scale);
1209                tmpMatrix.postTranslate(spec.offsetX, spec.offsetY);
1210            }
1211
1212            tmpMatrix.getValues(tmpFloats);
1213
1214            mHaveMatrix = true;
1215            mDsDx = tmpFloats[Matrix.MSCALE_X];
1216            mDtDx = tmpFloats[Matrix.MSKEW_Y];
1217            mDsDy = tmpFloats[Matrix.MSKEW_X];
1218            mDtDy = tmpFloats[Matrix.MSCALE_Y];
1219            float x = tmpFloats[Matrix.MTRANS_X];
1220            float y = tmpFloats[Matrix.MTRANS_Y];
1221            int w = frame.width();
1222            int h = frame.height();
1223            mWin.mShownFrame.set(x, y, x + w, y + h);
1224
1225            mShownAlpha = mAlpha;
1226            if (applyUniverseTransformation) {
1227                mShownAlpha *= mAnimator.mUniverseBackground.mUniverseTransform.getAlpha();
1228            }
1229        } else {
1230            mWin.mShownFrame.set(mWin.mFrame);
1231            if (mWin.mXOffset != 0 || mWin.mYOffset != 0) {
1232                mWin.mShownFrame.offset(mWin.mXOffset, mWin.mYOffset);
1233            }
1234            mShownAlpha = mAlpha;
1235            mHaveMatrix = false;
1236            mDsDx = mWin.mGlobalScale;
1237            mDtDx = 0;
1238            mDsDy = 0;
1239            mDtDy = mWin.mGlobalScale;
1240        }
1241    }
1242
1243    void applyDecorRect(final Rect decorRect) {
1244        final WindowState w = mWin;
1245        final int width = w.mFrame.width();
1246        final int height = w.mFrame.height();
1247
1248        // Compute the offset of the window in relation to the decor rect.
1249        final int left = w.mXOffset + w.mFrame.left;
1250        final int top = w.mYOffset + w.mFrame.top;
1251
1252        // Initialize the decor rect to the entire frame.
1253        w.mSystemDecorRect.set(0, 0, width, height);
1254
1255        // Intersect with the decor rect, offsetted by window position.
1256        w.mSystemDecorRect.intersect(decorRect.left - left, decorRect.top - top,
1257                decorRect.right - left, decorRect.bottom - top);
1258
1259        // If size compatibility is being applied to the window, the
1260        // surface is scaled relative to the screen.  Also apply this
1261        // scaling to the crop rect.  We aren't using the standard rect
1262        // scale function because we want to round things to make the crop
1263        // always round to a larger rect to ensure we don't crop too
1264        // much and hide part of the window that should be seen.
1265        if (w.mEnforceSizeCompat && w.mInvGlobalScale != 1.0f) {
1266            final float scale = w.mInvGlobalScale;
1267            w.mSystemDecorRect.left = (int) (w.mSystemDecorRect.left * scale - 0.5f);
1268            w.mSystemDecorRect.top = (int) (w.mSystemDecorRect.top * scale - 0.5f);
1269            w.mSystemDecorRect.right = (int) ((w.mSystemDecorRect.right+1) * scale - 0.5f);
1270            w.mSystemDecorRect.bottom = (int) ((w.mSystemDecorRect.bottom+1) * scale - 0.5f);
1271        }
1272    }
1273
1274    void updateSurfaceWindowCrop(final boolean recoveringMemory) {
1275        final WindowState w = mWin;
1276        final DisplayContent displayContent = w.getDisplayContent();
1277        if (displayContent == null) {
1278            return;
1279        }
1280
1281        // Need to recompute a new system decor rect each time.
1282        if ((w.mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) {
1283            // Currently can't do this cropping for scaled windows.  We'll
1284            // just keep the crop rect the same as the source surface.
1285            w.mSystemDecorRect.set(0, 0, w.mRequestedWidth, w.mRequestedHeight);
1286        } else if (!w.isDefaultDisplay()) {
1287            // On a different display there is no system decor.  Crop the window
1288            // by the screen boundaries.
1289            final DisplayInfo displayInfo = displayContent.getDisplayInfo();
1290            w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(), w.mCompatFrame.height());
1291            w.mSystemDecorRect.intersect(-w.mCompatFrame.left, -w.mCompatFrame.top,
1292                    displayInfo.logicalWidth - w.mCompatFrame.left,
1293                    displayInfo.logicalHeight - w.mCompatFrame.top);
1294        } else if (w.mLayer >= mService.mSystemDecorLayer) {
1295            // Above the decor layer is easy, just use the entire window.
1296            // Unless we have a universe background...  in which case all the
1297            // windows need to be cropped by the screen, so they don't cover
1298            // the universe background.
1299            if (mAnimator.mUniverseBackground == null) {
1300                w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(), w.mCompatFrame.height());
1301            } else {
1302                applyDecorRect(mService.mScreenRect);
1303            }
1304        } else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND
1305                || w.mDecorFrame.isEmpty()) {
1306            // The universe background isn't cropped, nor windows without policy decor.
1307            w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(), w.mCompatFrame.height());
1308        } else if (w.mAttrs.type == LayoutParams.TYPE_WALLPAPER && mAnimator.mAnimating) {
1309            // If we're animating, the wallpaper crop should only be updated at the end of the
1310            // animation.
1311            mTmpClipRect.set(w.mSystemDecorRect);
1312            applyDecorRect(w.mDecorFrame);
1313            w.mSystemDecorRect.union(mTmpClipRect);
1314        } else {
1315            // Crop to the system decor specified by policy.
1316            applyDecorRect(w.mDecorFrame);
1317        }
1318
1319        // By default, the clip rect is the system decor.
1320        final Rect clipRect = mTmpClipRect;
1321        clipRect.set(w.mSystemDecorRect);
1322
1323        // Expand the clip rect for surface insets.
1324        final WindowManager.LayoutParams attrs = w.mAttrs;
1325        clipRect.left -= attrs.surfaceInsets.left;
1326        clipRect.top -= attrs.surfaceInsets.top;
1327        clipRect.right += attrs.surfaceInsets.right;
1328        clipRect.bottom += attrs.surfaceInsets.bottom;
1329
1330        // If we have an animated clip rect, intersect it with the clip rect.
1331        if (mHasClipRect) {
1332            // NOTE: We are adding a temporary workaround due to the status bar
1333            // not always reporting the correct system decor rect. In such
1334            // cases, we take into account the specified content insets as well.
1335            if ((w.mSystemUiVisibility & SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN)
1336                    == SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN
1337                    || (w.mAttrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0) {
1338                // Don't apply the workaround to apps explicitly requesting
1339                // fullscreen layout or when the bars are transparent.
1340                clipRect.intersect(mClipRect);
1341            } else {
1342                final int offsetTop = Math.max(clipRect.top, w.mContentInsets.top);
1343                clipRect.offset(0, -offsetTop);
1344                clipRect.intersect(mClipRect);
1345                clipRect.offset(0, offsetTop);
1346            }
1347        }
1348
1349        // The clip rect was generated assuming (0,0) as the window origin,
1350        // so we need to translate to match the actual surface coordinates.
1351        clipRect.offset(attrs.surfaceInsets.left, attrs.surfaceInsets.top);
1352
1353        if (!clipRect.equals(mLastClipRect)) {
1354            mLastClipRect.set(clipRect);
1355            try {
1356                if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
1357                        "CROP " + clipRect.toShortString(), null);
1358                mSurfaceControl.setWindowCrop(clipRect);
1359            } catch (RuntimeException e) {
1360                Slog.w(TAG, "Error setting crop surface of " + w
1361                        + " crop=" + clipRect.toShortString(), e);
1362                if (!recoveringMemory) {
1363                    mService.reclaimSomeSurfaceMemoryLocked(this, "crop", true);
1364                }
1365            }
1366        }
1367    }
1368
1369    void setSurfaceBoundariesLocked(final boolean recoveringMemory) {
1370        final WindowState w = mWin;
1371
1372        int width;
1373        int height;
1374        if ((w.mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) {
1375            // for a scaled surface, we always want the requested
1376            // size.
1377            width  = w.mRequestedWidth;
1378            height = w.mRequestedHeight;
1379        } else {
1380            width = w.mCompatFrame.width();
1381            height = w.mCompatFrame.height();
1382        }
1383
1384        // Something is wrong and SurfaceFlinger will not like this,
1385        // try to revert to sane values
1386        if (width < 1) {
1387            width = 1;
1388        }
1389        if (height < 1) {
1390            height = 1;
1391        }
1392
1393        float left = w.mShownFrame.left;
1394        float top = w.mShownFrame.top;
1395
1396        // Adjust for surface insets.
1397        final LayoutParams attrs = w.getAttrs();
1398        width += attrs.surfaceInsets.left + attrs.surfaceInsets.right;
1399        height += attrs.surfaceInsets.top + attrs.surfaceInsets.bottom;
1400        left -= attrs.surfaceInsets.left;
1401        top -= attrs.surfaceInsets.top;
1402
1403        final boolean surfaceMoved = mSurfaceX != left || mSurfaceY != top;
1404        if (surfaceMoved) {
1405            mSurfaceX = left;
1406            mSurfaceY = top;
1407
1408            try {
1409                if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
1410                        "POS " + left + ", " + top, null);
1411                mSurfaceControl.setPosition(left, top);
1412            } catch (RuntimeException e) {
1413                Slog.w(TAG, "Error positioning surface of " + w
1414                        + " pos=(" + left + "," + top + ")", e);
1415                if (!recoveringMemory) {
1416                    mService.reclaimSomeSurfaceMemoryLocked(this, "position", true);
1417                }
1418            }
1419        }
1420
1421        final boolean surfaceResized = mSurfaceW != width || mSurfaceH != height;
1422        if (surfaceResized) {
1423            mSurfaceW = width;
1424            mSurfaceH = height;
1425            mSurfaceResized = true;
1426
1427            try {
1428                if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
1429                        "SIZE " + width + "x" + height, null);
1430                mSurfaceControl.setSize(width, height);
1431                mAnimator.setPendingLayoutChanges(w.getDisplayId(),
1432                        WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
1433                if ((w.mAttrs.flags & LayoutParams.FLAG_DIM_BEHIND) != 0) {
1434                    final TaskStack stack = w.getStack();
1435                    if (stack != null) {
1436                        stack.startDimmingIfNeeded(this);
1437                    }
1438                }
1439            } catch (RuntimeException e) {
1440                // If something goes wrong with the surface (such
1441                // as running out of memory), don't take down the
1442                // entire system.
1443                Slog.e(TAG, "Error resizing surface of " + w
1444                        + " size=(" + width + "x" + height + ")", e);
1445                if (!recoveringMemory) {
1446                    mService.reclaimSomeSurfaceMemoryLocked(this, "size", true);
1447                }
1448            }
1449        }
1450
1451        updateSurfaceWindowCrop(recoveringMemory);
1452    }
1453
1454    public void prepareSurfaceLocked(final boolean recoveringMemory) {
1455        final WindowState w = mWin;
1456        if (mSurfaceControl == null) {
1457            if (w.mOrientationChanging) {
1458                if (DEBUG_ORIENTATION) {
1459                    Slog.v(TAG, "Orientation change skips hidden " + w);
1460                }
1461                w.mOrientationChanging = false;
1462            }
1463            return;
1464        }
1465
1466        boolean displayed = false;
1467
1468        computeShownFrameLocked();
1469
1470        setSurfaceBoundariesLocked(recoveringMemory);
1471
1472        if (mIsWallpaper && !mWin.mWallpaperVisible) {
1473            // Wallpaper is no longer visible and there is no wp target => hide it.
1474            hide();
1475        } else if (w.mAttachedHidden || !w.isOnScreen()) {
1476            hide();
1477            mAnimator.hideWallpapersLocked(w);
1478
1479            // If we are waiting for this window to handle an
1480            // orientation change, well, it is hidden, so
1481            // doesn't really matter.  Note that this does
1482            // introduce a potential glitch if the window
1483            // becomes unhidden before it has drawn for the
1484            // new orientation.
1485            if (w.mOrientationChanging) {
1486                w.mOrientationChanging = false;
1487                if (DEBUG_ORIENTATION) Slog.v(TAG,
1488                        "Orientation change skips hidden " + w);
1489            }
1490        } else if (mLastLayer != mAnimLayer
1491                || mLastAlpha != mShownAlpha
1492                || mLastDsDx != mDsDx
1493                || mLastDtDx != mDtDx
1494                || mLastDsDy != mDsDy
1495                || mLastDtDy != mDtDy
1496                || w.mLastHScale != w.mHScale
1497                || w.mLastVScale != w.mVScale
1498                || mLastHidden) {
1499            displayed = true;
1500            mLastAlpha = mShownAlpha;
1501            mLastLayer = mAnimLayer;
1502            mLastDsDx = mDsDx;
1503            mLastDtDx = mDtDx;
1504            mLastDsDy = mDsDy;
1505            mLastDtDy = mDtDy;
1506            w.mLastHScale = w.mHScale;
1507            w.mLastVScale = w.mVScale;
1508            if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
1509                    "alpha=" + mShownAlpha + " layer=" + mAnimLayer
1510                    + " matrix=[" + mDsDx + "*" + w.mHScale
1511                    + "," + mDtDx + "*" + w.mVScale
1512                    + "][" + mDsDy + "*" + w.mHScale
1513                    + "," + mDtDy + "*" + w.mVScale + "]", null);
1514            if (mSurfaceControl != null) {
1515                try {
1516                    mSurfaceAlpha = mShownAlpha;
1517                    mSurfaceControl.setAlpha(mShownAlpha);
1518                    mSurfaceLayer = mAnimLayer;
1519                    mSurfaceControl.setLayer(mAnimLayer);
1520                    mSurfaceControl.setMatrix(
1521                            mDsDx * w.mHScale, mDtDx * w.mVScale,
1522                            mDsDy * w.mHScale, mDtDy * w.mVScale);
1523
1524                    if (mLastHidden && mDrawState == HAS_DRAWN) {
1525                        if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
1526                                "SHOW (performLayout)", null);
1527                        if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + w
1528                                + " during relayout");
1529                        if (showSurfaceRobustlyLocked()) {
1530                            mLastHidden = false;
1531                            if (mIsWallpaper) {
1532                                mService.dispatchWallpaperVisibility(w, true);
1533                            }
1534                            // This draw means the difference between unique content and mirroring.
1535                            // Run another pass through performLayout to set mHasContent in the
1536                            // LogicalDisplay.
1537                            mAnimator.setPendingLayoutChanges(w.getDisplayId(),
1538                                    WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM);
1539                        } else {
1540                            w.mOrientationChanging = false;
1541                        }
1542                    }
1543                    if (mSurfaceControl != null) {
1544                        w.mToken.hasVisible = true;
1545                    }
1546                } catch (RuntimeException e) {
1547                    Slog.w(TAG, "Error updating surface in " + w, e);
1548                    if (!recoveringMemory) {
1549                        mService.reclaimSomeSurfaceMemoryLocked(this, "update", true);
1550                    }
1551                }
1552            }
1553        } else {
1554            if (DEBUG_ANIM && isAnimating()) {
1555                Slog.v(TAG, "prepareSurface: No changes in animation for " + this);
1556            }
1557            displayed = true;
1558        }
1559
1560        if (displayed) {
1561            if (w.mOrientationChanging) {
1562                if (!w.isDrawnLw()) {
1563                    mAnimator.mBulkUpdateParams &= ~SET_ORIENTATION_CHANGE_COMPLETE;
1564                    mAnimator.mLastWindowFreezeSource = w;
1565                    if (DEBUG_ORIENTATION) Slog.v(TAG,
1566                            "Orientation continue waiting for draw in " + w);
1567                } else {
1568                    w.mOrientationChanging = false;
1569                    if (DEBUG_ORIENTATION) Slog.v(TAG, "Orientation change complete in " + w);
1570                }
1571            }
1572            w.mToken.hasVisible = true;
1573        }
1574    }
1575
1576    void setTransparentRegionHintLocked(final Region region) {
1577        if (mSurfaceControl == null) {
1578            Slog.w(TAG, "setTransparentRegionHint: null mSurface after mHasSurface true");
1579            return;
1580        }
1581        if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setTransparentRegion");
1582        SurfaceControl.openTransaction();
1583        try {
1584            if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin,
1585                    "transparentRegionHint=" + region, null);
1586            mSurfaceControl.setTransparentRegionHint(region);
1587        } finally {
1588            SurfaceControl.closeTransaction();
1589            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
1590                    "<<< CLOSE TRANSACTION setTransparentRegion");
1591        }
1592    }
1593
1594    void setWallpaperOffset(RectF shownFrame) {
1595        final LayoutParams attrs = mWin.getAttrs();
1596        final int left = ((int) shownFrame.left) - attrs.surfaceInsets.left;
1597        final int top = ((int) shownFrame.top) - attrs.surfaceInsets.top;
1598        if (mSurfaceX != left || mSurfaceY != top) {
1599            mSurfaceX = left;
1600            mSurfaceY = top;
1601            if (mAnimating) {
1602                // If this window (or its app token) is animating, then the position
1603                // of the surface will be re-computed on the next animation frame.
1604                // We can't poke it directly here because it depends on whatever
1605                // transformation is being applied by the animation.
1606                return;
1607            }
1608            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setWallpaperOffset");
1609            SurfaceControl.openTransaction();
1610            try {
1611                if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin,
1612                        "POS " + left + ", " + top, null);
1613                mSurfaceControl.setPosition(mWin.mFrame.left + left, mWin.mFrame.top + top);
1614                updateSurfaceWindowCrop(false);
1615            } catch (RuntimeException e) {
1616                Slog.w(TAG, "Error positioning surface of " + mWin
1617                        + " pos=(" + left + "," + top + ")", e);
1618            } finally {
1619                SurfaceControl.closeTransaction();
1620                if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
1621                        "<<< CLOSE TRANSACTION setWallpaperOffset");
1622            }
1623        }
1624    }
1625
1626    void setOpaqueLocked(boolean isOpaque) {
1627        if (mSurfaceControl == null) {
1628            return;
1629        }
1630        if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setOpaqueLocked");
1631        SurfaceControl.openTransaction();
1632        try {
1633            if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin, "isOpaque=" + isOpaque,
1634                    null);
1635            mSurfaceControl.setOpaque(isOpaque);
1636        } finally {
1637            SurfaceControl.closeTransaction();
1638            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION setOpaqueLocked");
1639        }
1640    }
1641
1642    // This must be called while inside a transaction.
1643    boolean performShowLocked() {
1644        if (mWin.isHiddenFromUserLocked()) {
1645            return false;
1646        }
1647        if (DEBUG_VISIBILITY || (DEBUG_STARTING_WINDOW &&
1648                mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING)) {
1649            RuntimeException e = null;
1650            if (!WindowManagerService.HIDE_STACK_CRAWLS) {
1651                e = new RuntimeException();
1652                e.fillInStackTrace();
1653            }
1654            Slog.v(TAG, "performShow on " + this
1655                    + ": mDrawState=" + mDrawState + " readyForDisplay="
1656                    + mWin.isReadyForDisplayIgnoringKeyguard()
1657                    + " starting=" + (mWin.mAttrs.type == TYPE_APPLICATION_STARTING)
1658                    + " during animation: policyVis=" + mWin.mPolicyVisibility
1659                    + " attHidden=" + mWin.mAttachedHidden
1660                    + " tok.hiddenRequested="
1661                    + (mWin.mAppToken != null ? mWin.mAppToken.hiddenRequested : false)
1662                    + " tok.hidden="
1663                    + (mWin.mAppToken != null ? mWin.mAppToken.hidden : false)
1664                    + " animating=" + mAnimating
1665                    + " tok animating="
1666                    + (mAppAnimator != null ? mAppAnimator.animating : false), e);
1667        }
1668        if (mDrawState == READY_TO_SHOW && mWin.isReadyForDisplayIgnoringKeyguard()) {
1669            if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION)
1670                WindowManagerService.logSurface(mWin, "SHOW (performShowLocked)", null);
1671            if (DEBUG_VISIBILITY || (DEBUG_STARTING_WINDOW &&
1672                    mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING)) {
1673                Slog.v(TAG, "Showing " + this
1674                        + " during animation: policyVis=" + mWin.mPolicyVisibility
1675                        + " attHidden=" + mWin.mAttachedHidden
1676                        + " tok.hiddenRequested="
1677                        + (mWin.mAppToken != null ? mWin.mAppToken.hiddenRequested : false)
1678                        + " tok.hidden="
1679                        + (mWin.mAppToken != null ? mWin.mAppToken.hidden : false)
1680                        + " animating=" + mAnimating
1681                        + " tok animating="
1682                        + (mAppAnimator != null ? mAppAnimator.animating : false));
1683            }
1684
1685            mService.enableScreenIfNeededLocked();
1686
1687            applyEnterAnimationLocked();
1688
1689            // Force the show in the next prepareSurfaceLocked() call.
1690            mLastAlpha = -1;
1691            if (DEBUG_SURFACE_TRACE || DEBUG_ANIM)
1692                Slog.v(TAG, "performShowLocked: mDrawState=HAS_DRAWN in " + this);
1693            mDrawState = HAS_DRAWN;
1694            mService.scheduleAnimationLocked();
1695
1696            int i = mWin.mChildWindows.size();
1697            while (i > 0) {
1698                i--;
1699                WindowState c = mWin.mChildWindows.get(i);
1700                if (c.mAttachedHidden) {
1701                    c.mAttachedHidden = false;
1702                    if (c.mWinAnimator.mSurfaceControl != null) {
1703                        c.mWinAnimator.performShowLocked();
1704                        // It hadn't been shown, which means layout not
1705                        // performed on it, so now we want to make sure to
1706                        // do a layout.  If called from within the transaction
1707                        // loop, this will cause it to restart with a new
1708                        // layout.
1709                        final DisplayContent displayContent = c.getDisplayContent();
1710                        if (displayContent != null) {
1711                            displayContent.layoutNeeded = true;
1712                        }
1713                    }
1714                }
1715            }
1716
1717            if (mWin.mAttrs.type != TYPE_APPLICATION_STARTING
1718                    && mWin.mAppToken != null) {
1719                mWin.mAppToken.firstWindowDrawn = true;
1720
1721                if (mWin.mAppToken.startingData != null) {
1722                    if (WindowManagerService.DEBUG_STARTING_WINDOW ||
1723                            WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
1724                            "Finish starting " + mWin.mToken
1725                            + ": first real window is shown, no animation");
1726                    // If this initial window is animating, stop it -- we
1727                    // will do an animation to reveal it from behind the
1728                    // starting window, so there is no need for it to also
1729                    // be doing its own stuff.
1730                    clearAnimation();
1731                    mService.mFinishedStarting.add(mWin.mAppToken);
1732                    mService.mH.sendEmptyMessage(H.FINISHED_STARTING);
1733                }
1734                mWin.mAppToken.updateReportedVisibilityLocked();
1735            }
1736
1737            return true;
1738        }
1739
1740        return false;
1741    }
1742
1743    /**
1744     * Have the surface flinger show a surface, robustly dealing with
1745     * error conditions.  In particular, if there is not enough memory
1746     * to show the surface, then we will try to get rid of other surfaces
1747     * in order to succeed.
1748     *
1749     * @return Returns true if the surface was successfully shown.
1750     */
1751    boolean showSurfaceRobustlyLocked() {
1752        try {
1753            if (mSurfaceControl != null) {
1754                mSurfaceShown = true;
1755                mSurfaceControl.show();
1756                if (mWin.mTurnOnScreen) {
1757                    if (DEBUG_VISIBILITY) Slog.v(TAG,
1758                            "Show surface turning screen on: " + mWin);
1759                    mWin.mTurnOnScreen = false;
1760                    mAnimator.mBulkUpdateParams |= SET_TURN_ON_SCREEN;
1761                }
1762            }
1763            return true;
1764        } catch (RuntimeException e) {
1765            Slog.w(TAG, "Failure showing surface " + mSurfaceControl + " in " + mWin, e);
1766        }
1767
1768        mService.reclaimSomeSurfaceMemoryLocked(this, "show", true);
1769
1770        return false;
1771    }
1772
1773    void applyEnterAnimationLocked() {
1774        final int transit;
1775        if (mEnterAnimationPending) {
1776            mEnterAnimationPending = false;
1777            transit = WindowManagerPolicy.TRANSIT_ENTER;
1778        } else {
1779            transit = WindowManagerPolicy.TRANSIT_SHOW;
1780        }
1781        applyAnimationLocked(transit, true);
1782        //TODO (multidisplay): Magnification is supported only for the default display.
1783        if (mService.mAccessibilityController != null
1784                && mWin.getDisplayId() == Display.DEFAULT_DISPLAY) {
1785            mService.mAccessibilityController.onWindowTransitionLocked(mWin, transit);
1786        }
1787    }
1788
1789    /**
1790     * Choose the correct animation and set it to the passed WindowState.
1791     * @param transit If AppTransition.TRANSIT_PREVIEW_DONE and the app window has been drawn
1792     *      then the animation will be app_starting_exit. Any other value loads the animation from
1793     *      the switch statement below.
1794     * @param isEntrance The animation type the last time this was called. Used to keep from
1795     *      loading the same animation twice.
1796     * @return true if an animation has been loaded.
1797     */
1798    boolean applyAnimationLocked(int transit, boolean isEntrance) {
1799        if ((mLocalAnimating && mAnimationIsEntrance == isEntrance)
1800                || mKeyguardGoingAwayAnimation) {
1801            // If we are trying to apply an animation, but already running
1802            // an animation of the same type, then just leave that one alone.
1803
1804            // If we are in a keyguard exit animation, and the window should animate away, modify
1805            // keyguard exit animation such that it also fades out.
1806            if (mAnimation != null && mKeyguardGoingAwayAnimation
1807                    && transit == WindowManagerPolicy.TRANSIT_PREVIEW_DONE) {
1808                applyFadeoutDuringKeyguardExitAnimation();
1809            }
1810            return true;
1811        }
1812
1813        // Only apply an animation if the display isn't frozen.  If it is
1814        // frozen, there is no reason to animate and it can cause strange
1815        // artifacts when we unfreeze the display if some different animation
1816        // is running.
1817        if (mService.okToDisplay()) {
1818            int anim = mPolicy.selectAnimationLw(mWin, transit);
1819            int attr = -1;
1820            Animation a = null;
1821            if (anim != 0) {
1822                a = anim != -1 ? AnimationUtils.loadAnimation(mContext, anim) : null;
1823            } else {
1824                switch (transit) {
1825                    case WindowManagerPolicy.TRANSIT_ENTER:
1826                        attr = com.android.internal.R.styleable.WindowAnimation_windowEnterAnimation;
1827                        break;
1828                    case WindowManagerPolicy.TRANSIT_EXIT:
1829                        attr = com.android.internal.R.styleable.WindowAnimation_windowExitAnimation;
1830                        break;
1831                    case WindowManagerPolicy.TRANSIT_SHOW:
1832                        attr = com.android.internal.R.styleable.WindowAnimation_windowShowAnimation;
1833                        break;
1834                    case WindowManagerPolicy.TRANSIT_HIDE:
1835                        attr = com.android.internal.R.styleable.WindowAnimation_windowHideAnimation;
1836                        break;
1837                }
1838                if (attr >= 0) {
1839                    a = mService.mAppTransition.loadAnimationAttr(mWin.mAttrs, attr);
1840                }
1841            }
1842            if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
1843                    "applyAnimation: win=" + this
1844                    + " anim=" + anim + " attr=0x" + Integer.toHexString(attr)
1845                    + " a=" + a
1846                    + " transit=" + transit
1847                    + " isEntrance=" + isEntrance + " Callers " + Debug.getCallers(3));
1848            if (a != null) {
1849                if (WindowManagerService.DEBUG_ANIM) {
1850                    RuntimeException e = null;
1851                    if (!WindowManagerService.HIDE_STACK_CRAWLS) {
1852                        e = new RuntimeException();
1853                        e.fillInStackTrace();
1854                    }
1855                    Slog.v(TAG, "Loaded animation " + a + " for " + this, e);
1856                }
1857                setAnimation(a);
1858                mAnimationIsEntrance = isEntrance;
1859            }
1860        } else {
1861            clearAnimation();
1862        }
1863
1864        return mAnimation != null;
1865    }
1866
1867    private void applyFadeoutDuringKeyguardExitAnimation() {
1868        long startTime = mAnimation.getStartTime();
1869        long duration = mAnimation.getDuration();
1870        long elapsed = mLastAnimationTime - startTime;
1871        long fadeDuration = duration - elapsed;
1872        if (fadeDuration <= 0) {
1873            // Never mind, this would be no visible animation, so abort the animation change.
1874            return;
1875        }
1876        AnimationSet newAnimation = new AnimationSet(false /* shareInterpolator */);
1877        newAnimation.setDuration(duration);
1878        newAnimation.setStartTime(startTime);
1879        newAnimation.addAnimation(mAnimation);
1880        Animation fadeOut = AnimationUtils.loadAnimation(
1881                mContext, com.android.internal.R.anim.app_starting_exit);
1882        fadeOut.setDuration(fadeDuration);
1883        fadeOut.setStartOffset(elapsed);
1884        newAnimation.addAnimation(fadeOut);
1885        newAnimation.initialize(mWin.mFrame.width(), mWin.mFrame.height(), mAnimDw, mAnimDh);
1886        mAnimation = newAnimation;
1887    }
1888
1889    public void dump(PrintWriter pw, String prefix, boolean dumpAll) {
1890        if (mAnimating || mLocalAnimating || mAnimationIsEntrance
1891                || mAnimation != null) {
1892            pw.print(prefix); pw.print("mAnimating="); pw.print(mAnimating);
1893                    pw.print(" mLocalAnimating="); pw.print(mLocalAnimating);
1894                    pw.print(" mAnimationIsEntrance="); pw.print(mAnimationIsEntrance);
1895                    pw.print(" mAnimation="); pw.println(mAnimation);
1896        }
1897        if (mHasTransformation || mHasLocalTransformation) {
1898            pw.print(prefix); pw.print("XForm: has=");
1899                    pw.print(mHasTransformation);
1900                    pw.print(" hasLocal="); pw.print(mHasLocalTransformation);
1901                    pw.print(" "); mTransformation.printShortString(pw);
1902                    pw.println();
1903        }
1904        if (mSurfaceControl != null) {
1905            if (dumpAll) {
1906                pw.print(prefix); pw.print("mSurface="); pw.println(mSurfaceControl);
1907                pw.print(prefix); pw.print("mDrawState=");
1908                pw.print(drawStateToString());
1909                pw.print(" mLastHidden="); pw.println(mLastHidden);
1910            }
1911            pw.print(prefix); pw.print("Surface: shown="); pw.print(mSurfaceShown);
1912                    pw.print(" layer="); pw.print(mSurfaceLayer);
1913                    pw.print(" alpha="); pw.print(mSurfaceAlpha);
1914                    pw.print(" rect=("); pw.print(mSurfaceX);
1915                    pw.print(","); pw.print(mSurfaceY);
1916                    pw.print(") "); pw.print(mSurfaceW);
1917                    pw.print(" x "); pw.println(mSurfaceH);
1918        }
1919        if (mPendingDestroySurface != null) {
1920            pw.print(prefix); pw.print("mPendingDestroySurface=");
1921                    pw.println(mPendingDestroySurface);
1922        }
1923        if (mSurfaceResized || mSurfaceDestroyDeferred) {
1924            pw.print(prefix); pw.print("mSurfaceResized="); pw.print(mSurfaceResized);
1925                    pw.print(" mSurfaceDestroyDeferred="); pw.println(mSurfaceDestroyDeferred);
1926        }
1927        if (mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND) {
1928            pw.print(prefix); pw.print("mUniverseTransform=");
1929                    mUniverseTransform.printShortString(pw);
1930                    pw.println();
1931        }
1932        if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) {
1933            pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha);
1934                    pw.print(" mAlpha="); pw.print(mAlpha);
1935                    pw.print(" mLastAlpha="); pw.println(mLastAlpha);
1936        }
1937        if (mHaveMatrix || mWin.mGlobalScale != 1) {
1938            pw.print(prefix); pw.print("mGlobalScale="); pw.print(mWin.mGlobalScale);
1939                    pw.print(" mDsDx="); pw.print(mDsDx);
1940                    pw.print(" mDtDx="); pw.print(mDtDx);
1941                    pw.print(" mDsDy="); pw.print(mDsDy);
1942                    pw.print(" mDtDy="); pw.println(mDtDy);
1943        }
1944    }
1945
1946    @Override
1947    public String toString() {
1948        StringBuffer sb = new StringBuffer("WindowStateAnimator{");
1949        sb.append(Integer.toHexString(System.identityHashCode(this)));
1950        sb.append(' ');
1951        sb.append(mWin.mAttrs.getTitle());
1952        sb.append('}');
1953        return sb.toString();
1954    }
1955}
1956