1 /*
2  * Copyright (C) 2017 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 
17 package com.android.systemui.statusbar.phone;
18 
19 import android.graphics.Color;
20 import android.os.Trace;
21 
22 import com.android.systemui.dock.DockManager;
23 import com.android.systemui.scrim.ScrimView;
24 import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
25 
26 /**
27  * Possible states of the ScrimController state machine.
28  */
29 public enum ScrimState {
30 
31     /**
32      * Initial state.
33      */
34     UNINITIALIZED,
35 
36     /**
37      * When turned off by sensors (prox, presence.)
38      */
39     OFF {
40         @Override
prepare(ScrimState previousState)41         public void prepare(ScrimState previousState) {
42             mFrontTint = Color.BLACK;
43             mBehindTint = Color.BLACK;
44 
45             mFrontAlpha = 1f;
46             mBehindAlpha = 1f;
47 
48             mAnimationDuration = ScrimController.ANIMATION_DURATION_LONG;
49         }
50 
51         @Override
isLowPowerState()52         public boolean isLowPowerState() {
53             return true;
54         }
55     },
56 
57     /**
58      * On the lock screen.
59      */
60     KEYGUARD {
61         @Override
prepare(ScrimState previousState)62         public void prepare(ScrimState previousState) {
63             mBlankScreen = false;
64             if (previousState == ScrimState.AOD) {
65                 mAnimationDuration = StackStateAnimator.ANIMATION_DURATION_WAKEUP_SCRIM;
66                 if (mDisplayRequiresBlanking) {
67                     // DisplayPowerManager will blank the screen, we'll just
68                     // set our scrim to black in this frame to avoid flickering and
69                     // fade it out afterwards.
70                     mBlankScreen = true;
71                 }
72             } else if (previousState == ScrimState.KEYGUARD) {
73                 mAnimationDuration = StackStateAnimator.ANIMATION_DURATION_WAKEUP_SCRIM;
74             } else {
75                 mAnimationDuration = ScrimController.ANIMATION_DURATION;
76             }
77             mFrontTint = Color.BLACK;
78             mBehindTint = Color.BLACK;
79             mNotifTint = mClipQsScrim ? Color.BLACK : Color.TRANSPARENT;
80 
81             mFrontAlpha = 0;
82             mBehindAlpha = mClipQsScrim ? 1 : mScrimBehindAlphaKeyguard;
83             mNotifAlpha = mClipQsScrim ? mScrimBehindAlphaKeyguard : 0;
84             if (mClipQsScrim) {
85                 updateScrimColor(mScrimBehind, 1f /* alpha */, Color.BLACK);
86             }
87         }
88     },
89 
90     AUTH_SCRIMMED_SHADE {
91         @Override
prepare(ScrimState previousState)92         public void prepare(ScrimState previousState) {
93             // notif scrim alpha values are determined by ScrimController#applyState
94             // based on the shade expansion
95 
96             mFrontTint = Color.BLACK;
97             mFrontAlpha = .66f;
98 
99             mBehindTint = Color.BLACK;
100             mBehindAlpha = 1f;
101         }
102     },
103 
104     AUTH_SCRIMMED {
105         @Override
prepare(ScrimState previousState)106         public void prepare(ScrimState previousState) {
107             mNotifTint = previousState.mNotifTint;
108             mNotifAlpha = previousState.mNotifAlpha;
109 
110             mBehindTint = previousState.mBehindTint;
111             mBehindAlpha = previousState.mBehindAlpha;
112 
113             mFrontTint = Color.BLACK;
114             mFrontAlpha = .66f;
115         }
116     },
117 
118     /**
119      * Showing password challenge on the keyguard.
120      */
121     BOUNCER {
122         @Override
prepare(ScrimState previousState)123         public void prepare(ScrimState previousState) {
124             mBehindAlpha = mClipQsScrim ? 1 : mDefaultScrimAlpha;
125             mBehindTint = mClipQsScrim ? Color.BLACK : mSurfaceColor;
126             mNotifAlpha = mClipQsScrim ? mDefaultScrimAlpha : 0;
127             mNotifTint = Color.TRANSPARENT;
128             mFrontAlpha = 0f;
129         }
130 
131         @Override
setSurfaceColor(int surfaceColor)132         public void setSurfaceColor(int surfaceColor) {
133             super.setSurfaceColor(surfaceColor);
134             if (!mClipQsScrim) {
135                 mBehindTint = mSurfaceColor;
136             }
137         }
138     },
139 
140     /**
141      * Showing password challenge on top of a FLAG_SHOW_WHEN_LOCKED activity.
142      */
143     BOUNCER_SCRIMMED {
144         @Override
prepare(ScrimState previousState)145         public void prepare(ScrimState previousState) {
146             mBehindAlpha = 0;
147             mFrontAlpha = mDefaultScrimAlpha;
148         }
149     },
150 
151     SHADE_LOCKED {
152         @Override
prepare(ScrimState previousState)153         public void prepare(ScrimState previousState) {
154             mBehindAlpha = mClipQsScrim ? 1 : mDefaultScrimAlpha;
155             mNotifAlpha = 1f;
156             mFrontAlpha = 0f;
157             mBehindTint = mClipQsScrim ? Color.TRANSPARENT : Color.BLACK;
158 
159             if (mClipQsScrim) {
160                 updateScrimColor(mScrimBehind, 1f /* alpha */, Color.BLACK);
161             }
162         }
163     },
164 
165     /**
166      * Changing screen brightness from quick settings.
167      */
168     BRIGHTNESS_MIRROR {
169         @Override
prepare(ScrimState previousState)170         public void prepare(ScrimState previousState) {
171             mBehindAlpha = 0;
172             mFrontAlpha = 0;
173         }
174     },
175 
176     /**
177      * Always on display or screen off.
178      */
179     AOD {
180         @Override
prepare(ScrimState previousState)181         public void prepare(ScrimState previousState) {
182             final boolean alwaysOnEnabled = mDozeParameters.getAlwaysOn();
183             final boolean quickPickupEnabled = mDozeParameters.isQuickPickupEnabled();
184             final boolean isDocked = mDockManager.isDocked();
185             mBlankScreen = mDisplayRequiresBlanking;
186 
187             mFrontTint = Color.BLACK;
188             mFrontAlpha = (alwaysOnEnabled || isDocked || quickPickupEnabled)
189                     ? mAodFrontScrimAlpha : 1f;
190 
191             mBehindTint = Color.BLACK;
192             mBehindAlpha = ScrimController.TRANSPARENT;
193 
194             mAnimationDuration = ScrimController.ANIMATION_DURATION_LONG;
195             // DisplayPowerManager may blank the screen for us, or we might blank it for ourselves
196             // by animating the screen off via the LightRevelScrim. In either case we just need to
197             // set our state.
198             mAnimateChange = mDozeParameters.shouldControlScreenOff()
199                     && !mDozeParameters.shouldShowLightRevealScrim();
200         }
201 
202         @Override
getMaxLightRevealScrimAlpha()203         public float getMaxLightRevealScrimAlpha() {
204             return mWallpaperSupportsAmbientMode && !mHasBackdrop ? 0f : 1f;
205         }
206 
207         @Override
isLowPowerState()208         public boolean isLowPowerState() {
209             return true;
210         }
211 
212         @Override
shouldBlendWithMainColor()213         public boolean shouldBlendWithMainColor() {
214             return false;
215         }
216     },
217 
218     /**
219      * When phone wakes up because you received a notification.
220      */
221     PULSING {
222         @Override
prepare(ScrimState previousState)223         public void prepare(ScrimState previousState) {
224             mFrontAlpha = mAodFrontScrimAlpha;
225             mBehindTint = Color.BLACK;
226             mFrontTint = Color.BLACK;
227             mBlankScreen = mDisplayRequiresBlanking;
228             mAnimationDuration = mWakeLockScreenSensorActive
229                     ? ScrimController.ANIMATION_DURATION_LONG : ScrimController.ANIMATION_DURATION;
230         }
231         @Override
getMaxLightRevealScrimAlpha()232         public float getMaxLightRevealScrimAlpha() {
233             return mWakeLockScreenSensorActive ? ScrimController.WAKE_SENSOR_SCRIM_ALPHA
234                 : AOD.getMaxLightRevealScrimAlpha();
235         }
236     },
237 
238     /**
239      * Unlocked on top of an app (launcher or any other activity.)
240      */
241     UNLOCKED {
242         @Override
prepare(ScrimState previousState)243         public void prepare(ScrimState previousState) {
244             // State that UI will sync to.
245             mBehindAlpha = mClipQsScrim ? 1 : 0;
246             mNotifAlpha = 0;
247             mFrontAlpha = 0;
248 
249             mAnimationDuration = mKeyguardFadingAway
250                     ? mKeyguardFadingAwayDuration
251                     : CentralSurfaces.FADE_KEYGUARD_DURATION;
252 
253             boolean fromAod = previousState == AOD || previousState == PULSING;
254             // If launch/occlude animations were playing, they already animated the scrim
255             // alpha to 0f as part of the animation. If we animate it now, we'll set it back
256             // to 1f and animate it back to 0f, causing an unwanted scrim flash.
257             mAnimateChange = !mLaunchingAffordanceWithPreview
258                     && !mOccludeAnimationPlaying
259                     && !fromAod;
260 
261             mFrontTint = Color.TRANSPARENT;
262             mBehindTint = Color.BLACK;
263             mBlankScreen = false;
264 
265             if (mDisplayRequiresBlanking && previousState == ScrimState.AOD) {
266                 // Set all scrims black, before they fade transparent.
267                 updateScrimColor(mScrimInFront, 1f /* alpha */, Color.BLACK /* tint */);
268                 updateScrimColor(mScrimBehind, 1f /* alpha */, Color.BLACK /* tint */);
269 
270                 // Scrims should still be black at the end of the transition.
271                 mFrontTint = Color.BLACK;
272                 mBehindTint = Color.BLACK;
273                 mBlankScreen = true;
274             }
275 
276             if (mClipQsScrim) {
277                 updateScrimColor(mScrimBehind, 1f /* alpha */, Color.BLACK);
278             }
279         }
280     },
281 
282     DREAMING {
283         @Override
prepare(ScrimState previousState)284         public void prepare(ScrimState previousState) {
285             mFrontTint = Color.TRANSPARENT;
286             mBehindTint = Color.BLACK;
287             mNotifTint = mClipQsScrim ? Color.BLACK : Color.TRANSPARENT;
288 
289             mFrontAlpha = 0;
290             mBehindAlpha = mClipQsScrim ? 1 : 0;
291             mNotifAlpha = 0;
292 
293             mBlankScreen = false;
294 
295             if (mClipQsScrim) {
296                 updateScrimColor(mScrimBehind, 1f /* alpha */, Color.BLACK);
297             }
298         }
299     };
300 
301     boolean mBlankScreen = false;
302     long mAnimationDuration = ScrimController.ANIMATION_DURATION;
303     int mFrontTint = Color.TRANSPARENT;
304     int mBehindTint = Color.TRANSPARENT;
305     int mNotifTint = Color.TRANSPARENT;
306     int mSurfaceColor = Color.TRANSPARENT;
307 
308     boolean mAnimateChange = true;
309     float mAodFrontScrimAlpha;
310     float mFrontAlpha;
311     float mBehindAlpha;
312     float mNotifAlpha;
313 
314     float mScrimBehindAlphaKeyguard;
315     float mDefaultScrimAlpha;
316     ScrimView mScrimInFront;
317     ScrimView mScrimBehind;
318 
319     DozeParameters mDozeParameters;
320     DockManager mDockManager;
321     boolean mDisplayRequiresBlanking;
322     boolean mWallpaperSupportsAmbientMode;
323     boolean mHasBackdrop;
324     boolean mLaunchingAffordanceWithPreview;
325     boolean mOccludeAnimationPlaying;
326     boolean mWakeLockScreenSensorActive;
327     boolean mKeyguardFadingAway;
328     long mKeyguardFadingAwayDuration;
329     boolean mClipQsScrim;
330 
init(ScrimView scrimInFront, ScrimView scrimBehind, DozeParameters dozeParameters, DockManager dockManager)331     public void init(ScrimView scrimInFront, ScrimView scrimBehind, DozeParameters dozeParameters,
332             DockManager dockManager) {
333         mScrimInFront = scrimInFront;
334         mScrimBehind = scrimBehind;
335 
336         mDozeParameters = dozeParameters;
337         mDockManager = dockManager;
338         mDisplayRequiresBlanking = dozeParameters.getDisplayNeedsBlanking();
339     }
340 
341     /** Prepare state for transition. */
prepare(ScrimState previousState)342     public void prepare(ScrimState previousState) {
343     }
344 
345     /**
346      * Whether a particular state should enable blending with extracted theme colors.
347      */
shouldBlendWithMainColor()348     public boolean shouldBlendWithMainColor() {
349         return true;
350     }
351 
getFrontAlpha()352     public float getFrontAlpha() {
353         return mFrontAlpha;
354     }
355 
getBehindAlpha()356     public float getBehindAlpha() {
357         return mBehindAlpha;
358     }
359 
getMaxLightRevealScrimAlpha()360     public float getMaxLightRevealScrimAlpha() {
361         return 1f;
362     }
363 
getNotifAlpha()364     public float getNotifAlpha() {
365         return mNotifAlpha;
366     }
367 
getFrontTint()368     public int getFrontTint() {
369         return mFrontTint;
370     }
371 
getBehindTint()372     public int getBehindTint() {
373         return mBehindTint;
374     }
375 
getNotifTint()376     public int getNotifTint() {
377         return mNotifTint;
378     }
379 
getAnimationDuration()380     public long getAnimationDuration() {
381         return mAnimationDuration;
382     }
383 
getBlanksScreen()384     public boolean getBlanksScreen() {
385         return mBlankScreen;
386     }
387 
updateScrimColor(ScrimView scrim, float alpha, int tint)388     public void updateScrimColor(ScrimView scrim, float alpha, int tint) {
389         if (ScrimController.DEBUG_MODE) {
390             tint = scrim == mScrimInFront ? ScrimController.DEBUG_FRONT_TINT
391                     : ScrimController.DEBUG_BEHIND_TINT;
392         }
393         Trace.traceCounter(Trace.TRACE_TAG_APP,
394                 scrim == mScrimInFront ? "front_scrim_alpha" : "back_scrim_alpha",
395                 (int) (alpha * 255));
396 
397         Trace.traceCounter(Trace.TRACE_TAG_APP,
398                 scrim == mScrimInFront ? "front_scrim_tint" : "back_scrim_tint",
399                 Color.alpha(tint));
400 
401         scrim.setTint(tint);
402         scrim.setViewAlpha(alpha);
403     }
404 
getAnimateChange()405     public boolean getAnimateChange() {
406         return mAnimateChange;
407     }
408 
setAodFrontScrimAlpha(float aodFrontScrimAlpha)409     public void setAodFrontScrimAlpha(float aodFrontScrimAlpha) {
410         mAodFrontScrimAlpha = aodFrontScrimAlpha;
411     }
412 
setScrimBehindAlphaKeyguard(float scrimBehindAlphaKeyguard)413     public void setScrimBehindAlphaKeyguard(float scrimBehindAlphaKeyguard) {
414         mScrimBehindAlphaKeyguard = scrimBehindAlphaKeyguard;
415     }
416 
setDefaultScrimAlpha(float defaultScrimAlpha)417     public void setDefaultScrimAlpha(float defaultScrimAlpha) {
418         mDefaultScrimAlpha = defaultScrimAlpha;
419     }
420 
setSurfaceColor(int surfaceColor)421     public void setSurfaceColor(int surfaceColor) {
422         mSurfaceColor = surfaceColor;
423     }
424 
setWallpaperSupportsAmbientMode(boolean wallpaperSupportsAmbientMode)425     public void setWallpaperSupportsAmbientMode(boolean wallpaperSupportsAmbientMode) {
426         mWallpaperSupportsAmbientMode = wallpaperSupportsAmbientMode;
427     }
428 
setLaunchingAffordanceWithPreview(boolean launchingAffordanceWithPreview)429     public void setLaunchingAffordanceWithPreview(boolean launchingAffordanceWithPreview) {
430         mLaunchingAffordanceWithPreview = launchingAffordanceWithPreview;
431     }
432 
setOccludeAnimationPlaying(boolean occludeAnimationPlaying)433     public void setOccludeAnimationPlaying(boolean occludeAnimationPlaying) {
434         mOccludeAnimationPlaying = occludeAnimationPlaying;
435     }
436 
isLowPowerState()437     public boolean isLowPowerState() {
438         return false;
439     }
440 
setHasBackdrop(boolean hasBackdrop)441     public void setHasBackdrop(boolean hasBackdrop) {
442         mHasBackdrop = hasBackdrop;
443     }
444 
setWakeLockScreenSensorActive(boolean active)445     public void setWakeLockScreenSensorActive(boolean active) {
446         mWakeLockScreenSensorActive = active;
447     }
448 
setKeyguardFadingAway(boolean fadingAway, long duration)449     public void setKeyguardFadingAway(boolean fadingAway, long duration) {
450         mKeyguardFadingAway = fadingAway;
451         mKeyguardFadingAwayDuration = duration;
452     }
453 
setClipQsScrim(boolean clipsQsScrim)454     public void setClipQsScrim(boolean clipsQsScrim) {
455         mClipQsScrim = clipsQsScrim;
456     }
457 }
458