AppWindowAnimator.java revision bec53f7066852c1c5877c51fcd8c55840891d866
1// Copyright 2012 Google Inc. All Rights Reserved.
2
3package com.android.server.wm;
4
5import android.graphics.Matrix;
6import android.util.Slog;
7import android.view.Surface;
8import android.view.WindowManagerPolicy;
9import android.view.animation.Animation;
10import android.view.animation.Transformation;
11
12import java.io.PrintWriter;
13
14/**
15 *
16 */
17public class AppWindowAnimator {
18
19    final AppWindowToken mAppToken;
20    final WindowManagerService mService;
21    final WindowAnimator mAnimator;
22
23    boolean animating;
24    Animation animation;
25    boolean animInitialized;
26    boolean hasTransformation;
27    final Transformation transformation = new Transformation();
28
29    // Have we been asked to have this token keep the screen frozen?
30    // Protect with mAnimator.
31    boolean freezingScreen;
32
33    // Offset to the window of all layers in the token, for use by
34    // AppWindowToken animations.
35    int animLayerAdjustment;
36
37    // Special surface for thumbnail animation.
38    Surface thumbnail;
39    int thumbnailTransactionSeq;
40    int thumbnailX;
41    int thumbnailY;
42    int thumbnailLayer;
43    Animation thumbnailAnimation;
44    final Transformation thumbnailTransformation = new Transformation();
45
46    public AppWindowAnimator(final WindowManagerService service, final AppWindowToken atoken) {
47        mService = service;
48        mAppToken = atoken;
49        mAnimator = service.mAnimator;
50    }
51
52    public void setAnimation(Animation anim, boolean initialized) {
53        if (WindowManagerService.localLOGV) Slog.v(
54            WindowManagerService.TAG, "Setting animation in " + this + ": " + anim);
55        animation = anim;
56        animating = false;
57        animInitialized = initialized;
58        anim.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION);
59        anim.scaleCurrentDuration(mService.mTransitionAnimationScale);
60        int zorder = anim.getZAdjustment();
61        int adj = 0;
62        if (zorder == Animation.ZORDER_TOP) {
63            adj = WindowManagerService.TYPE_LAYER_OFFSET;
64        } else if (zorder == Animation.ZORDER_BOTTOM) {
65            adj = -WindowManagerService.TYPE_LAYER_OFFSET;
66        }
67
68        if (animLayerAdjustment != adj) {
69            animLayerAdjustment = adj;
70            updateLayers();
71        }
72        // Start out animation gone if window is gone, or visible if window is visible.
73        transformation.clear();
74        transformation.setAlpha(mAppToken.reportedVisible ? 1 : 0);
75        hasTransformation = true;
76    }
77
78    public void setDummyAnimation() {
79        if (animation == null) {
80            if (WindowManagerService.localLOGV) Slog.v(
81                WindowManagerService.TAG, "Setting dummy animation in " + this);
82            animation = WindowManagerService.sDummyAnimation;
83            animInitialized = false;
84        }
85    }
86
87    public void clearAnimation() {
88        if (animation != null) {
89            animation = null;
90            animating = true;
91            animInitialized = false;
92        }
93        clearThumbnail();
94    }
95
96    public void clearThumbnail() {
97        if (thumbnail != null) {
98            thumbnail.destroy();
99            thumbnail = null;
100        }
101    }
102
103    void updateLayers() {
104        final int N = mAppToken.allAppWindows.size();
105        final int adj = animLayerAdjustment;
106        thumbnailLayer = -1;
107        for (int i=0; i<N; i++) {
108            final WindowState w = mAppToken.allAppWindows.get(i);
109            final WindowStateAnimator winAnimator = w.mWinAnimator;
110            winAnimator.mAnimLayer = w.mLayer + adj;
111            if (winAnimator.mAnimLayer > thumbnailLayer) {
112                thumbnailLayer = winAnimator.mAnimLayer;
113            }
114            if (WindowManagerService.DEBUG_LAYERS) Slog.v(WindowManagerService.TAG, "Updating layer " + w + ": "
115                    + winAnimator.mAnimLayer);
116            if (w == mService.mInputMethodTarget && !mService.mInputMethodTargetWaitingAnim) {
117                mService.setInputMethodAnimLayerAdjustment(adj);
118            }
119            if (w == mService.mWallpaperTarget && mService.mLowerWallpaperTarget == null) {
120                mService.setWallpaperAnimLayerAdjustmentLocked(adj);
121            }
122        }
123    }
124
125    private void stepThumbnailAnimation(long currentTime) {
126        thumbnailTransformation.clear();
127        thumbnailAnimation.getTransformation(currentTime, thumbnailTransformation);
128        thumbnailTransformation.getMatrix().preTranslate(thumbnailX, thumbnailY);
129        final boolean screenAnimation = mAnimator.mScreenRotationAnimation != null
130                && mAnimator.mScreenRotationAnimation.isAnimating();
131        if (screenAnimation) {
132            thumbnailTransformation.postCompose(
133                    mAnimator.mScreenRotationAnimation.getEnterTransformation());
134        }
135        // cache often used attributes locally
136        final float tmpFloats[] = mService.mTmpFloats;
137        thumbnailTransformation.getMatrix().getValues(tmpFloats);
138        if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(thumbnail,
139                "thumbnail", "POS " + tmpFloats[Matrix.MTRANS_X]
140                + ", " + tmpFloats[Matrix.MTRANS_Y], null);
141        thumbnail.setPosition(tmpFloats[Matrix.MTRANS_X], tmpFloats[Matrix.MTRANS_Y]);
142        if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(thumbnail,
143                "thumbnail", "alpha=" + thumbnailTransformation.getAlpha()
144                + " layer=" + thumbnailLayer
145                + " matrix=[" + tmpFloats[Matrix.MSCALE_X]
146                + "," + tmpFloats[Matrix.MSKEW_Y]
147                + "][" + tmpFloats[Matrix.MSKEW_X]
148                + "," + tmpFloats[Matrix.MSCALE_Y] + "]", null);
149        thumbnail.setAlpha(thumbnailTransformation.getAlpha());
150        // The thumbnail is layered below the window immediately above this
151        // token's anim layer.
152        thumbnail.setLayer(thumbnailLayer + WindowManagerService.WINDOW_LAYER_MULTIPLIER
153                - WindowManagerService.LAYER_OFFSET_THUMBNAIL);
154        thumbnail.setMatrix(tmpFloats[Matrix.MSCALE_X], tmpFloats[Matrix.MSKEW_Y],
155                tmpFloats[Matrix.MSKEW_X], tmpFloats[Matrix.MSCALE_Y]);
156    }
157
158    private boolean stepAnimation(long currentTime) {
159        if (animation == null) {
160            return false;
161        }
162        transformation.clear();
163        final boolean more = animation.getTransformation(currentTime, transformation);
164        if (WindowManagerService.DEBUG_ANIM) Slog.v(
165            WindowManagerService.TAG, "Stepped animation in " + this +
166            ": more=" + more + ", xform=" + transformation);
167        if (!more) {
168            animation = null;
169            clearThumbnail();
170            if (WindowManagerService.DEBUG_ANIM) Slog.v(
171                WindowManagerService.TAG, "Finished animation in " + this +
172                " @ " + currentTime);
173        }
174        hasTransformation = more;
175        return more;
176    }
177
178    // This must be called while inside a transaction.
179    boolean stepAnimationLocked(long currentTime, int dw, int dh) {
180        if (mService.okToDisplay()) {
181            // We will run animations as long as the display isn't frozen.
182
183            if (animation == WindowManagerService.sDummyAnimation) {
184                // This guy is going to animate, but not yet.  For now count
185                // it as not animating for purposes of scheduling transactions;
186                // when it is really time to animate, this will be set to
187                // a real animation and the next call will execute normally.
188                return false;
189            }
190
191            if ((mAppToken.allDrawn || animating || mAppToken.startingDisplayed)
192                    && animation != null) {
193                if (!animating) {
194                    if (WindowManagerService.DEBUG_ANIM) Slog.v(
195                        WindowManagerService.TAG, "Starting animation in " + this +
196                        " @ " + currentTime + ": dw=" + dw + " dh=" + dh
197                        + " scale=" + mService.mTransitionAnimationScale
198                        + " allDrawn=" + mAppToken.allDrawn + " animating=" + animating);
199                    if (!animInitialized) {
200                        animation.initialize(dw, dh, dw, dh);
201                    }
202                    animation.setStartTime(currentTime);
203                    animating = true;
204                    if (thumbnail != null) {
205                        thumbnail.show();
206                        thumbnailAnimation.setStartTime(currentTime);
207                    }
208                }
209                if (stepAnimation(currentTime)) {
210                    // animation isn't over, step any thumbnail and that's
211                    // it for now.
212                    if (thumbnail != null) {
213                        stepThumbnailAnimation(currentTime);
214                    }
215                    return true;
216                }
217            }
218        } else if (animation != null) {
219            // If the display is frozen, and there is a pending animation,
220            // clear it and make sure we run the cleanup code.
221            animating = true;
222            animation = null;
223        }
224
225        hasTransformation = false;
226
227        if (!animating) {
228            return false;
229        }
230
231        mAnimator.mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
232        if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
233            mService.debugLayoutRepeats("AppWindowToken", mAnimator.mPendingLayoutChanges);
234        }
235
236        clearAnimation();
237        animating = false;
238        if (animLayerAdjustment != 0) {
239            animLayerAdjustment = 0;
240            updateLayers();
241        }
242        if (mService.mInputMethodTarget != null
243                && mService.mInputMethodTarget.mAppToken == mAppToken) {
244            mService.moveInputMethodWindowsIfNeededLocked(true);
245        }
246
247        if (WindowManagerService.DEBUG_ANIM) Slog.v(
248                WindowManagerService.TAG, "Animation done in " + this
249                + ": reportedVisible=" + mAppToken.reportedVisible);
250
251        transformation.clear();
252
253        final int N = mAppToken.windows.size();
254        for (int i=0; i<N; i++) {
255            mAppToken.windows.get(i).mWinAnimator.finishExit();
256        }
257        mAppToken.updateReportedVisibilityLocked();
258
259        return false;
260    }
261
262    boolean showAllWindowsLocked() {
263        boolean isAnimating = false;
264        final int NW = mAppToken.allAppWindows.size();
265        for (int i=0; i<NW; i++) {
266            WindowStateAnimator winAnimator = mAppToken.allAppWindows.get(i).mWinAnimator;
267            if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG,
268                    "performing show on: " + winAnimator);
269            winAnimator.performShowLocked();
270            isAnimating |= winAnimator.isAnimating();
271        }
272        return isAnimating;
273    }
274
275    void dump(PrintWriter pw, String prefix) {
276        if (freezingScreen) {
277            pw.print(prefix); pw.print(" freezingScreen="); pw.println(freezingScreen);
278        }
279        if (animating || animation != null) {
280            pw.print(prefix); pw.print("animating="); pw.print(animating);
281                    pw.print(" animation="); pw.println(animation);
282        }
283        if (hasTransformation) {
284            pw.print(prefix); pw.print("XForm: ");
285                    transformation.printShortString(pw);
286                    pw.println();
287        }
288        if (animLayerAdjustment != 0) {
289            pw.print(prefix); pw.print("animLayerAdjustment="); pw.println(animLayerAdjustment);
290        }
291        if (thumbnail != null) {
292            pw.print(prefix); pw.print("thumbnail="); pw.print(thumbnail);
293                    pw.print(" x="); pw.print(thumbnailX);
294                    pw.print(" y="); pw.print(thumbnailY);
295                    pw.print(" layer="); pw.println(thumbnailLayer);
296            pw.print(prefix); pw.print("thumbnailAnimation="); pw.println(thumbnailAnimation);
297            pw.print(prefix); pw.print("thumbnailTransformation=");
298                    pw.println(thumbnailTransformation.toShortString());
299        }
300    }
301}
302