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