blob: 052b2f542d28d8ab5f023dc9d33c9cf6ce29e730 [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 Gruszczynski64b6b442016-01-18 13:20:58 -080019import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DIM_LAYER;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080020import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE;
21import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC;
22import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
23import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
24import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
25
Craig Mautner1420b932012-12-28 17:14:38 -080026import android.graphics.PixelFormat;
Craig Mautner05d29032013-05-03 13:40:13 -070027import android.graphics.Rect;
Craig Mautner1420b932012-12-28 17:14:38 -080028import android.os.SystemClock;
29import android.util.Slog;
30import android.view.DisplayInfo;
Mathias Agopian3866f0d2013-02-11 22:08:48 -080031import android.view.SurfaceControl;
Craig Mautner1420b932012-12-28 17:14:38 -080032
33import java.io.PrintWriter;
34
35public class DimLayer {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080036 private static final String TAG = TAG_WITH_CLASS_NAME ? "DimLayer" : TAG_WM;
Filip Gruszczynski64b6b442016-01-18 13:20:58 -080037 private final WindowManagerService mService;
Filip Gruszczynski57b6cce2015-10-06 09:50:51 -070038
Craig Mautner1420b932012-12-28 17:14:38 -080039 /** Actual surface that dims */
Filip Gruszczynski64b6b442016-01-18 13:20:58 -080040 private SurfaceControl mDimSurface;
Craig Mautner1420b932012-12-28 17:14:38 -080041
42 /** Last value passed to mDimSurface.setAlpha() */
Filip Gruszczynski64b6b442016-01-18 13:20:58 -080043 private float mAlpha = 0;
Craig Mautner1420b932012-12-28 17:14:38 -080044
45 /** Last value passed to mDimSurface.setLayer() */
Filip Gruszczynski64b6b442016-01-18 13:20:58 -080046 private int mLayer = -1;
Craig Mautner1420b932012-12-28 17:14:38 -080047
Craig Mautner05d29032013-05-03 13:40:13 -070048 /** Next values to pass to mDimSurface.setPosition() and mDimSurface.setSize() */
Filip Gruszczynski64b6b442016-01-18 13:20:58 -080049 private final Rect mBounds = new Rect();
Craig Mautner05d29032013-05-03 13:40:13 -070050
51 /** Last values passed to mDimSurface.setPosition() and mDimSurface.setSize() */
Filip Gruszczynski64b6b442016-01-18 13:20:58 -080052 private final Rect mLastBounds = new Rect();
Craig Mautner1420b932012-12-28 17:14:38 -080053
54 /** True after mDimSurface.show() has been called, false after mDimSurface.hide(). */
55 private boolean mShowing = false;
56
57 /** Value of mAlpha when beginning transition to mTargetAlpha */
Filip Gruszczynski64b6b442016-01-18 13:20:58 -080058 private float mStartAlpha = 0;
Craig Mautner1420b932012-12-28 17:14:38 -080059
60 /** Final value of mAlpha following transition */
Filip Gruszczynski64b6b442016-01-18 13:20:58 -080061 private float mTargetAlpha = 0;
Craig Mautner1420b932012-12-28 17:14:38 -080062
63 /** Time in units of SystemClock.uptimeMillis() at which the current transition started */
Filip Gruszczynski64b6b442016-01-18 13:20:58 -080064 private long mStartTime;
Craig Mautner1420b932012-12-28 17:14:38 -080065
66 /** Time in milliseconds to take to transition from mStartAlpha to mTargetAlpha */
Filip Gruszczynski64b6b442016-01-18 13:20:58 -080067 private long mDuration;
68
69 private boolean mDestroyed = false;
70
71 private final int mDisplayId;
72
Craig Mautner1420b932012-12-28 17:14:38 -080073
Wale Ogunwalee4a0c572015-06-30 08:40:31 -070074 /** Interface implemented by users of the dim layer */
75 interface DimLayerUser {
Wale Ogunwale29bfbb82016-05-12 15:13:52 -070076 /** Returns true if the dim should be fullscreen. */
77 boolean dimFullscreen();
Wale Ogunwalee4a0c572015-06-30 08:40:31 -070078 /** Returns the display info. of the dim layer user. */
79 DisplayInfo getDisplayInfo();
Filip Gruszczynski0689ae92015-10-01 12:30:31 -070080 /** Gets the bounds of the dim layer user. */
Chong Zhang4c9ba52a2015-11-10 18:36:33 -080081 void getDimBounds(Rect outBounds);
Filip Gruszczynski0689ae92015-10-01 12:30:31 -070082 String toShortString();
Wale Ogunwalee4a0c572015-06-30 08:40:31 -070083 }
84 /** The user of this dim layer. */
Filip Gruszczynski64b6b442016-01-18 13:20:58 -080085 private final DimLayerUser mUser;
Craig Mautnerc7b8a102013-10-02 16:49:52 -070086
Jorim Jaggibc5425c2016-03-01 13:51:16 +010087 private final String mName;
88
89 DimLayer(WindowManagerService service, DimLayerUser user, int displayId, String name) {
Wale Ogunwalee4a0c572015-06-30 08:40:31 -070090 mUser = user;
Filip Gruszczynski64b6b442016-01-18 13:20:58 -080091 mDisplayId = displayId;
92 mService = service;
Jorim Jaggibc5425c2016-03-01 13:51:16 +010093 mName = name;
Filip Gruszczynski64b6b442016-01-18 13:20:58 -080094 if (DEBUG_DIM_LAYER) Slog.v(TAG, "Ctor: displayId=" + displayId);
95 }
96
97 private void constructSurface(WindowManagerService service) {
Mathias Agopian3866f0d2013-02-11 22:08:48 -080098 SurfaceControl.openTransaction();
Craig Mautner1420b932012-12-28 17:14:38 -080099 try {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800100 if (DEBUG_SURFACE_TRACE) {
Robert Carre6a83512015-11-03 16:09:21 -0800101 mDimSurface = new WindowSurfaceController.SurfaceTrace(service.mFxSession,
Craig Mautner1420b932012-12-28 17:14:38 -0800102 "DimSurface",
103 16, 16, PixelFormat.OPAQUE,
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800104 SurfaceControl.FX_SURFACE_DIM | SurfaceControl.HIDDEN);
Craig Mautner1420b932012-12-28 17:14:38 -0800105 } else {
Jorim Jaggibc5425c2016-03-01 13:51:16 +0100106 mDimSurface = new SurfaceControl(service.mFxSession, mName,
Craig Mautner1420b932012-12-28 17:14:38 -0800107 16, 16, PixelFormat.OPAQUE,
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800108 SurfaceControl.FX_SURFACE_DIM | SurfaceControl.HIDDEN);
Craig Mautner1420b932012-12-28 17:14:38 -0800109 }
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800110 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) Slog.i(TAG,
111 " DIM " + mDimSurface + ": CREATE");
Filip Gruszczynski64b6b442016-01-18 13:20:58 -0800112 mDimSurface.setLayerStack(mDisplayId);
113 adjustBounds();
114 adjustAlpha(mAlpha);
115 adjustLayer(mLayer);
Craig Mautner1420b932012-12-28 17:14:38 -0800116 } catch (Exception e) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800117 Slog.e(TAG_WM, "Exception creating Dim surface", e);
Craig Mautner1420b932012-12-28 17:14:38 -0800118 } finally {
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800119 SurfaceControl.closeTransaction();
Craig Mautner1420b932012-12-28 17:14:38 -0800120 }
121 }
122
123 /** Return true if dim layer is showing */
124 boolean isDimming() {
125 return mTargetAlpha != 0;
126 }
127
128 /** Return true if in a transition period */
129 boolean isAnimating() {
130 return mTargetAlpha != mAlpha;
131 }
132
133 float getTargetAlpha() {
134 return mTargetAlpha;
135 }
136
Craig Mautner13131e72013-01-11 11:03:33 -0800137 void setLayer(int layer) {
Filip Gruszczynski64b6b442016-01-18 13:20:58 -0800138 if (mLayer == layer) {
139 return;
140 }
141 mLayer = layer;
142 adjustLayer(layer);
143 }
144
145 private void adjustLayer(int layer) {
146 if (mDimSurface != null) {
Craig Mautner13131e72013-01-11 11:03:33 -0800147 mDimSurface.setLayer(layer);
148 }
149 }
150
151 int getLayer() {
152 return mLayer;
153 }
154
Craig Mautner1420b932012-12-28 17:14:38 -0800155 private void setAlpha(float alpha) {
Filip Gruszczynski64b6b442016-01-18 13:20:58 -0800156 if (mAlpha == alpha) {
157 return;
158 }
159 mAlpha = alpha;
160 adjustAlpha(alpha);
161 }
162
163 private void adjustAlpha(float alpha) {
164 if (DEBUG_DIM_LAYER) Slog.v(TAG, "setAlpha alpha=" + alpha);
165 try {
166 if (mDimSurface != null) {
Craig Mautner1420b932012-12-28 17:14:38 -0800167 mDimSurface.setAlpha(alpha);
Filip Gruszczynski64b6b442016-01-18 13:20:58 -0800168 }
169 if (alpha == 0 && mShowing) {
170 if (DEBUG_DIM_LAYER) Slog.v(TAG, "setAlpha hiding");
171 if (mDimSurface != null) {
Craig Mautner1420b932012-12-28 17:14:38 -0800172 mDimSurface.hide();
173 mShowing = false;
Filip Gruszczynski64b6b442016-01-18 13:20:58 -0800174 }
175 } else if (alpha > 0 && !mShowing) {
176 if (DEBUG_DIM_LAYER) Slog.v(TAG, "setAlpha showing");
177 if (mDimSurface != null) {
Craig Mautner1420b932012-12-28 17:14:38 -0800178 mDimSurface.show();
179 mShowing = true;
180 }
Craig Mautner1420b932012-12-28 17:14:38 -0800181 }
Filip Gruszczynski64b6b442016-01-18 13:20:58 -0800182 } catch (RuntimeException e) {
183 Slog.w(TAG, "Failure setting alpha immediately", e);
Craig Mautner1420b932012-12-28 17:14:38 -0800184 }
185 }
186
Craig Mautner902945d2014-02-20 14:31:32 -0800187 /**
Dohyun Lee6ce3a372015-03-23 09:16:34 +0900188 * NOTE: Must be called with Surface transaction open.
Craig Mautner902945d2014-02-20 14:31:32 -0800189 */
Dohyun Lee6ce3a372015-03-23 09:16:34 +0900190 private void adjustBounds() {
Wale Ogunwale29bfbb82016-05-12 15:13:52 -0700191 if (mUser.dimFullscreen()) {
192 getBoundsForFullscreen(mBounds);
Craig Mautner902945d2014-02-20 14:31:32 -0800193 }
194
Filip Gruszczynski64b6b442016-01-18 13:20:58 -0800195 if (mDimSurface != null) {
Wale Ogunwale29bfbb82016-05-12 15:13:52 -0700196 mDimSurface.setPosition(mBounds.left, mBounds.top);
197 mDimSurface.setSize(mBounds.width(), mBounds.height());
198 if (DEBUG_DIM_LAYER) Slog.v(TAG,
199 "adjustBounds user=" + mUser.toShortString() + " mBounds=" + mBounds);
Filip Gruszczynski64b6b442016-01-18 13:20:58 -0800200 }
Dohyun Lee6ce3a372015-03-23 09:16:34 +0900201
Craig Mautner902945d2014-02-20 14:31:32 -0800202 mLastBounds.set(mBounds);
Craig Mautner902945d2014-02-20 14:31:32 -0800203 }
204
Wale Ogunwale29bfbb82016-05-12 15:13:52 -0700205 private void getBoundsForFullscreen(Rect outBounds) {
206 final int dw, dh;
207 final float xPos, yPos;
208 // Set surface size to screen size.
209 final DisplayInfo info = mUser.getDisplayInfo();
210 // Multiply by 1.5 so that rotating a frozen surface that includes this does not expose
211 // a corner.
212 dw = (int) (info.logicalWidth * 1.5);
213 dh = (int) (info.logicalHeight * 1.5);
214 // back off position so 1/4 of Surface is before and 1/4 is after.
215 xPos = -1 * dw / 6;
216 yPos = -1 * dh / 6;
217 outBounds.set((int) xPos, (int) yPos, (int) xPos + dw, (int) yPos + dh);
218 }
219
220 void setBoundsForFullscreen() {
221 getBoundsForFullscreen(mBounds);
222 setBounds(mBounds);
223 }
224
Wale Ogunwale0ade61b2015-03-24 10:40:32 -0700225 /** @param bounds The new bounds to set */
226 void setBounds(Rect bounds) {
Craig Mautner05d29032013-05-03 13:40:13 -0700227 mBounds.set(bounds);
Craig Mautnerb660b9d2014-02-13 10:59:16 -0800228 if (isDimming() && !mLastBounds.equals(bounds)) {
Dohyun Lee6ce3a372015-03-23 09:16:34 +0900229 try {
Wale Ogunwale0ade61b2015-03-24 10:40:32 -0700230 SurfaceControl.openTransaction();
Dohyun Lee6ce3a372015-03-23 09:16:34 +0900231 adjustBounds();
232 } catch (RuntimeException e) {
233 Slog.w(TAG, "Failure setting size", e);
234 } finally {
Wale Ogunwale0ade61b2015-03-24 10:40:32 -0700235 SurfaceControl.closeTransaction();
Dohyun Lee6ce3a372015-03-23 09:16:34 +0900236 }
Craig Mautnerb660b9d2014-02-13 10:59:16 -0800237 }
Craig Mautner05d29032013-05-03 13:40:13 -0700238 }
239
Craig Mautner1420b932012-12-28 17:14:38 -0800240 /**
241 * @param duration The time to test.
242 * @return True if the duration would lead to an earlier end to the current animation.
243 */
244 private boolean durationEndsEarlier(long duration) {
245 return SystemClock.uptimeMillis() + duration < mStartTime + mDuration;
246 }
247
248 /** Jump to the end of the animation.
249 * NOTE: Must be called with Surface transaction open. */
250 void show() {
251 if (isAnimating()) {
Filip Gruszczynski64b6b442016-01-18 13:20:58 -0800252 if (DEBUG_DIM_LAYER) Slog.v(TAG, "show: immediate");
Craig Mautner1420b932012-12-28 17:14:38 -0800253 show(mLayer, mTargetAlpha, 0);
254 }
255 }
256
257 /**
258 * Begin an animation to a new dim value.
259 * NOTE: Must be called with Surface transaction open.
260 *
261 * @param layer The layer to set the surface to.
262 * @param alpha The dim value to end at.
263 * @param duration How long to take to get there in milliseconds.
264 */
265 void show(int layer, float alpha, long duration) {
Filip Gruszczynski64b6b442016-01-18 13:20:58 -0800266 if (DEBUG_DIM_LAYER) Slog.v(TAG, "show: layer=" + layer + " alpha=" + alpha
267 + " duration=" + duration + ", mDestroyed=" + mDestroyed);
268 if (mDestroyed) {
Craig Mautner1420b932012-12-28 17:14:38 -0800269 Slog.e(TAG, "show: no Surface");
270 // Make sure isAnimating() returns false.
271 mTargetAlpha = mAlpha = 0;
272 return;
273 }
274
Filip Gruszczynski64b6b442016-01-18 13:20:58 -0800275 if (mDimSurface == null) {
276 constructSurface(mService);
277 }
278
Dohyun Lee6ce3a372015-03-23 09:16:34 +0900279 if (!mLastBounds.equals(mBounds)) {
280 adjustBounds();
Craig Mautner1420b932012-12-28 17:14:38 -0800281 }
Dohyun Lee6ce3a372015-03-23 09:16:34 +0900282 setLayer(layer);
Craig Mautner1420b932012-12-28 17:14:38 -0800283
284 long curTime = SystemClock.uptimeMillis();
285 final boolean animating = isAnimating();
286 if ((animating && (mTargetAlpha != alpha || durationEndsEarlier(duration)))
287 || (!animating && mAlpha != alpha)) {
288 if (duration <= 0) {
289 // No animation required, just set values.
290 setAlpha(alpha);
291 } else {
292 // Start or continue animation with new parameters.
293 mStartAlpha = mAlpha;
294 mStartTime = curTime;
295 mDuration = duration;
296 }
297 }
Craig Mautner1420b932012-12-28 17:14:38 -0800298 mTargetAlpha = alpha;
Filip Gruszczynski64b6b442016-01-18 13:20:58 -0800299 if (DEBUG_DIM_LAYER) Slog.v(TAG, "show: mStartAlpha=" + mStartAlpha + " mStartTime="
300 + mStartTime + " mTargetAlpha=" + mTargetAlpha);
Craig Mautner1420b932012-12-28 17:14:38 -0800301 }
302
303 /** Immediate hide.
304 * NOTE: Must be called with Surface transaction open. */
305 void hide() {
306 if (mShowing) {
Filip Gruszczynski64b6b442016-01-18 13:20:58 -0800307 if (DEBUG_DIM_LAYER) Slog.v(TAG, "hide: immediate");
Craig Mautner1420b932012-12-28 17:14:38 -0800308 hide(0);
309 }
310 }
311
312 /**
313 * Gradually fade to transparent.
314 * NOTE: Must be called with Surface transaction open.
315 *
316 * @param duration Time to fade in milliseconds.
317 */
318 void hide(long duration) {
319 if (mShowing && (mTargetAlpha != 0 || durationEndsEarlier(duration))) {
Filip Gruszczynski64b6b442016-01-18 13:20:58 -0800320 if (DEBUG_DIM_LAYER) Slog.v(TAG, "hide: duration=" + duration);
Craig Mautner1420b932012-12-28 17:14:38 -0800321 show(mLayer, 0, duration);
322 }
323 }
324
325 /**
326 * Advance the dimming per the last #show(int, float, long) call.
327 * NOTE: Must be called with Surface transaction open.
328 *
329 * @return True if animation is still required after this step.
330 */
331 boolean stepAnimation() {
Filip Gruszczynski64b6b442016-01-18 13:20:58 -0800332 if (mDestroyed) {
333 Slog.e(TAG, "stepAnimation: surface destroyed");
Craig Mautner1420b932012-12-28 17:14:38 -0800334 // Ensure that isAnimating() returns false;
335 mTargetAlpha = mAlpha = 0;
336 return false;
337 }
Craig Mautner1420b932012-12-28 17:14:38 -0800338 if (isAnimating()) {
339 final long curTime = SystemClock.uptimeMillis();
340 final float alphaDelta = mTargetAlpha - mStartAlpha;
341 float alpha = mStartAlpha + alphaDelta * (curTime - mStartTime) / mDuration;
342 if (alphaDelta > 0 && alpha > mTargetAlpha ||
343 alphaDelta < 0 && alpha < mTargetAlpha) {
344 // Don't exceed limits.
345 alpha = mTargetAlpha;
346 }
Filip Gruszczynski64b6b442016-01-18 13:20:58 -0800347 if (DEBUG_DIM_LAYER) Slog.v(TAG, "stepAnimation: curTime=" + curTime + " alpha=" + alpha);
Craig Mautner1420b932012-12-28 17:14:38 -0800348 setAlpha(alpha);
349 }
350
351 return isAnimating();
352 }
353
354 /** Cleanup */
355 void destroySurface() {
Filip Gruszczynski64b6b442016-01-18 13:20:58 -0800356 if (DEBUG_DIM_LAYER) Slog.v(TAG, "destroySurface.");
Craig Mautner1420b932012-12-28 17:14:38 -0800357 if (mDimSurface != null) {
358 mDimSurface.destroy();
359 mDimSurface = null;
360 }
Filip Gruszczynski64b6b442016-01-18 13:20:58 -0800361 mDestroyed = true;
Craig Mautner1420b932012-12-28 17:14:38 -0800362 }
363
364 public void printTo(String prefix, PrintWriter pw) {
Craig Mautner967212c2013-04-13 21:10:58 -0700365 pw.print(prefix); pw.print("mDimSurface="); pw.print(mDimSurface);
366 pw.print(" mLayer="); pw.print(mLayer);
Craig Mautner1420b932012-12-28 17:14:38 -0800367 pw.print(" mAlpha="); pw.println(mAlpha);
Craig Mautner05d29032013-05-03 13:40:13 -0700368 pw.print(prefix); pw.print("mLastBounds="); pw.print(mLastBounds.toShortString());
369 pw.print(" mBounds="); pw.println(mBounds.toShortString());
Craig Mautner967212c2013-04-13 21:10:58 -0700370 pw.print(prefix); pw.print("Last animation: ");
Craig Mautner1420b932012-12-28 17:14:38 -0800371 pw.print(" mDuration="); pw.print(mDuration);
Craig Mautner967212c2013-04-13 21:10:58 -0700372 pw.print(" mStartTime="); pw.print(mStartTime);
Craig Mautner1420b932012-12-28 17:14:38 -0800373 pw.print(" curTime="); pw.println(SystemClock.uptimeMillis());
Craig Mautner967212c2013-04-13 21:10:58 -0700374 pw.print(prefix); pw.print(" mStartAlpha="); pw.print(mStartAlpha);
375 pw.print(" mTargetAlpha="); pw.println(mTargetAlpha);
Craig Mautner1420b932012-12-28 17:14:38 -0800376 }
377}