DimAnimator.java revision d5523dc7b7318f2774109dd30716ff7b74560e61
1/*
2 * Copyright (C) 2011 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 android.content.res.Resources;
20import android.graphics.PixelFormat;
21import android.util.Slog;
22import android.util.TypedValue;
23import android.view.Surface;
24import android.view.SurfaceSession;
25
26import java.io.PrintWriter;
27
28/**
29 * DimAnimator class that controls the dim animation. This holds the surface and
30 * all state used for dim animation.
31 */
32class DimAnimator {
33    static final String TAG = "DimAnimator";
34
35    Surface mDimSurface;
36    boolean mDimShown = false;
37    float mDimCurrentAlpha;
38    float mDimTargetAlpha;
39    float mDimDeltaPerMs;
40    long mLastDimAnimTime;
41
42    int mLastDimWidth, mLastDimHeight;
43
44    DimAnimator (SurfaceSession session, final int layerStack) {
45        try {
46            if (WindowManagerService.DEBUG_SURFACE_TRACE) {
47                mDimSurface = new WindowStateAnimator.SurfaceTrace(session,
48                    "DimAnimator",
49                    16, 16, PixelFormat.OPAQUE,
50                    Surface.FX_SURFACE_DIM | Surface.HIDDEN);
51            } else {
52                mDimSurface = new Surface(session, "DimAnimator",
53                    16, 16, PixelFormat.OPAQUE,
54                    Surface.FX_SURFACE_DIM | Surface.HIDDEN);
55            }
56            if (WindowManagerService.SHOW_TRANSACTIONS ||
57                    WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
58                            "  DIM " + mDimSurface + ": CREATE");
59            mDimSurface.setLayerStack(layerStack);
60            mDimSurface.setAlpha(0.0f);
61            mDimSurface.show();
62        } catch (Exception e) {
63            Slog.e(WindowManagerService.TAG, "Exception creating Dim surface", e);
64        }
65    }
66
67    /**
68     * Set's the dim surface's layer and update dim parameters that will be used in
69     * {@link #updateSurface} after all windows are examined.
70     */
71    void updateParameters(final Resources res, final Parameters params, final long currentTime) {
72        if (mDimSurface == null) {
73            Slog.e(TAG, "updateParameters: no Surface");
74            return;
75        }
76
77        // Multiply by 1.5 so that rotating a frozen surface that includes this does not expose a
78        // corner.
79        final int dw = (int) (params.mDimWidth * 1.5);
80        final int dh = (int) (params.mDimHeight * 1.5);
81        final WindowStateAnimator winAnimator = params.mDimWinAnimator;
82        final float target = params.mDimTarget;
83        if (!mDimShown) {
84            if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG,
85                "  DIM " + mDimSurface + ": SHOW pos=(0,0) (" + dw + "x" + dh + ")");
86            mDimShown = true;
87            try {
88                mLastDimWidth = dw;
89                mLastDimHeight = dh;
90                // back off position so mDimXXX/4 is before and mDimXXX/4 is after
91                mDimSurface.setPosition(-1 * dw / 6, -1 * dh /6);
92                mDimSurface.setSize(dw, dh);
93                mDimSurface.show();
94            } catch (RuntimeException e) {
95                Slog.w(WindowManagerService.TAG, "Failure showing dim surface", e);
96            }
97        } else if (mLastDimWidth != dw || mLastDimHeight != dh) {
98            mLastDimWidth = dw;
99            mLastDimHeight = dh;
100            mDimSurface.setSize(dw, dh);
101            // back off position so mDimXXX/4 is before and mDimXXX/4 is after
102            mDimSurface.setPosition(-1 * dw / 6, -1 * dh /6);
103        }
104
105        mDimSurface.setLayer(winAnimator.mAnimLayer - WindowManagerService.LAYER_OFFSET_DIM);
106
107        if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "  DIM "
108                + mDimSurface + ": layer=" + (winAnimator.mAnimLayer-1) + " target=" + target);
109        if (mDimTargetAlpha != target) {
110            // If the desired dim level has changed, then
111            // start an animation to it.
112            mLastDimAnimTime = currentTime;
113            long duration = (winAnimator.mAnimating && winAnimator.mAnimation != null)
114                    ? winAnimator.mAnimation.computeDurationHint()
115                    : WindowManagerService.DEFAULT_DIM_DURATION;
116            if (target > mDimTargetAlpha) {
117                TypedValue tv = new TypedValue();
118                res.getValue(com.android.internal.R.fraction.config_dimBehindFadeDuration,
119                        tv, true);
120                if (tv.type == TypedValue.TYPE_FRACTION) {
121                    duration = (long)tv.getFraction(duration, duration);
122                } else if (tv.type >= TypedValue.TYPE_FIRST_INT
123                        && tv.type <= TypedValue.TYPE_LAST_INT) {
124                    duration = tv.data;
125                }
126            }
127            if (duration < 1) {
128                // Don't divide by zero
129                duration = 1;
130            }
131            mDimTargetAlpha = target;
132            mDimDeltaPerMs = (mDimTargetAlpha-mDimCurrentAlpha) / duration;
133        }
134    }
135
136    /**
137     * Updating the surface's alpha. Returns true if the animation continues, or returns
138     * false when the animation is finished and the dim surface is hidden.
139     */
140    boolean updateSurface(boolean dimming, long currentTime, boolean displayFrozen) {
141        if (mDimSurface == null) {
142            Slog.e(TAG, "updateSurface: no Surface");
143            return false;
144        }
145
146        if (!dimming) {
147            if (mDimTargetAlpha != 0) {
148                mLastDimAnimTime = currentTime;
149                mDimTargetAlpha = 0;
150                mDimDeltaPerMs = (-mDimCurrentAlpha) / WindowManagerService.DEFAULT_DIM_DURATION;
151            }
152        }
153
154        boolean animating = mLastDimAnimTime != 0;
155        if (animating) {
156            mDimCurrentAlpha += mDimDeltaPerMs
157                    * (currentTime-mLastDimAnimTime);
158            if (displayFrozen) {
159                // If the display is frozen, there is no reason to animate.
160                animating = false;
161            } else if (mDimDeltaPerMs > 0) {
162                if (mDimCurrentAlpha > mDimTargetAlpha) {
163                    animating = false;
164                }
165            } else if (mDimDeltaPerMs < 0) {
166                if (mDimCurrentAlpha < mDimTargetAlpha) {
167                    animating = false;
168                }
169            } else {
170                animating = false;
171            }
172
173            // Do we need to continue animating?
174            if (animating) {
175                if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "  DIM "
176                        + mDimSurface + ": alpha=" + mDimCurrentAlpha);
177                mLastDimAnimTime = currentTime;
178                mDimSurface.setAlpha(mDimCurrentAlpha);
179            } else {
180                mDimCurrentAlpha = mDimTargetAlpha;
181                mLastDimAnimTime = 0;
182                if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "  DIM "
183                        + mDimSurface + ": final alpha=" + mDimCurrentAlpha);
184                mDimSurface.setAlpha(mDimCurrentAlpha);
185                if (!dimming) {
186                    if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "  DIM " + mDimSurface
187                            + ": HIDE");
188                    try {
189                        mDimSurface.hide();
190                    } catch (RuntimeException e) {
191                        Slog.w(WindowManagerService.TAG, "Illegal argument exception hiding dim surface");
192                    }
193                    mDimShown = false;
194                }
195            }
196        }
197        return animating;
198    }
199
200    public void kill() {
201        if (mDimSurface != null) {
202            mDimSurface.destroy();
203            mDimSurface = null;
204        }
205    }
206
207    public void printTo(String prefix, PrintWriter pw) {
208        pw.print(prefix);
209        pw.print("mDimSurface="); pw.print(mDimSurface);
210                pw.print(" "); pw.print(mLastDimWidth); pw.print(" x ");
211                pw.println(mLastDimHeight);
212        pw.print(prefix);
213        pw.print("mDimShown="); pw.print(mDimShown);
214        pw.print(" current="); pw.print(mDimCurrentAlpha);
215        pw.print(" target="); pw.print(mDimTargetAlpha);
216        pw.print(" delta="); pw.print(mDimDeltaPerMs);
217        pw.print(" lastAnimTime="); pw.println(mLastDimAnimTime);
218    }
219
220    static class Parameters {
221        final WindowStateAnimator mDimWinAnimator;
222        final int mDimWidth;
223        final int mDimHeight;
224        final float mDimTarget;
225        Parameters(final WindowStateAnimator dimWinAnimator, final int dimWidth,
226                final int dimHeight, final float dimTarget) {
227            mDimWinAnimator = dimWinAnimator;
228            mDimWidth = dimWidth;
229            mDimHeight = dimHeight;
230            mDimTarget = dimTarget;
231        }
232
233        Parameters(Parameters o) {
234            mDimWinAnimator = o.mDimWinAnimator;
235            mDimWidth = o.mDimWidth;
236            mDimHeight = o.mDimHeight;
237            mDimTarget = o.mDimTarget;
238        }
239
240        public void printTo(String prefix, PrintWriter pw) {
241            pw.print(prefix);
242            pw.print("mDimWinAnimator="); pw.print(mDimWinAnimator.mWin.mAttrs.getTitle());
243                    pw.print(" "); pw.print(mDimWidth); pw.print(" x ");
244                    pw.print(mDimHeight);
245            pw.print(" mDimTarget="); pw.println(mDimTarget);
246        }
247    }
248}
249