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;
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;
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 & behind scrim alpha values are determined by ScrimController#applyState
94             // based on the shade expansion
95 
96             mFrontTint = Color.BLACK;
97             mFrontAlpha = .66f;
98         }
99     },
100 
101     AUTH_SCRIMMED {
102         @Override
prepare(ScrimState previousState)103         public void prepare(ScrimState previousState) {
104             mNotifTint = previousState.mNotifTint;
105             mNotifAlpha = previousState.mNotifAlpha;
106 
107             mBehindTint = previousState.mBehindTint;
108             mBehindAlpha = previousState.mBehindAlpha;
109 
110             mFrontTint = Color.BLACK;
111             mFrontAlpha = .66f;
112         }
113     },
114 
115     /**
116      * Showing password challenge on the keyguard.
117      */
118     BOUNCER {
119         @Override
prepare(ScrimState previousState)120         public void prepare(ScrimState previousState) {
121             mBehindAlpha = mClipQsScrim ? 1 : mDefaultScrimAlpha;
122             mBehindTint = mClipQsScrim ? Color.BLACK : Color.TRANSPARENT;
123             mNotifAlpha = mClipQsScrim ? mDefaultScrimAlpha : 0;
124             mNotifTint = Color.TRANSPARENT;
125             mFrontAlpha = 0f;
126         }
127     },
128 
129     /**
130      * Showing password challenge on top of a FLAG_SHOW_WHEN_LOCKED activity.
131      */
132     BOUNCER_SCRIMMED {
133         @Override
prepare(ScrimState previousState)134         public void prepare(ScrimState previousState) {
135             mBehindAlpha = 0;
136             mFrontAlpha = mDefaultScrimAlpha;
137         }
138     },
139 
140     SHADE_LOCKED {
141         @Override
prepare(ScrimState previousState)142         public void prepare(ScrimState previousState) {
143             mBehindAlpha = mClipQsScrim ? 1 : mDefaultScrimAlpha;
144             mNotifAlpha = 1f;
145             mFrontAlpha = 0f;
146             mBehindTint = Color.BLACK;
147 
148             if (mClipQsScrim) {
149                 updateScrimColor(mScrimBehind, 1f /* alpha */, Color.BLACK);
150             }
151         }
152 
153         // to make sure correct color is returned before "prepare" is called
154         @Override
getBehindTint()155         public int getBehindTint() {
156             return Color.BLACK;
157         }
158     },
159 
160     /**
161      * Changing screen brightness from quick settings.
162      */
163     BRIGHTNESS_MIRROR {
164         @Override
prepare(ScrimState previousState)165         public void prepare(ScrimState previousState) {
166             mBehindAlpha = 0;
167             mFrontAlpha = 0;
168         }
169     },
170 
171     /**
172      * Always on display or screen off.
173      */
174     AOD {
175         @Override
prepare(ScrimState previousState)176         public void prepare(ScrimState previousState) {
177             final boolean alwaysOnEnabled = mDozeParameters.getAlwaysOn();
178             final boolean quickPickupEnabled = mDozeParameters.isQuickPickupEnabled();
179             final boolean isDocked = mDockManager.isDocked();
180             mBlankScreen = mDisplayRequiresBlanking;
181 
182             mFrontTint = Color.BLACK;
183             mFrontAlpha = (alwaysOnEnabled || isDocked || quickPickupEnabled)
184                     ? mAodFrontScrimAlpha : 1f;
185 
186             mBehindTint = Color.BLACK;
187             mBehindAlpha = ScrimController.TRANSPARENT;
188 
189             mAnimationDuration = ScrimController.ANIMATION_DURATION_LONG;
190             // DisplayPowerManager may blank the screen for us, or we might blank it for ourselves
191             // by animating the screen off via the LightRevelScrim. In either case we just need to
192             // set our state.
193             mAnimateChange = mDozeParameters.shouldControlScreenOff()
194                     && !mDozeParameters.shouldControlUnlockedScreenOff();
195         }
196 
197         @Override
getMaxLightRevealScrimAlpha()198         public float getMaxLightRevealScrimAlpha() {
199             return mWallpaperSupportsAmbientMode && !mHasBackdrop ? 0f : 1f;
200         }
201 
202         @Override
isLowPowerState()203         public boolean isLowPowerState() {
204             return true;
205         }
206     },
207 
208     /**
209      * When phone wakes up because you received a notification.
210      */
211     PULSING {
212         @Override
prepare(ScrimState previousState)213         public void prepare(ScrimState previousState) {
214             mFrontAlpha = mAodFrontScrimAlpha;
215             mBehindTint = Color.BLACK;
216             mFrontTint = Color.BLACK;
217             mBlankScreen = mDisplayRequiresBlanking;
218             mAnimationDuration = mWakeLockScreenSensorActive
219                     ? ScrimController.ANIMATION_DURATION_LONG : ScrimController.ANIMATION_DURATION;
220         }
221         @Override
getMaxLightRevealScrimAlpha()222         public float getMaxLightRevealScrimAlpha() {
223             return mWakeLockScreenSensorActive ? ScrimController.WAKE_SENSOR_SCRIM_ALPHA
224                 : AOD.getMaxLightRevealScrimAlpha();
225         }
226     },
227 
228     /**
229      * Unlocked on top of an app (launcher or any other activity.)
230      */
231     UNLOCKED {
232         @Override
prepare(ScrimState previousState)233         public void prepare(ScrimState previousState) {
234             // State that UI will sync to.
235             mBehindAlpha = mClipQsScrim ? 1 : 0;
236             mNotifAlpha = 0;
237             mFrontAlpha = 0;
238 
239             mAnimationDuration = mKeyguardFadingAway
240                     ? mKeyguardFadingAwayDuration
241                     : StatusBar.FADE_KEYGUARD_DURATION;
242 
243             boolean fromAod = previousState == AOD || previousState == PULSING;
244             mAnimateChange = !mLaunchingAffordanceWithPreview && !fromAod;
245 
246             mFrontTint = Color.TRANSPARENT;
247             mBehindTint = Color.BLACK;
248             mBlankScreen = false;
249 
250             if (previousState == ScrimState.AOD) {
251                 // Set all scrims black, before they fade transparent.
252                 updateScrimColor(mScrimInFront, 1f /* alpha */, Color.BLACK /* tint */);
253                 updateScrimColor(mScrimBehind, 1f /* alpha */, Color.BLACK /* tint */);
254 
255                 // Scrims should still be black at the end of the transition.
256                 mFrontTint = Color.BLACK;
257                 mBehindTint = Color.BLACK;
258                 mBlankScreen = true;
259             }
260 
261             if (mClipQsScrim) {
262                 updateScrimColor(mScrimBehind, 1f /* alpha */, Color.BLACK);
263             }
264         }
265     };
266 
267     boolean mBlankScreen = false;
268     long mAnimationDuration = ScrimController.ANIMATION_DURATION;
269     int mFrontTint = Color.TRANSPARENT;
270     int mBehindTint = Color.TRANSPARENT;
271     int mNotifTint = Color.TRANSPARENT;
272 
273     boolean mAnimateChange = true;
274     float mAodFrontScrimAlpha;
275     float mFrontAlpha;
276     float mBehindAlpha;
277     float mNotifAlpha;
278 
279     float mScrimBehindAlphaKeyguard;
280     float mDefaultScrimAlpha;
281     ScrimView mScrimInFront;
282     ScrimView mScrimBehind;
283 
284     DozeParameters mDozeParameters;
285     DockManager mDockManager;
286     boolean mDisplayRequiresBlanking;
287     boolean mWallpaperSupportsAmbientMode;
288     boolean mHasBackdrop;
289     boolean mLaunchingAffordanceWithPreview;
290     boolean mWakeLockScreenSensorActive;
291     boolean mKeyguardFadingAway;
292     long mKeyguardFadingAwayDuration;
293     boolean mClipQsScrim;
294 
init(ScrimView scrimInFront, ScrimView scrimBehind, DozeParameters dozeParameters, DockManager dockManager)295     public void init(ScrimView scrimInFront, ScrimView scrimBehind, DozeParameters dozeParameters,
296             DockManager dockManager) {
297         mScrimInFront = scrimInFront;
298         mScrimBehind = scrimBehind;
299 
300         mDozeParameters = dozeParameters;
301         mDockManager = dockManager;
302         mDisplayRequiresBlanking = dozeParameters.getDisplayNeedsBlanking();
303     }
304 
305     /** Prepare state for transition. */
prepare(ScrimState previousState)306     public void prepare(ScrimState previousState) {
307     }
308 
getFrontAlpha()309     public float getFrontAlpha() {
310         return mFrontAlpha;
311     }
312 
getBehindAlpha()313     public float getBehindAlpha() {
314         return mBehindAlpha;
315     }
316 
getMaxLightRevealScrimAlpha()317     public float getMaxLightRevealScrimAlpha() {
318         return 1f;
319     }
320 
getNotifAlpha()321     public float getNotifAlpha() {
322         return mNotifAlpha;
323     }
324 
getFrontTint()325     public int getFrontTint() {
326         return mFrontTint;
327     }
328 
getBehindTint()329     public int getBehindTint() {
330         return mBehindTint;
331     }
332 
getNotifTint()333     public int getNotifTint() {
334         return mNotifTint;
335     }
336 
getAnimationDuration()337     public long getAnimationDuration() {
338         return mAnimationDuration;
339     }
340 
getBlanksScreen()341     public boolean getBlanksScreen() {
342         return mBlankScreen;
343     }
344 
updateScrimColor(ScrimView scrim, float alpha, int tint)345     public void updateScrimColor(ScrimView scrim, float alpha, int tint) {
346         Trace.traceCounter(Trace.TRACE_TAG_APP,
347                 scrim == mScrimInFront ? "front_scrim_alpha" : "back_scrim_alpha",
348                 (int) (alpha * 255));
349 
350         Trace.traceCounter(Trace.TRACE_TAG_APP,
351                 scrim == mScrimInFront ? "front_scrim_tint" : "back_scrim_tint",
352                 Color.alpha(tint));
353 
354         scrim.setTint(tint);
355         scrim.setViewAlpha(alpha);
356     }
357 
getAnimateChange()358     public boolean getAnimateChange() {
359         return mAnimateChange;
360     }
361 
setAodFrontScrimAlpha(float aodFrontScrimAlpha)362     public void setAodFrontScrimAlpha(float aodFrontScrimAlpha) {
363         mAodFrontScrimAlpha = aodFrontScrimAlpha;
364     }
365 
setScrimBehindAlphaKeyguard(float scrimBehindAlphaKeyguard)366     public void setScrimBehindAlphaKeyguard(float scrimBehindAlphaKeyguard) {
367         mScrimBehindAlphaKeyguard = scrimBehindAlphaKeyguard;
368     }
369 
setDefaultScrimAlpha(float defaultScrimAlpha)370     public void setDefaultScrimAlpha(float defaultScrimAlpha) {
371         mDefaultScrimAlpha = defaultScrimAlpha;
372     }
373 
setWallpaperSupportsAmbientMode(boolean wallpaperSupportsAmbientMode)374     public void setWallpaperSupportsAmbientMode(boolean wallpaperSupportsAmbientMode) {
375         mWallpaperSupportsAmbientMode = wallpaperSupportsAmbientMode;
376     }
377 
setLaunchingAffordanceWithPreview(boolean launchingAffordanceWithPreview)378     public void setLaunchingAffordanceWithPreview(boolean launchingAffordanceWithPreview) {
379         mLaunchingAffordanceWithPreview = launchingAffordanceWithPreview;
380     }
381 
isLowPowerState()382     public boolean isLowPowerState() {
383         return false;
384     }
385 
setHasBackdrop(boolean hasBackdrop)386     public void setHasBackdrop(boolean hasBackdrop) {
387         mHasBackdrop = hasBackdrop;
388     }
389 
setWakeLockScreenSensorActive(boolean active)390     public void setWakeLockScreenSensorActive(boolean active) {
391         mWakeLockScreenSensorActive = active;
392     }
393 
setKeyguardFadingAway(boolean fadingAway, long duration)394     public void setKeyguardFadingAway(boolean fadingAway, long duration) {
395         mKeyguardFadingAway = fadingAway;
396         mKeyguardFadingAwayDuration = duration;
397     }
398 
setClipQsScrim(boolean clipsQsScrim)399     public void setClipQsScrim(boolean clipsQsScrim) {
400         mClipQsScrim = clipsQsScrim;
401     }
402 }