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.statusbar.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             mBubbleTint = previousState.mBubbleTint;
45 
46             mFrontAlpha = 1f;
47             mBehindAlpha = 1f;
48             mBubbleAlpha = previousState.mBubbleAlpha;
49 
50             mAnimationDuration = ScrimController.ANIMATION_DURATION_LONG;
51         }
52 
53         @Override
isLowPowerState()54         public boolean isLowPowerState() {
55             return true;
56         }
57     },
58 
59     /**
60      * On the lock screen.
61      */
62     KEYGUARD {
63         @Override
prepare(ScrimState previousState)64         public void prepare(ScrimState previousState) {
65             mBlankScreen = false;
66             if (previousState == ScrimState.AOD) {
67                 mAnimationDuration = StackStateAnimator.ANIMATION_DURATION_WAKEUP;
68                 if (mDisplayRequiresBlanking) {
69                     // DisplayPowerManager will blank the screen, we'll just
70                     // set our scrim to black in this frame to avoid flickering and
71                     // fade it out afterwards.
72                     mBlankScreen = true;
73                 }
74             } else if (previousState == ScrimState.KEYGUARD) {
75                 mAnimationDuration = StackStateAnimator.ANIMATION_DURATION_WAKEUP;
76             } else {
77                 mAnimationDuration = ScrimController.ANIMATION_DURATION;
78             }
79             mFrontTint = Color.BLACK;
80             mBehindTint = Color.BLACK;
81             mBubbleTint = Color.TRANSPARENT;
82 
83             mFrontAlpha = 0;
84             mBehindAlpha = mScrimBehindAlphaKeyguard;
85             mBubbleAlpha = 0;
86         }
87     },
88 
89     /**
90      * Showing password challenge on the keyguard.
91      */
92     BOUNCER {
93         @Override
prepare(ScrimState previousState)94         public void prepare(ScrimState previousState) {
95             mBehindAlpha = mDefaultScrimAlpha;
96             mFrontAlpha = 0f;
97             mBubbleAlpha = 0f;
98         }
99     },
100 
101     /**
102      * Showing password challenge on top of a FLAG_SHOW_WHEN_LOCKED activity.
103      */
104     BOUNCER_SCRIMMED {
105         @Override
prepare(ScrimState previousState)106         public void prepare(ScrimState previousState) {
107             mBehindAlpha = 0;
108             mBubbleAlpha = 0f;
109             mFrontAlpha = mDefaultScrimAlpha;
110         }
111     },
112 
113     /**
114      * Changing screen brightness from quick settings.
115      */
116     BRIGHTNESS_MIRROR {
117         @Override
prepare(ScrimState previousState)118         public void prepare(ScrimState previousState) {
119             mBehindAlpha = 0;
120             mFrontAlpha = 0;
121             mBubbleAlpha = 0;
122         }
123     },
124 
125     /**
126      * Always on display or screen off.
127      */
128     AOD {
129         @Override
prepare(ScrimState previousState)130         public void prepare(ScrimState previousState) {
131             final boolean alwaysOnEnabled = mDozeParameters.getAlwaysOn();
132             final boolean isDocked = mDockManager.isDocked();
133             mBlankScreen = mDisplayRequiresBlanking;
134 
135             mFrontTint = Color.BLACK;
136             mFrontAlpha = (alwaysOnEnabled || isDocked) ? mAodFrontScrimAlpha : 1f;
137 
138             mBehindTint = Color.BLACK;
139             mBehindAlpha = ScrimController.TRANSPARENT;
140 
141             mBubbleTint = Color.TRANSPARENT;
142             mBubbleAlpha = ScrimController.TRANSPARENT;
143 
144             mAnimationDuration = ScrimController.ANIMATION_DURATION_LONG;
145             // DisplayPowerManager may blank the screen for us,
146             // in this case we just need to set our state.
147             mAnimateChange = mDozeParameters.shouldControlScreenOff();
148         }
149 
150         @Override
getBehindAlpha()151         public float getBehindAlpha() {
152             return mWallpaperSupportsAmbientMode && !mHasBackdrop ? 0f : 1f;
153         }
154 
155         @Override
isLowPowerState()156         public boolean isLowPowerState() {
157             return true;
158         }
159     },
160 
161     /**
162      * When phone wakes up because you received a notification.
163      */
164     PULSING {
165         @Override
prepare(ScrimState previousState)166         public void prepare(ScrimState previousState) {
167             mFrontAlpha = mAodFrontScrimAlpha;
168             mBubbleAlpha = 0f;
169             mBehindTint = Color.BLACK;
170             mFrontTint = Color.BLACK;
171             mBlankScreen = mDisplayRequiresBlanking;
172             mAnimationDuration = mWakeLockScreenSensorActive
173                     ? ScrimController.ANIMATION_DURATION_LONG : ScrimController.ANIMATION_DURATION;
174 
175             // Wake sensor will show the wallpaper, let's fade from black. Otherwise it will
176             // feel like the screen is flashing if the wallpaper is light.
177             if (mWakeLockScreenSensorActive && previousState == AOD) {
178                 updateScrimColor(mScrimBehind, 1f /* alpha */, Color.BLACK);
179             }
180         }
181 
182         @Override
getBehindAlpha()183         public float getBehindAlpha() {
184             return mWakeLockScreenSensorActive ? ScrimController.WAKE_SENSOR_SCRIM_ALPHA
185                     : AOD.getBehindAlpha();
186         }
187     },
188 
189     /**
190      * Unlocked on top of an app (launcher or any other activity.)
191      */
192     UNLOCKED {
193         @Override
prepare(ScrimState previousState)194         public void prepare(ScrimState previousState) {
195             // State that UI will sync to.
196             mBehindAlpha = 0;
197             mFrontAlpha = 0;
198             mBubbleAlpha = 0;
199 
200             mAnimationDuration = mKeyguardFadingAway
201                     ? mKeyguardFadingAwayDuration
202                     : StatusBar.FADE_KEYGUARD_DURATION;
203 
204             mAnimateChange = !mLaunchingAffordanceWithPreview;
205 
206             mFrontTint = Color.TRANSPARENT;
207             mBehindTint = Color.TRANSPARENT;
208             mBubbleTint = Color.TRANSPARENT;
209             mBlankScreen = false;
210 
211             if (previousState == ScrimState.AOD) {
212                 // Set all scrims black, before they fade transparent.
213                 updateScrimColor(mScrimInFront, 1f /* alpha */, Color.BLACK /* tint */);
214                 updateScrimColor(mScrimBehind, 1f /* alpha */, Color.BLACK /* tint */);
215                 updateScrimColor(mScrimForBubble, 1f /* alpha */, Color.BLACK /* tint */);
216 
217                 // Scrims should still be black at the end of the transition.
218                 mFrontTint = Color.BLACK;
219                 mBehindTint = Color.BLACK;
220                 mBubbleTint = Color.BLACK;
221                 mBlankScreen = true;
222             }
223         }
224     },
225 
226     /**
227      * Unlocked with a bubble expanded.
228      */
229     BUBBLE_EXPANDED {
230         @Override
prepare(ScrimState previousState)231         public void prepare(ScrimState previousState) {
232             mFrontTint = Color.TRANSPARENT;
233             mBehindTint = Color.TRANSPARENT;
234             mBubbleTint = Color.TRANSPARENT;
235 
236             mFrontAlpha = 0f;
237             mBehindAlpha = mDefaultScrimAlpha;
238             mBubbleAlpha = ScrimController.BUBBLE_SCRIM_ALPHA;
239 
240             mAnimationDuration = ScrimController.ANIMATION_DURATION;
241             mBlankScreen = false;
242         }
243     };
244 
245     boolean mBlankScreen = false;
246     long mAnimationDuration = ScrimController.ANIMATION_DURATION;
247     int mFrontTint = Color.TRANSPARENT;
248     int mBehindTint = Color.TRANSPARENT;
249     int mBubbleTint = Color.TRANSPARENT;
250 
251     boolean mAnimateChange = true;
252     float mAodFrontScrimAlpha;
253     float mFrontAlpha;
254     float mBehindAlpha;
255     float mBubbleAlpha;
256 
257     float mScrimBehindAlphaKeyguard;
258     float mDefaultScrimAlpha;
259     ScrimView mScrimInFront;
260     ScrimView mScrimBehind;
261     ScrimView mScrimForBubble;
262 
263     DozeParameters mDozeParameters;
264     DockManager mDockManager;
265     boolean mDisplayRequiresBlanking;
266     boolean mWallpaperSupportsAmbientMode;
267     boolean mHasBackdrop;
268     boolean mLaunchingAffordanceWithPreview;
269     boolean mWakeLockScreenSensorActive;
270     boolean mKeyguardFadingAway;
271     long mKeyguardFadingAwayDuration;
272 
init(ScrimView scrimInFront, ScrimView scrimBehind, ScrimView scrimForBubble, DozeParameters dozeParameters, DockManager dockManager)273     public void init(ScrimView scrimInFront, ScrimView scrimBehind, ScrimView scrimForBubble,
274             DozeParameters dozeParameters, DockManager dockManager) {
275         mScrimInFront = scrimInFront;
276         mScrimBehind = scrimBehind;
277         mScrimForBubble = scrimForBubble;
278 
279         mDozeParameters = dozeParameters;
280         mDockManager = dockManager;
281         mDisplayRequiresBlanking = dozeParameters.getDisplayNeedsBlanking();
282     }
283 
284     /** Prepare state for transition. */
prepare(ScrimState previousState)285     public void prepare(ScrimState previousState) {
286     }
287 
getFrontAlpha()288     public float getFrontAlpha() {
289         return mFrontAlpha;
290     }
291 
getBehindAlpha()292     public float getBehindAlpha() {
293         return mBehindAlpha;
294     }
295 
getBubbleAlpha()296     public float getBubbleAlpha() {
297         return mBubbleAlpha;
298     }
299 
getFrontTint()300     public int getFrontTint() {
301         return mFrontTint;
302     }
303 
getBehindTint()304     public int getBehindTint() {
305         return mBehindTint;
306     }
307 
getBubbleTint()308     public int getBubbleTint() {
309         return mBubbleTint;
310     }
311 
getAnimationDuration()312     public long getAnimationDuration() {
313         return mAnimationDuration;
314     }
315 
getBlanksScreen()316     public boolean getBlanksScreen() {
317         return mBlankScreen;
318     }
319 
updateScrimColor(ScrimView scrim, float alpha, int tint)320     public void updateScrimColor(ScrimView scrim, float alpha, int tint) {
321         Trace.traceCounter(Trace.TRACE_TAG_APP,
322                 scrim == mScrimInFront ? "front_scrim_alpha" : "back_scrim_alpha",
323                 (int) (alpha * 255));
324 
325         Trace.traceCounter(Trace.TRACE_TAG_APP,
326                 scrim == mScrimInFront ? "front_scrim_tint" : "back_scrim_tint",
327                 Color.alpha(tint));
328 
329         scrim.setTint(tint);
330         scrim.setViewAlpha(alpha);
331     }
332 
getAnimateChange()333     public boolean getAnimateChange() {
334         return mAnimateChange;
335     }
336 
setAodFrontScrimAlpha(float aodFrontScrimAlpha)337     public void setAodFrontScrimAlpha(float aodFrontScrimAlpha) {
338         mAodFrontScrimAlpha = aodFrontScrimAlpha;
339     }
340 
setScrimBehindAlphaKeyguard(float scrimBehindAlphaKeyguard)341     public void setScrimBehindAlphaKeyguard(float scrimBehindAlphaKeyguard) {
342         mScrimBehindAlphaKeyguard = scrimBehindAlphaKeyguard;
343     }
344 
setDefaultScrimAlpha(float defaultScrimAlpha)345     public void setDefaultScrimAlpha(float defaultScrimAlpha) {
346         mDefaultScrimAlpha = defaultScrimAlpha;
347     }
348 
setWallpaperSupportsAmbientMode(boolean wallpaperSupportsAmbientMode)349     public void setWallpaperSupportsAmbientMode(boolean wallpaperSupportsAmbientMode) {
350         mWallpaperSupportsAmbientMode = wallpaperSupportsAmbientMode;
351     }
352 
setLaunchingAffordanceWithPreview(boolean launchingAffordanceWithPreview)353     public void setLaunchingAffordanceWithPreview(boolean launchingAffordanceWithPreview) {
354         mLaunchingAffordanceWithPreview = launchingAffordanceWithPreview;
355     }
356 
isLowPowerState()357     public boolean isLowPowerState() {
358         return false;
359     }
360 
setHasBackdrop(boolean hasBackdrop)361     public void setHasBackdrop(boolean hasBackdrop) {
362         mHasBackdrop = hasBackdrop;
363     }
364 
setWakeLockScreenSensorActive(boolean active)365     public void setWakeLockScreenSensorActive(boolean active) {
366         mWakeLockScreenSensorActive = active;
367     }
368 
setKeyguardFadingAway(boolean fadingAway, long duration)369     public void setKeyguardFadingAway(boolean fadingAway, long duration) {
370         mKeyguardFadingAway = fadingAway;
371         mKeyguardFadingAwayDuration = duration;
372     }
373 }