blob: 6657a7b03489c35d3ee2b209cb710f6a55a31017 [file] [log] [blame]
Craig Mautnerc2c0a612014-02-20 20:25:41 -08001/*
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 */
Craig Mautner1420b932012-12-28 17:14:38 -080016
17package com.android.server.wm;
18
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080019import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE;
20import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC;
21import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
22import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
23import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
24
Craig Mautner1420b932012-12-28 17:14:38 -080025import android.graphics.PixelFormat;
Craig Mautner05d29032013-05-03 13:40:13 -070026import android.graphics.Rect;
Craig Mautner1420b932012-12-28 17:14:38 -080027import android.os.SystemClock;
28import android.util.Slog;
29import android.view.DisplayInfo;
Mathias Agopian3866f0d2013-02-11 22:08:48 -080030import android.view.SurfaceControl;
Craig Mautner1420b932012-12-28 17:14:38 -080031
32import java.io.PrintWriter;
33
34public class DimLayer {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080035 private static final String TAG = TAG_WITH_CLASS_NAME ? "DimLayer" : TAG_WM;
Craig Mautnerc34bc112013-01-08 15:02:13 -080036 private static final boolean DEBUG = false;
Craig Mautner1420b932012-12-28 17:14:38 -080037
Filip Gruszczynski57b6cce2015-10-06 09:50:51 -070038 public static final float RESIZING_HINT_ALPHA = 0.5f;
39
40 public static final int RESIZING_HINT_DURATION_MS = 0;
41
Craig Mautner1420b932012-12-28 17:14:38 -080042 /** Actual surface that dims */
Mathias Agopian3866f0d2013-02-11 22:08:48 -080043 SurfaceControl mDimSurface;
Craig Mautner1420b932012-12-28 17:14:38 -080044
45 /** Last value passed to mDimSurface.setAlpha() */
46 float mAlpha = 0;
47
48 /** Last value passed to mDimSurface.setLayer() */
49 int mLayer = -1;
50
Craig Mautner05d29032013-05-03 13:40:13 -070051 /** Next values to pass to mDimSurface.setPosition() and mDimSurface.setSize() */
52 Rect mBounds = new Rect();
53
54 /** Last values passed to mDimSurface.setPosition() and mDimSurface.setSize() */
55 Rect mLastBounds = new Rect();
Craig Mautner1420b932012-12-28 17:14:38 -080056
57 /** True after mDimSurface.show() has been called, false after mDimSurface.hide(). */
58 private boolean mShowing = false;
59
60 /** Value of mAlpha when beginning transition to mTargetAlpha */
61 float mStartAlpha = 0;
62
63 /** Final value of mAlpha following transition */
64 float mTargetAlpha = 0;
65
66 /** Time in units of SystemClock.uptimeMillis() at which the current transition started */
67 long mStartTime;
68
69 /** Time in milliseconds to take to transition from mStartAlpha to mTargetAlpha */
70 long mDuration;
71
Wale Ogunwalee4a0c572015-06-30 08:40:31 -070072 /** Interface implemented by users of the dim layer */
73 interface DimLayerUser {
74 /** Returns true if the user of the dim layer is fullscreen. */
75 boolean isFullscreen();
76 /** Returns the display info. of the dim layer user. */
77 DisplayInfo getDisplayInfo();
Filip Gruszczynski0689ae92015-10-01 12:30:31 -070078 /** Gets the bounds of the dim layer user. */
Chong Zhang4c9ba52a2015-11-10 18:36:33 -080079 void getDimBounds(Rect outBounds);
Filip Gruszczynski0689ae92015-10-01 12:30:31 -070080 String toShortString();
Wale Ogunwalee4a0c572015-06-30 08:40:31 -070081 }
82 /** The user of this dim layer. */
83 final DimLayerUser mUser;
Craig Mautnerc7b8a102013-10-02 16:49:52 -070084
Wale Ogunwalee4a0c572015-06-30 08:40:31 -070085 DimLayer(WindowManagerService service, DimLayerUser user, int displayId) {
86 mUser = user;
Craig Mautner1420b932012-12-28 17:14:38 -080087 if (DEBUG) Slog.v(TAG, "Ctor: displayId=" + displayId);
Mathias Agopian3866f0d2013-02-11 22:08:48 -080088 SurfaceControl.openTransaction();
Craig Mautner1420b932012-12-28 17:14:38 -080089 try {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080090 if (DEBUG_SURFACE_TRACE) {
Robert Carre6a83512015-11-03 16:09:21 -080091 mDimSurface = new WindowSurfaceController.SurfaceTrace(service.mFxSession,
Craig Mautner1420b932012-12-28 17:14:38 -080092 "DimSurface",
93 16, 16, PixelFormat.OPAQUE,
Mathias Agopian3866f0d2013-02-11 22:08:48 -080094 SurfaceControl.FX_SURFACE_DIM | SurfaceControl.HIDDEN);
Craig Mautner1420b932012-12-28 17:14:38 -080095 } else {
Mathias Agopian3866f0d2013-02-11 22:08:48 -080096 mDimSurface = new SurfaceControl(service.mFxSession, TAG,
Craig Mautner1420b932012-12-28 17:14:38 -080097 16, 16, PixelFormat.OPAQUE,
Mathias Agopian3866f0d2013-02-11 22:08:48 -080098 SurfaceControl.FX_SURFACE_DIM | SurfaceControl.HIDDEN);
Craig Mautner1420b932012-12-28 17:14:38 -080099 }
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800100 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) Slog.i(TAG,
101 " DIM " + mDimSurface + ": CREATE");
Craig Mautner1420b932012-12-28 17:14:38 -0800102 mDimSurface.setLayerStack(displayId);
103 } catch (Exception e) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800104 Slog.e(TAG_WM, "Exception creating Dim surface", e);
Craig Mautner1420b932012-12-28 17:14:38 -0800105 } finally {
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800106 SurfaceControl.closeTransaction();
Craig Mautner1420b932012-12-28 17:14:38 -0800107 }
108 }
109
110 /** Return true if dim layer is showing */
111 boolean isDimming() {
112 return mTargetAlpha != 0;
113 }
114
115 /** Return true if in a transition period */
116 boolean isAnimating() {
117 return mTargetAlpha != mAlpha;
118 }
119
120 float getTargetAlpha() {
121 return mTargetAlpha;
122 }
123
Craig Mautner13131e72013-01-11 11:03:33 -0800124 void setLayer(int layer) {
125 if (mLayer != layer) {
126 mLayer = layer;
127 mDimSurface.setLayer(layer);
128 }
129 }
130
131 int getLayer() {
132 return mLayer;
133 }
134
Craig Mautner1420b932012-12-28 17:14:38 -0800135 private void setAlpha(float alpha) {
136 if (mAlpha != alpha) {
137 if (DEBUG) Slog.v(TAG, "setAlpha alpha=" + alpha);
138 try {
139 mDimSurface.setAlpha(alpha);
140 if (alpha == 0 && mShowing) {
141 if (DEBUG) Slog.v(TAG, "setAlpha hiding");
142 mDimSurface.hide();
143 mShowing = false;
144 } else if (alpha > 0 && !mShowing) {
145 if (DEBUG) Slog.v(TAG, "setAlpha showing");
146 mDimSurface.show();
147 mShowing = true;
148 }
149 } catch (RuntimeException e) {
150 Slog.w(TAG, "Failure setting alpha immediately", e);
151 }
152 mAlpha = alpha;
153 }
154 }
155
Craig Mautner902945d2014-02-20 14:31:32 -0800156 /**
Dohyun Lee6ce3a372015-03-23 09:16:34 +0900157 * NOTE: Must be called with Surface transaction open.
Craig Mautner902945d2014-02-20 14:31:32 -0800158 */
Dohyun Lee6ce3a372015-03-23 09:16:34 +0900159 private void adjustBounds() {
Craig Mautner902945d2014-02-20 14:31:32 -0800160 final int dw, dh;
161 final float xPos, yPos;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700162 if (!mUser.isFullscreen()) {
Craig Mautner902945d2014-02-20 14:31:32 -0800163 dw = mBounds.width();
164 dh = mBounds.height();
165 xPos = mBounds.left;
166 yPos = mBounds.top;
167 } else {
168 // Set surface size to screen size.
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700169 final DisplayInfo info = mUser.getDisplayInfo();
Craig Mautner902945d2014-02-20 14:31:32 -0800170 // Multiply by 1.5 so that rotating a frozen surface that includes this does not expose
171 // a corner.
172 dw = (int) (info.logicalWidth * 1.5);
173 dh = (int) (info.logicalHeight * 1.5);
174 // back off position so 1/4 of Surface is before and 1/4 is after.
175 xPos = -1 * dw / 6;
176 yPos = -1 * dh / 6;
177 }
178
Dohyun Lee6ce3a372015-03-23 09:16:34 +0900179 mDimSurface.setPosition(xPos, yPos);
180 mDimSurface.setSize(dw, dh);
181
Craig Mautner902945d2014-02-20 14:31:32 -0800182 mLastBounds.set(mBounds);
Craig Mautner902945d2014-02-20 14:31:32 -0800183 }
184
Wale Ogunwale0ade61b2015-03-24 10:40:32 -0700185 /** @param bounds The new bounds to set */
186 void setBounds(Rect bounds) {
Craig Mautner05d29032013-05-03 13:40:13 -0700187 mBounds.set(bounds);
Craig Mautnerb660b9d2014-02-13 10:59:16 -0800188 if (isDimming() && !mLastBounds.equals(bounds)) {
Dohyun Lee6ce3a372015-03-23 09:16:34 +0900189 try {
Wale Ogunwale0ade61b2015-03-24 10:40:32 -0700190 SurfaceControl.openTransaction();
Dohyun Lee6ce3a372015-03-23 09:16:34 +0900191 adjustBounds();
192 } catch (RuntimeException e) {
193 Slog.w(TAG, "Failure setting size", e);
194 } finally {
Wale Ogunwale0ade61b2015-03-24 10:40:32 -0700195 SurfaceControl.closeTransaction();
Dohyun Lee6ce3a372015-03-23 09:16:34 +0900196 }
Craig Mautnerb660b9d2014-02-13 10:59:16 -0800197 }
Craig Mautner05d29032013-05-03 13:40:13 -0700198 }
199
Craig Mautner1420b932012-12-28 17:14:38 -0800200 /**
201 * @param duration The time to test.
202 * @return True if the duration would lead to an earlier end to the current animation.
203 */
204 private boolean durationEndsEarlier(long duration) {
205 return SystemClock.uptimeMillis() + duration < mStartTime + mDuration;
206 }
207
208 /** Jump to the end of the animation.
209 * NOTE: Must be called with Surface transaction open. */
210 void show() {
211 if (isAnimating()) {
212 if (DEBUG) Slog.v(TAG, "show: immediate");
213 show(mLayer, mTargetAlpha, 0);
214 }
215 }
216
217 /**
218 * Begin an animation to a new dim value.
219 * NOTE: Must be called with Surface transaction open.
220 *
221 * @param layer The layer to set the surface to.
222 * @param alpha The dim value to end at.
223 * @param duration How long to take to get there in milliseconds.
224 */
225 void show(int layer, float alpha, long duration) {
226 if (DEBUG) Slog.v(TAG, "show: layer=" + layer + " alpha=" + alpha
227 + " duration=" + duration);
228 if (mDimSurface == null) {
229 Slog.e(TAG, "show: no Surface");
230 // Make sure isAnimating() returns false.
231 mTargetAlpha = mAlpha = 0;
232 return;
233 }
234
Dohyun Lee6ce3a372015-03-23 09:16:34 +0900235 if (!mLastBounds.equals(mBounds)) {
236 adjustBounds();
Craig Mautner1420b932012-12-28 17:14:38 -0800237 }
Dohyun Lee6ce3a372015-03-23 09:16:34 +0900238 setLayer(layer);
Craig Mautner1420b932012-12-28 17:14:38 -0800239
240 long curTime = SystemClock.uptimeMillis();
241 final boolean animating = isAnimating();
242 if ((animating && (mTargetAlpha != alpha || durationEndsEarlier(duration)))
243 || (!animating && mAlpha != alpha)) {
244 if (duration <= 0) {
245 // No animation required, just set values.
246 setAlpha(alpha);
247 } else {
248 // Start or continue animation with new parameters.
249 mStartAlpha = mAlpha;
250 mStartTime = curTime;
251 mDuration = duration;
252 }
253 }
Craig Mautner1420b932012-12-28 17:14:38 -0800254 mTargetAlpha = alpha;
Filip Gruszczynski0689ae92015-10-01 12:30:31 -0700255 if (DEBUG) Slog.v(TAG, "show: mStartAlpha=" + mStartAlpha + " mStartTime=" + mStartTime
256 + " mTargetAlpha=" + mTargetAlpha);
Craig Mautner1420b932012-12-28 17:14:38 -0800257 }
258
259 /** Immediate hide.
260 * NOTE: Must be called with Surface transaction open. */
261 void hide() {
262 if (mShowing) {
263 if (DEBUG) Slog.v(TAG, "hide: immediate");
264 hide(0);
265 }
266 }
267
268 /**
269 * Gradually fade to transparent.
270 * NOTE: Must be called with Surface transaction open.
271 *
272 * @param duration Time to fade in milliseconds.
273 */
274 void hide(long duration) {
275 if (mShowing && (mTargetAlpha != 0 || durationEndsEarlier(duration))) {
276 if (DEBUG) Slog.v(TAG, "hide: duration=" + duration);
277 show(mLayer, 0, duration);
278 }
279 }
280
281 /**
282 * Advance the dimming per the last #show(int, float, long) call.
283 * NOTE: Must be called with Surface transaction open.
284 *
285 * @return True if animation is still required after this step.
286 */
287 boolean stepAnimation() {
288 if (mDimSurface == null) {
289 Slog.e(TAG, "stepAnimation: null Surface");
290 // Ensure that isAnimating() returns false;
291 mTargetAlpha = mAlpha = 0;
292 return false;
293 }
294
295 if (isAnimating()) {
296 final long curTime = SystemClock.uptimeMillis();
297 final float alphaDelta = mTargetAlpha - mStartAlpha;
298 float alpha = mStartAlpha + alphaDelta * (curTime - mStartTime) / mDuration;
299 if (alphaDelta > 0 && alpha > mTargetAlpha ||
300 alphaDelta < 0 && alpha < mTargetAlpha) {
301 // Don't exceed limits.
302 alpha = mTargetAlpha;
303 }
304 if (DEBUG) Slog.v(TAG, "stepAnimation: curTime=" + curTime + " alpha=" + alpha);
305 setAlpha(alpha);
306 }
307
308 return isAnimating();
309 }
310
311 /** Cleanup */
312 void destroySurface() {
313 if (DEBUG) Slog.v(TAG, "destroySurface.");
314 if (mDimSurface != null) {
315 mDimSurface.destroy();
316 mDimSurface = null;
317 }
318 }
319
320 public void printTo(String prefix, PrintWriter pw) {
Craig Mautner967212c2013-04-13 21:10:58 -0700321 pw.print(prefix); pw.print("mDimSurface="); pw.print(mDimSurface);
322 pw.print(" mLayer="); pw.print(mLayer);
Craig Mautner1420b932012-12-28 17:14:38 -0800323 pw.print(" mAlpha="); pw.println(mAlpha);
Craig Mautner05d29032013-05-03 13:40:13 -0700324 pw.print(prefix); pw.print("mLastBounds="); pw.print(mLastBounds.toShortString());
325 pw.print(" mBounds="); pw.println(mBounds.toShortString());
Craig Mautner967212c2013-04-13 21:10:58 -0700326 pw.print(prefix); pw.print("Last animation: ");
Craig Mautner1420b932012-12-28 17:14:38 -0800327 pw.print(" mDuration="); pw.print(mDuration);
Craig Mautner967212c2013-04-13 21:10:58 -0700328 pw.print(" mStartTime="); pw.print(mStartTime);
Craig Mautner1420b932012-12-28 17:14:38 -0800329 pw.print(" curTime="); pw.println(SystemClock.uptimeMillis());
Craig Mautner967212c2013-04-13 21:10:58 -0700330 pw.print(prefix); pw.print(" mStartAlpha="); pw.print(mStartAlpha);
331 pw.print(" mTargetAlpha="); pw.println(mTargetAlpha);
Craig Mautner1420b932012-12-28 17:14:38 -0800332 }
333}