blob: 7839d06421fefffa362b54171cfd5ff550340cee [file] [log] [blame]
Craig Mautner1420b932012-12-28 17:14:38 -08001// Copyright 2012 Google Inc. All Rights Reserved.
2
3package com.android.server.wm;
4
5import android.graphics.PixelFormat;
Craig Mautner05d29032013-05-03 13:40:13 -07006import android.graphics.Rect;
Craig Mautner1420b932012-12-28 17:14:38 -08007import android.os.SystemClock;
8import android.util.Slog;
9import android.view.DisplayInfo;
Mathias Agopian3866f0d2013-02-11 22:08:48 -080010import android.view.SurfaceControl;
Craig Mautner1420b932012-12-28 17:14:38 -080011
12import java.io.PrintWriter;
13
14public class DimLayer {
15 private static final String TAG = "DimLayer";
Craig Mautnerc34bc112013-01-08 15:02:13 -080016 private static final boolean DEBUG = false;
Craig Mautner1420b932012-12-28 17:14:38 -080017
18 /** Reference to the owner of this object. */
19 final DisplayContent mDisplayContent;
20
21 /** Actual surface that dims */
Mathias Agopian3866f0d2013-02-11 22:08:48 -080022 SurfaceControl mDimSurface;
Craig Mautner1420b932012-12-28 17:14:38 -080023
24 /** Last value passed to mDimSurface.setAlpha() */
25 float mAlpha = 0;
26
27 /** Last value passed to mDimSurface.setLayer() */
28 int mLayer = -1;
29
Craig Mautner05d29032013-05-03 13:40:13 -070030 /** Next values to pass to mDimSurface.setPosition() and mDimSurface.setSize() */
31 Rect mBounds = new Rect();
32
33 /** Last values passed to mDimSurface.setPosition() and mDimSurface.setSize() */
34 Rect mLastBounds = new Rect();
Craig Mautner1420b932012-12-28 17:14:38 -080035
36 /** True after mDimSurface.show() has been called, false after mDimSurface.hide(). */
37 private boolean mShowing = false;
38
39 /** Value of mAlpha when beginning transition to mTargetAlpha */
40 float mStartAlpha = 0;
41
42 /** Final value of mAlpha following transition */
43 float mTargetAlpha = 0;
44
45 /** Time in units of SystemClock.uptimeMillis() at which the current transition started */
46 long mStartTime;
47
48 /** Time in milliseconds to take to transition from mStartAlpha to mTargetAlpha */
49 long mDuration;
50
51 DimLayer(WindowManagerService service, int displayId) {
52 if (DEBUG) Slog.v(TAG, "Ctor: displayId=" + displayId);
53 mDisplayContent = service.getDisplayContentLocked(displayId);
Mathias Agopian3866f0d2013-02-11 22:08:48 -080054 SurfaceControl.openTransaction();
Craig Mautner1420b932012-12-28 17:14:38 -080055 try {
56 if (WindowManagerService.DEBUG_SURFACE_TRACE) {
57 mDimSurface = new WindowStateAnimator.SurfaceTrace(service.mFxSession,
58 "DimSurface",
59 16, 16, PixelFormat.OPAQUE,
Mathias Agopian3866f0d2013-02-11 22:08:48 -080060 SurfaceControl.FX_SURFACE_DIM | SurfaceControl.HIDDEN);
Craig Mautner1420b932012-12-28 17:14:38 -080061 } else {
Mathias Agopian3866f0d2013-02-11 22:08:48 -080062 mDimSurface = new SurfaceControl(service.mFxSession, TAG,
Craig Mautner1420b932012-12-28 17:14:38 -080063 16, 16, PixelFormat.OPAQUE,
Mathias Agopian3866f0d2013-02-11 22:08:48 -080064 SurfaceControl.FX_SURFACE_DIM | SurfaceControl.HIDDEN);
Craig Mautner1420b932012-12-28 17:14:38 -080065 }
66 if (WindowManagerService.SHOW_TRANSACTIONS ||
67 WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(TAG,
68 " DIM " + mDimSurface + ": CREATE");
69 mDimSurface.setLayerStack(displayId);
70 } catch (Exception e) {
71 Slog.e(WindowManagerService.TAG, "Exception creating Dim surface", e);
72 } finally {
Mathias Agopian3866f0d2013-02-11 22:08:48 -080073 SurfaceControl.closeTransaction();
Craig Mautner1420b932012-12-28 17:14:38 -080074 }
75 }
76
77 /** Return true if dim layer is showing */
78 boolean isDimming() {
79 return mTargetAlpha != 0;
80 }
81
82 /** Return true if in a transition period */
83 boolean isAnimating() {
84 return mTargetAlpha != mAlpha;
85 }
86
87 float getTargetAlpha() {
88 return mTargetAlpha;
89 }
90
Craig Mautner13131e72013-01-11 11:03:33 -080091 void setLayer(int layer) {
92 if (mLayer != layer) {
93 mLayer = layer;
94 mDimSurface.setLayer(layer);
95 }
96 }
97
98 int getLayer() {
99 return mLayer;
100 }
101
Craig Mautner1420b932012-12-28 17:14:38 -0800102 private void setAlpha(float alpha) {
103 if (mAlpha != alpha) {
104 if (DEBUG) Slog.v(TAG, "setAlpha alpha=" + alpha);
105 try {
106 mDimSurface.setAlpha(alpha);
107 if (alpha == 0 && mShowing) {
108 if (DEBUG) Slog.v(TAG, "setAlpha hiding");
109 mDimSurface.hide();
110 mShowing = false;
111 } else if (alpha > 0 && !mShowing) {
112 if (DEBUG) Slog.v(TAG, "setAlpha showing");
113 mDimSurface.show();
114 mShowing = true;
115 }
116 } catch (RuntimeException e) {
117 Slog.w(TAG, "Failure setting alpha immediately", e);
118 }
119 mAlpha = alpha;
120 }
121 }
122
Craig Mautner05d29032013-05-03 13:40:13 -0700123 void setBounds(Rect bounds) {
124 mBounds.set(bounds);
125 }
126
Craig Mautner1420b932012-12-28 17:14:38 -0800127 /**
128 * @param duration The time to test.
129 * @return True if the duration would lead to an earlier end to the current animation.
130 */
131 private boolean durationEndsEarlier(long duration) {
132 return SystemClock.uptimeMillis() + duration < mStartTime + mDuration;
133 }
134
135 /** Jump to the end of the animation.
136 * NOTE: Must be called with Surface transaction open. */
137 void show() {
138 if (isAnimating()) {
139 if (DEBUG) Slog.v(TAG, "show: immediate");
140 show(mLayer, mTargetAlpha, 0);
141 }
142 }
143
144 /**
145 * Begin an animation to a new dim value.
146 * NOTE: Must be called with Surface transaction open.
147 *
148 * @param layer The layer to set the surface to.
149 * @param alpha The dim value to end at.
150 * @param duration How long to take to get there in milliseconds.
151 */
152 void show(int layer, float alpha, long duration) {
153 if (DEBUG) Slog.v(TAG, "show: layer=" + layer + " alpha=" + alpha
154 + " duration=" + duration);
155 if (mDimSurface == null) {
156 Slog.e(TAG, "show: no Surface");
157 // Make sure isAnimating() returns false.
158 mTargetAlpha = mAlpha = 0;
159 return;
160 }
161
Craig Mautner05d29032013-05-03 13:40:13 -0700162 /*
Craig Mautner1420b932012-12-28 17:14:38 -0800163 // Set surface size to screen size.
164 final DisplayInfo info = mDisplayContent.getDisplayInfo();
165 // Multiply by 1.5 so that rotating a frozen surface that includes this does not expose a
166 // corner.
167 final int dw = (int) (info.logicalWidth * 1.5);
168 final int dh = (int) (info.logicalHeight * 1.5);
169 // back off position so 1/4 of Surface is before and 1/4 is after.
170 final float xPos = -1 * dw / 6;
171 final float yPos = -1 * dh / 6;
Craig Mautner05d29032013-05-03 13:40:13 -0700172 */
Craig Mautner1420b932012-12-28 17:14:38 -0800173
Craig Mautner05d29032013-05-03 13:40:13 -0700174 if (!mLastBounds.equals(mBounds) || mLayer != layer) {
Craig Mautner1420b932012-12-28 17:14:38 -0800175 try {
Craig Mautner05d29032013-05-03 13:40:13 -0700176 mDimSurface.setPosition(mBounds.left, mBounds.top);
177 mDimSurface.setSize(mBounds.width(), mBounds.height());
Craig Mautner1420b932012-12-28 17:14:38 -0800178 mDimSurface.setLayer(layer);
179 } catch (RuntimeException e) {
180 Slog.w(TAG, "Failure setting size or layer", e);
181 }
Craig Mautner05d29032013-05-03 13:40:13 -0700182 mLastBounds.set(mBounds);
Craig Mautner1420b932012-12-28 17:14:38 -0800183 mLayer = layer;
184 }
185
186 long curTime = SystemClock.uptimeMillis();
187 final boolean animating = isAnimating();
188 if ((animating && (mTargetAlpha != alpha || durationEndsEarlier(duration)))
189 || (!animating && mAlpha != alpha)) {
190 if (duration <= 0) {
191 // No animation required, just set values.
192 setAlpha(alpha);
193 } else {
194 // Start or continue animation with new parameters.
195 mStartAlpha = mAlpha;
196 mStartTime = curTime;
197 mDuration = duration;
198 }
199 }
200 if (DEBUG) Slog.v(TAG, "show: mStartAlpha=" + mStartAlpha + " mStartTime=" + mStartTime);
201 mTargetAlpha = alpha;
202 }
203
204 /** Immediate hide.
205 * NOTE: Must be called with Surface transaction open. */
206 void hide() {
207 if (mShowing) {
208 if (DEBUG) Slog.v(TAG, "hide: immediate");
209 hide(0);
210 }
211 }
212
213 /**
214 * Gradually fade to transparent.
215 * NOTE: Must be called with Surface transaction open.
216 *
217 * @param duration Time to fade in milliseconds.
218 */
219 void hide(long duration) {
220 if (mShowing && (mTargetAlpha != 0 || durationEndsEarlier(duration))) {
221 if (DEBUG) Slog.v(TAG, "hide: duration=" + duration);
222 show(mLayer, 0, duration);
223 }
224 }
225
226 /**
227 * Advance the dimming per the last #show(int, float, long) call.
228 * NOTE: Must be called with Surface transaction open.
229 *
230 * @return True if animation is still required after this step.
231 */
232 boolean stepAnimation() {
233 if (mDimSurface == null) {
234 Slog.e(TAG, "stepAnimation: null Surface");
235 // Ensure that isAnimating() returns false;
236 mTargetAlpha = mAlpha = 0;
237 return false;
238 }
239
240 if (isAnimating()) {
241 final long curTime = SystemClock.uptimeMillis();
242 final float alphaDelta = mTargetAlpha - mStartAlpha;
243 float alpha = mStartAlpha + alphaDelta * (curTime - mStartTime) / mDuration;
244 if (alphaDelta > 0 && alpha > mTargetAlpha ||
245 alphaDelta < 0 && alpha < mTargetAlpha) {
246 // Don't exceed limits.
247 alpha = mTargetAlpha;
248 }
249 if (DEBUG) Slog.v(TAG, "stepAnimation: curTime=" + curTime + " alpha=" + alpha);
250 setAlpha(alpha);
251 }
252
253 return isAnimating();
254 }
255
256 /** Cleanup */
257 void destroySurface() {
258 if (DEBUG) Slog.v(TAG, "destroySurface.");
259 if (mDimSurface != null) {
260 mDimSurface.destroy();
261 mDimSurface = null;
262 }
263 }
264
265 public void printTo(String prefix, PrintWriter pw) {
Craig Mautner967212c2013-04-13 21:10:58 -0700266 pw.print(prefix); pw.print("mDimSurface="); pw.print(mDimSurface);
267 pw.print(" mLayer="); pw.print(mLayer);
Craig Mautner1420b932012-12-28 17:14:38 -0800268 pw.print(" mAlpha="); pw.println(mAlpha);
Craig Mautner05d29032013-05-03 13:40:13 -0700269 pw.print(prefix); pw.print("mLastBounds="); pw.print(mLastBounds.toShortString());
270 pw.print(" mBounds="); pw.println(mBounds.toShortString());
Craig Mautner967212c2013-04-13 21:10:58 -0700271 pw.print(prefix); pw.print("Last animation: ");
Craig Mautner1420b932012-12-28 17:14:38 -0800272 pw.print(" mDuration="); pw.print(mDuration);
Craig Mautner967212c2013-04-13 21:10:58 -0700273 pw.print(" mStartTime="); pw.print(mStartTime);
Craig Mautner1420b932012-12-28 17:14:38 -0800274 pw.print(" curTime="); pw.println(SystemClock.uptimeMillis());
Craig Mautner967212c2013-04-13 21:10:58 -0700275 pw.print(prefix); pw.print(" mStartAlpha="); pw.print(mStartAlpha);
276 pw.print(" mTargetAlpha="); pw.println(mTargetAlpha);
Craig Mautner1420b932012-12-28 17:14:38 -0800277 }
278}