blob: f72d4119b50c1a68c4cce8c0a53c6ebdf3d74ee7 [file] [log] [blame]
Lucas Dupin9e3fa102017-11-08 17:16:55 -08001/*
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
17package com.android.systemui.statusbar.phone;
18
Lucas Dupin82aa1632017-12-13 00:13:57 -080019import static com.android.systemui.statusbar.phone.ScrimController.VISIBILITY_FULLY_OPAQUE;
20import static com.android.systemui.statusbar.phone.ScrimController.VISIBILITY_FULLY_TRANSPARENT;
21import static com.android.systemui.statusbar.phone.ScrimController.VISIBILITY_SEMI_TRANSPARENT;
22
23import static org.mockito.ArgumentMatchers.any;
24import static org.mockito.ArgumentMatchers.anyInt;
25import static org.mockito.ArgumentMatchers.anyLong;
Lucas Dupinee4c9b72019-02-18 17:04:58 -080026import static org.mockito.ArgumentMatchers.anyString;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080027import static org.mockito.Mockito.mock;
28import static org.mockito.Mockito.never;
Lucas Dupin82aa1632017-12-13 00:13:57 -080029import static org.mockito.Mockito.reset;
Lucas Dupin067136c2018-03-27 18:03:25 -070030import static org.mockito.Mockito.spy;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080031import static org.mockito.Mockito.verify;
Lucas Dupineea53b32017-12-18 13:47:14 -080032import static org.mockito.Mockito.verifyZeroInteractions;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080033import static org.mockito.Mockito.when;
34
35import android.animation.Animator;
Lucas Dupin80a3fcc2018-02-07 10:49:55 -080036import android.animation.ValueAnimator;
Lucas Dupin82aa1632017-12-13 00:13:57 -080037import android.app.AlarmManager;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080038import android.graphics.Color;
39import android.os.Handler;
40import android.os.Looper;
Lucas Dupin597dfaf2019-02-21 18:27:41 -080041import android.support.test.filters.FlakyTest;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080042import android.support.test.filters.SmallTest;
43import android.testing.AndroidTestingRunner;
44import android.testing.TestableLooper;
45import android.view.View;
46
shawnlin317db372018-04-09 19:49:48 +080047import com.android.internal.colorextraction.ColorExtractor.GradientColors;
Yohei Yukawa795f0102018-04-13 14:55:30 -070048import com.android.internal.util.function.TriConsumer;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080049import com.android.systemui.SysuiTestCase;
Lucas Dupin00be88f2019-01-03 17:50:52 -080050import com.android.systemui.doze.DozeLog;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080051import com.android.systemui.statusbar.ScrimView;
52import com.android.systemui.util.wakelock.WakeLock;
53import com.android.systemui.utils.os.FakeHandler;
54
55import org.junit.Assert;
56import org.junit.Before;
57import org.junit.Test;
58import org.junit.runner.RunWith;
59
Lucas Dupin1c327432019-01-03 13:37:53 -080060import java.util.Collections;
Lucas Dupin78949b82018-04-03 18:54:39 -070061import java.util.HashSet;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080062import java.util.function.Consumer;
63
64@RunWith(AndroidTestingRunner.class)
65@TestableLooper.RunWithLooper
66@SmallTest
67public class ScrimControllerTest extends SysuiTestCase {
68
69 private SynchronousScrimController mScrimController;
70 private ScrimView mScrimBehind;
71 private ScrimView mScrimInFront;
Yohei Yukawa795f0102018-04-13 14:55:30 -070072 private ScrimState mScrimState;
shawnlin317db372018-04-09 19:49:48 +080073 private float mScrimBehindAlpha;
74 private GradientColors mScrimInFrontColor;
Lucas Dupin82aa1632017-12-13 00:13:57 -080075 private int mScrimVisibility;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080076 private DozeParameters mDozeParamenters;
77 private WakeLock mWakeLock;
78 private boolean mAlwaysOnEnabled;
Lucas Dupin82aa1632017-12-13 00:13:57 -080079 private AlarmManager mAlarmManager;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080080
Yohei Yukawa795f0102018-04-13 14:55:30 -070081
Lucas Dupin9e3fa102017-11-08 17:16:55 -080082 @Before
83 public void setup() {
Lucas Dupin067136c2018-03-27 18:03:25 -070084 mScrimBehind = spy(new ScrimView(getContext()));
Lucas Dupin9e3fa102017-11-08 17:16:55 -080085 mScrimInFront = new ScrimView(getContext());
Lucas Dupin9e3fa102017-11-08 17:16:55 -080086 mWakeLock = mock(WakeLock.class);
Lucas Dupin82aa1632017-12-13 00:13:57 -080087 mAlarmManager = mock(AlarmManager.class);
Lucas Dupin9e3fa102017-11-08 17:16:55 -080088 mAlwaysOnEnabled = true;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080089 mDozeParamenters = mock(DozeParameters.class);
90 when(mDozeParamenters.getAlwaysOn()).thenAnswer(invocation -> mAlwaysOnEnabled);
Lucas Dupin43d0d732017-11-16 11:23:49 -080091 when(mDozeParamenters.getDisplayNeedsBlanking()).thenReturn(true);
shawnlin317db372018-04-09 19:49:48 +080092 mScrimController = new SynchronousScrimController(mScrimBehind, mScrimInFront,
Yohei Yukawa795f0102018-04-13 14:55:30 -070093 (scrimState, scrimBehindAlpha, scrimInFrontColor) -> {
94 mScrimState = scrimState;
95 mScrimBehindAlpha = scrimBehindAlpha;
96 mScrimInFrontColor = scrimInFrontColor;
97 },
98 visible -> mScrimVisibility = visible, mDozeParamenters, mAlarmManager);
Lucas Dupinf8463ee2018-06-11 16:18:15 -070099 mScrimController.setHasBackdrop(false);
TYM Tsaia71c8922019-01-07 15:57:53 +0800100 mScrimController.setWallpaperSupportsAmbientMode(false);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800101 }
102
103 @Test
104 public void initialState() {
105 Assert.assertEquals("ScrimController should start initialized",
106 mScrimController.getState(), ScrimState.UNINITIALIZED);
107 }
108
109 @Test
110 public void transitionToKeyguard() {
111 mScrimController.transitionTo(ScrimState.KEYGUARD);
112 mScrimController.finishAnimationsImmediately();
113 // Front scrim should be transparent
114 // Back scrim should be visible without tint
Lucas Dupin82aa1632017-12-13 00:13:57 -0800115 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800116 assertScrimTint(mScrimBehind, false /* tinted */);
117 }
118
119 @Test
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700120 public void transitionToAod_withRegularWallpaper() {
121 mScrimController.transitionTo(ScrimState.AOD);
122 mScrimController.finishAnimationsImmediately();
123 // Front scrim should be transparent
124 // Back scrim should be visible with tint
Lucas Dupin82aa1632017-12-13 00:13:57 -0800125 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700126 assertScrimTint(mScrimBehind, true /* tinted */);
127 assertScrimTint(mScrimInFront, true /* tinted */);
128 }
129
130 @Test
131 public void transitionToAod_withAodWallpaper() {
132 mScrimController.setWallpaperSupportsAmbientMode(true);
133 mScrimController.transitionTo(ScrimState.AOD);
134 mScrimController.finishAnimationsImmediately();
135 // Front scrim should be transparent
136 // Back scrim should be transparent
Lucas Dupin82aa1632017-12-13 00:13:57 -0800137 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
138
Lucas Dupin00be88f2019-01-03 17:50:52 -0800139 // Pulsing notification should conserve AOD wallpaper.
140 mScrimController.setPulseReason(DozeLog.PULSE_REASON_NOTIFICATION);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800141 mScrimController.transitionTo(ScrimState.PULSING);
142 mScrimController.finishAnimationsImmediately();
Lucas Dupin00be88f2019-01-03 17:50:52 -0800143 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700144 }
145
146 @Test
147 public void transitionToAod_withAodWallpaperAndLockScreenWallpaper() {
Lucas Dupinf8463ee2018-06-11 16:18:15 -0700148 mScrimController.setHasBackdrop(true);
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700149 mScrimController.setWallpaperSupportsAmbientMode(true);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800150 mScrimController.transitionTo(ScrimState.AOD);
151 mScrimController.finishAnimationsImmediately();
152 // Front scrim should be transparent
153 // Back scrim should be visible with tint
Lucas Dupin82aa1632017-12-13 00:13:57 -0800154 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800155 assertScrimTint(mScrimBehind, true /* tinted */);
156 assertScrimTint(mScrimInFront, true /* tinted */);
157 }
158
159 @Test
Lucas Dupin9bee5822018-07-09 14:32:53 -0700160 public void setHasBackdrop_withAodWallpaperAndAlbumArt() {
161 mScrimController.setWallpaperSupportsAmbientMode(true);
162 mScrimController.transitionTo(ScrimState.AOD);
163 mScrimController.finishAnimationsImmediately();
164 mScrimController.setHasBackdrop(true);
165 mScrimController.finishAnimationsImmediately();
166 // Front scrim should be transparent
167 // Back scrim should be visible with tint
168 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
169 assertScrimTint(mScrimBehind, true /* tinted */);
170 assertScrimTint(mScrimInFront, true /* tinted */);
171 }
172
173 @Test
Michael Wrightcae88752018-04-16 23:13:54 +0100174 public void transitionToAod_withFrontAlphaUpdates() {
175 // Assert that setting the AOD front scrim alpha doesn't take effect in a non-AOD state.
176 mScrimController.transitionTo(ScrimState.KEYGUARD);
177 mScrimController.setAodFrontScrimAlpha(0.5f);
178 mScrimController.finishAnimationsImmediately();
179 // Front scrim should be transparent
180 // Back scrim should be visible without tint
181 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
182
183 // ... but that it does take effect once we enter the AOD state.
184 mScrimController.transitionTo(ScrimState.AOD);
185 mScrimController.finishAnimationsImmediately();
186 // Front scrim should be semi-transparent
187 // Back scrim should be visible
188 assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
189
190 // ... and that if we set it while we're in AOD, it does take immediate effect.
191 mScrimController.setAodFrontScrimAlpha(1f);
192 assertScrimVisibility(VISIBILITY_FULLY_OPAQUE, VISIBILITY_FULLY_OPAQUE);
193
194 // ... and make sure we recall the previous front scrim alpha even if we transition away
195 // for a bit.
196 mScrimController.transitionTo(ScrimState.UNLOCKED);
197 mScrimController.transitionTo(ScrimState.AOD);
198 mScrimController.finishAnimationsImmediately();
199 assertScrimVisibility(VISIBILITY_FULLY_OPAQUE, VISIBILITY_FULLY_OPAQUE);
200
Lucas Dupin69bda602018-05-18 17:24:52 -0700201 // ... and alpha updates should be completely ignored if always_on is off.
202 // Passing it forward would mess up the wake-up transition.
203 mAlwaysOnEnabled = false;
204 mScrimController.transitionTo(ScrimState.UNLOCKED);
205 mScrimController.transitionTo(ScrimState.AOD);
206 mScrimController.finishAnimationsImmediately();
207 mScrimController.setAodFrontScrimAlpha(0.3f);
208 Assert.assertEquals(ScrimState.AOD.getFrontAlpha(), mScrimInFront.getViewAlpha(), 0.001f);
209 Assert.assertNotEquals(0.3f, mScrimInFront.getViewAlpha(), 0.001f);
210
Michael Wrightcae88752018-04-16 23:13:54 +0100211 // Reset value since enums are static.
212 mScrimController.setAodFrontScrimAlpha(0f);
213 }
214
215 @Test
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800216 public void transitionToPulsing() {
Lucas Dupin82aa1632017-12-13 00:13:57 -0800217 // Pre-condition
218 // Need to go to AoD first because PULSING doesn't change
219 // the back scrim opacity - otherwise it would hide AoD wallpapers.
220 mScrimController.setWallpaperSupportsAmbientMode(false);
221 mScrimController.transitionTo(ScrimState.AOD);
222 mScrimController.finishAnimationsImmediately();
223 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
224
Lucas Dupin00be88f2019-01-03 17:50:52 -0800225 mScrimController.setPulseReason(DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800226 mScrimController.transitionTo(ScrimState.PULSING);
227 mScrimController.finishAnimationsImmediately();
228 // Front scrim should be transparent
Lucas Dupinde64ee02018-12-21 14:45:12 -0800229 // Back scrim should be semi-transparent so the user can see the wallpaper
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800230 // Pulse callback should have been invoked
Lucas Dupinde64ee02018-12-21 14:45:12 -0800231 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
Lucas Dupin3d36dd82019-01-02 14:38:35 -0800232 assertScrimTint(mScrimBehind, false /* tinted */);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800233 }
234
235 @Test
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800236 public void transitionToKeyguardBouncer() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800237 mScrimController.transitionTo(ScrimState.BOUNCER);
238 mScrimController.finishAnimationsImmediately();
239 // Front scrim should be transparent
240 // Back scrim should be visible without tint
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800241 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
242 assertScrimTint(mScrimBehind, false /* tinted */);
243 }
244
245 @Test
246 public void transitionToBouncer() {
Lucas Dupin05726cd2018-03-13 14:00:24 -0700247 mScrimController.transitionTo(ScrimState.BOUNCER_SCRIMMED);
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800248 mScrimController.finishAnimationsImmediately();
249 // Front scrim should be transparent
250 // Back scrim should be visible without tint
251 assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800252 assertScrimTint(mScrimBehind, false /* tinted */);
253 }
254
Lucas Dupin597dfaf2019-02-21 18:27:41 -0800255 @FlakyTest(bugId = 124858892)
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800256 @Test
257 public void transitionToUnlocked() {
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800258 mScrimController.setPanelExpansion(0f);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800259 mScrimController.transitionTo(ScrimState.UNLOCKED);
260 mScrimController.finishAnimationsImmediately();
261 // Front scrim should be transparent
262 // Back scrim should be transparent
Lucas Dupin82aa1632017-12-13 00:13:57 -0800263 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800264 assertScrimTint(mScrimBehind, false /* tinted */);
265 assertScrimTint(mScrimInFront, false /* tinted */);
266
267 // Back scrim should be visible after start dragging
268 mScrimController.setPanelExpansion(0.5f);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800269 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800270 }
271
272 @Test
Mady Mellor0c333772018-11-06 18:05:54 -0800273 public void transitionToBubbleExpanded() {
274 mScrimController.transitionTo(ScrimState.BUBBLE_EXPANDED);
275 mScrimController.finishAnimationsImmediately();
276
277 // Front scrim should be transparent
278 Assert.assertEquals(ScrimController.VISIBILITY_FULLY_TRANSPARENT,
279 mScrimInFront.getViewAlpha(), 0.0f);
280 // Back scrim should be visible
281 Assert.assertEquals(ScrimController.GRADIENT_SCRIM_ALPHA_BUSY,
282 mScrimBehind.getViewAlpha(), 0.0f);
283 }
284
285 @Test
Yohei Yukawa795f0102018-04-13 14:55:30 -0700286 public void scrimStateCallback() {
287 mScrimController.transitionTo(ScrimState.UNLOCKED);
288 mScrimController.finishAnimationsImmediately();
289 Assert.assertEquals(mScrimState, ScrimState.UNLOCKED);
290
291 mScrimController.transitionTo(ScrimState.BOUNCER);
292 mScrimController.finishAnimationsImmediately();
293 Assert.assertEquals(mScrimState, ScrimState.BOUNCER);
294
295 mScrimController.transitionTo(ScrimState.BOUNCER_SCRIMMED);
296 mScrimController.finishAnimationsImmediately();
297 Assert.assertEquals(mScrimState, ScrimState.BOUNCER_SCRIMMED);
298 }
299
Lucas Dupin597dfaf2019-02-21 18:27:41 -0800300 @FlakyTest(bugId = 124858892)
Yohei Yukawa795f0102018-04-13 14:55:30 -0700301 @Test
shawnlin317db372018-04-09 19:49:48 +0800302 public void panelExpansion() {
303 mScrimController.setPanelExpansion(0f);
304 mScrimController.setPanelExpansion(0.5f);
305 mScrimController.transitionTo(ScrimState.UNLOCKED);
306 mScrimController.finishAnimationsImmediately();
307
308 reset(mScrimBehind);
309 mScrimController.setPanelExpansion(0f);
310 mScrimController.setPanelExpansion(1.0f);
311 mScrimController.onPreDraw();
312
313 Assert.assertEquals("Scrim alpha should change after setPanelExpansion",
314 mScrimBehindAlpha, mScrimBehind.getViewAlpha(), 0.01f);
315
316 mScrimController.setPanelExpansion(0f);
317 mScrimController.onPreDraw();
318
319 Assert.assertEquals("Scrim alpha should change after setPanelExpansion",
320 mScrimBehindAlpha, mScrimBehind.getViewAlpha(), 0.01f);
321 }
322
Lucas Dupin597dfaf2019-02-21 18:27:41 -0800323 @FlakyTest(bugId = 124858892)
shawnlin317db372018-04-09 19:49:48 +0800324 @Test
Lucas Dupin67f02632018-03-12 11:08:31 -0700325 public void panelExpansionAffectsAlpha() {
326 mScrimController.setPanelExpansion(0f);
327 mScrimController.setPanelExpansion(0.5f);
328 mScrimController.transitionTo(ScrimState.UNLOCKED);
329 mScrimController.finishAnimationsImmediately();
330
331 final float scrimAlpha = mScrimBehind.getViewAlpha();
Lucas Dupin067136c2018-03-27 18:03:25 -0700332 reset(mScrimBehind);
Lucas Dupin67f02632018-03-12 11:08:31 -0700333 mScrimController.setExpansionAffectsAlpha(false);
334 mScrimController.setPanelExpansion(0.8f);
Lucas Dupin067136c2018-03-27 18:03:25 -0700335 verifyZeroInteractions(mScrimBehind);
Lucas Dupin67f02632018-03-12 11:08:31 -0700336 Assert.assertEquals("Scrim opacity shouldn't change when setExpansionAffectsAlpha "
337 + "is false", scrimAlpha, mScrimBehind.getViewAlpha(), 0.01f);
338
339 mScrimController.setExpansionAffectsAlpha(true);
340 mScrimController.setPanelExpansion(0.1f);
341 Assert.assertNotEquals("Scrim opacity should change when setExpansionAffectsAlpha "
342 + "is true", scrimAlpha, mScrimBehind.getViewAlpha(), 0.01f);
343 }
344
345 @Test
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800346 public void transitionToUnlockedFromAod() {
347 // Simulate unlock with fingerprint
348 mScrimController.transitionTo(ScrimState.AOD);
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800349 mScrimController.setPanelExpansion(0f);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800350 mScrimController.finishAnimationsImmediately();
351 mScrimController.transitionTo(ScrimState.UNLOCKED);
352 // Immediately tinted after the transition starts
353 assertScrimTint(mScrimInFront, true /* tinted */);
354 assertScrimTint(mScrimBehind, true /* tinted */);
355 mScrimController.finishAnimationsImmediately();
356 // Front scrim should be transparent
357 // Back scrim should be transparent
358 // Neither scrims should be tinted anymore after the animation.
Lucas Dupin82aa1632017-12-13 00:13:57 -0800359 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800360 assertScrimTint(mScrimInFront, false /* tinted */);
361 assertScrimTint(mScrimBehind, false /* tinted */);
362 }
363
364 @Test
Lucas Dupinea0116e2018-04-05 10:09:29 -0700365 public void scrimBlanksBeforeLeavingAod() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800366 // Simulate unlock with fingerprint
367 mScrimController.transitionTo(ScrimState.AOD);
368 mScrimController.finishAnimationsImmediately();
369 mScrimController.transitionTo(ScrimState.UNLOCKED,
370 new ScrimController.Callback() {
371 @Override
372 public void onDisplayBlanked() {
373 // Front scrim should be black in the middle of the transition
374 Assert.assertTrue("Scrim should be visible during transition. Alpha: "
375 + mScrimInFront.getViewAlpha(), mScrimInFront.getViewAlpha() > 0);
376 assertScrimTint(mScrimInFront, true /* tinted */);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800377 Assert.assertSame("Scrim should be visible during transition.",
378 mScrimVisibility, VISIBILITY_FULLY_OPAQUE);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800379 }
380 });
381 mScrimController.finishAnimationsImmediately();
382 }
383
384 @Test
Lucas Dupineb840ea2018-06-01 00:28:58 -0700385 public void scrimBlanksWhenUnlockingFromPulse() {
386 boolean[] blanked = {false};
387 // Simulate unlock with fingerprint
388 mScrimController.transitionTo(ScrimState.PULSING);
389 mScrimController.finishAnimationsImmediately();
390 mScrimController.transitionTo(ScrimState.UNLOCKED,
391 new ScrimController.Callback() {
392 @Override
393 public void onDisplayBlanked() {
394 blanked[0] = true;
395 }
396 });
397 mScrimController.finishAnimationsImmediately();
398 Assert.assertTrue("Scrim should blank when unlocking from pulse.", blanked[0]);
399 }
400
401 @Test
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800402 public void testScrimCallback() {
403 int[] callOrder = {0, 0, 0};
404 int[] currentCall = {0};
405 mScrimController.transitionTo(ScrimState.AOD, new ScrimController.Callback() {
406 @Override
407 public void onStart() {
408 callOrder[0] = ++currentCall[0];
409 }
410
411 @Override
412 public void onDisplayBlanked() {
413 callOrder[1] = ++currentCall[0];
414 }
415
416 @Override
417 public void onFinished() {
418 callOrder[2] = ++currentCall[0];
419 }
420 });
421 mScrimController.finishAnimationsImmediately();
422 Assert.assertEquals("onStart called in wrong order", 1, callOrder[0]);
423 Assert.assertEquals("onDisplayBlanked called in wrong order", 2, callOrder[1]);
424 Assert.assertEquals("onFinished called in wrong order", 3, callOrder[2]);
425 }
426
427 @Test
428 public void testScrimCallbacksWithoutAmbientDisplay() {
429 mAlwaysOnEnabled = false;
430 testScrimCallback();
431 }
432
433 @Test
434 public void testScrimCallbackCancelled() {
435 boolean[] cancelledCalled = {false};
436 mScrimController.transitionTo(ScrimState.AOD, new ScrimController.Callback() {
437 @Override
438 public void onCancelled() {
439 cancelledCalled[0] = true;
440 }
441 });
442 mScrimController.transitionTo(ScrimState.PULSING);
443 Assert.assertTrue("onCancelled should have been called", cancelledCalled[0]);
444 }
445
446 @Test
Lucas Dupineea53b32017-12-18 13:47:14 -0800447 public void testHoldsWakeLock_whenAOD() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800448 mScrimController.transitionTo(ScrimState.AOD);
Lucas Dupinee4c9b72019-02-18 17:04:58 -0800449 verify(mWakeLock).acquire(anyString());
450 verify(mWakeLock, never()).release(anyString());
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800451 mScrimController.finishAnimationsImmediately();
Lucas Dupinee4c9b72019-02-18 17:04:58 -0800452 verify(mWakeLock).release(anyString());
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800453 }
454
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800455 @Test
Lucas Dupineea53b32017-12-18 13:47:14 -0800456 public void testDoesNotHoldWakeLock_whenUnlocking() {
457 mScrimController.transitionTo(ScrimState.UNLOCKED);
458 mScrimController.finishAnimationsImmediately();
459 verifyZeroInteractions(mWakeLock);
460 }
461
462 @Test
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800463 public void testCallbackInvokedOnSameStateTransition() {
464 mScrimController.transitionTo(ScrimState.UNLOCKED);
465 mScrimController.finishAnimationsImmediately();
466 ScrimController.Callback callback = mock(ScrimController.Callback.class);
467 mScrimController.transitionTo(ScrimState.UNLOCKED, callback);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800468 verify(callback).onFinished();
469 }
470
471 @Test
472 public void testHoldsAodWallpaperAnimationLock() {
473 // Pre-conditions
474 mScrimController.transitionTo(ScrimState.AOD);
475 mScrimController.finishAnimationsImmediately();
476 reset(mWakeLock);
477
478 mScrimController.onHideWallpaperTimeout();
Lucas Dupinee4c9b72019-02-18 17:04:58 -0800479 verify(mWakeLock).acquire(anyString());
480 verify(mWakeLock, never()).release(anyString());
Lucas Dupin82aa1632017-12-13 00:13:57 -0800481 mScrimController.finishAnimationsImmediately();
Lucas Dupinee4c9b72019-02-18 17:04:58 -0800482 verify(mWakeLock).release(anyString());
Lucas Dupin82aa1632017-12-13 00:13:57 -0800483 }
484
485 @Test
TYM Tsaia71c8922019-01-07 15:57:53 +0800486 public void testHoldsPulsingWallpaperAnimationLock() {
487 // Pre-conditions
Lucas Dupin00be88f2019-01-03 17:50:52 -0800488 mScrimController.setPulseReason(DozeLog.PULSE_REASON_NOTIFICATION);
489 mScrimController.transitionTo(ScrimState.PULSING);
TYM Tsaia71c8922019-01-07 15:57:53 +0800490 mScrimController.finishAnimationsImmediately();
491 reset(mWakeLock);
492
493 mScrimController.onHideWallpaperTimeout();
Lucas Dupinee4c9b72019-02-18 17:04:58 -0800494 verify(mWakeLock).acquire(anyString());
495 verify(mWakeLock, never()).release(anyString());
TYM Tsaia71c8922019-01-07 15:57:53 +0800496 mScrimController.finishAnimationsImmediately();
Lucas Dupinee4c9b72019-02-18 17:04:58 -0800497 verify(mWakeLock).release(anyString());
TYM Tsaia71c8922019-01-07 15:57:53 +0800498 }
499
500 @Test
Lucas Dupin16cfe452018-02-08 13:14:50 -0800501 public void testWillHideAodWallpaper() {
Lucas Dupin82aa1632017-12-13 00:13:57 -0800502 mScrimController.setWallpaperSupportsAmbientMode(true);
503 mScrimController.transitionTo(ScrimState.AOD);
504 verify(mAlarmManager).setExact(anyInt(), anyLong(), any(), any(), any());
505 mScrimController.transitionTo(ScrimState.KEYGUARD);
506 verify(mAlarmManager).cancel(any(AlarmManager.OnAlarmListener.class));
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800507 }
508
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800509 @Test
Lucas Dupin00be88f2019-01-03 17:50:52 -0800510 public void testWillHidePulsingWallpaper_whenNotification() {
511 mScrimController.setWallpaperSupportsAmbientMode(false);
512 mScrimController.transitionTo(ScrimState.AOD);
513 mScrimController.finishAnimationsImmediately();
514 mScrimController.setPulseReason(DozeLog.PULSE_REASON_NOTIFICATION);
TYM Tsaia71c8922019-01-07 15:57:53 +0800515 mScrimController.transitionTo(ScrimState.PULSING);
Lucas Dupin00be88f2019-01-03 17:50:52 -0800516 mScrimController.finishAnimationsImmediately();
517 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
518 assertScrimTint(mScrimBehind, true);
519 }
520
521 @Test
522 public void testWillHidePulsingWallpaper_whenDocking() {
523 mScrimController.setWallpaperSupportsAmbientMode(false);
524 mScrimController.transitionTo(ScrimState.AOD);
525 mScrimController.finishAnimationsImmediately();
526 mScrimController.setPulseReason(DozeLog.PULSE_REASON_DOCKING);
527 mScrimController.transitionTo(ScrimState.PULSING);
528 mScrimController.finishAnimationsImmediately();
529 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
530 assertScrimTint(mScrimBehind, true);
TYM Tsaia71c8922019-01-07 15:57:53 +0800531 }
532
533 @Test
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800534 public void testConservesExpansionOpacityAfterTransition() {
535 mScrimController.transitionTo(ScrimState.UNLOCKED);
536 mScrimController.setPanelExpansion(0.5f);
537 mScrimController.finishAnimationsImmediately();
538
539 final float expandedAlpha = mScrimBehind.getViewAlpha();
540
541 mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR);
542 mScrimController.finishAnimationsImmediately();
543 mScrimController.transitionTo(ScrimState.UNLOCKED);
544 mScrimController.finishAnimationsImmediately();
545
546 Assert.assertEquals("Scrim expansion opacity wasn't conserved when transitioning back",
547 expandedAlpha, mScrimBehind.getViewAlpha(), 0.01f);
548 }
549
550 @Test
551 public void cancelsOldAnimationBeforeBlanking() {
552 mScrimController.transitionTo(ScrimState.AOD);
553 mScrimController.finishAnimationsImmediately();
554 // Consume whatever value we had before
555 mScrimController.wasAnimationJustCancelled();
556
557 mScrimController.transitionTo(ScrimState.KEYGUARD);
558 mScrimController.finishAnimationsImmediately();
559 Assert.assertTrue(mScrimController.wasAnimationJustCancelled());
560 }
561
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800562 @Test
Lucas Dupin38962d72018-03-14 12:41:39 -0700563 public void testScrimFocus() {
564 mScrimController.transitionTo(ScrimState.AOD);
565 Assert.assertFalse("Should not be focusable on AOD", mScrimBehind.isFocusable());
566 Assert.assertFalse("Should not be focusable on AOD", mScrimInFront.isFocusable());
567
568 mScrimController.transitionTo(ScrimState.KEYGUARD);
569 Assert.assertTrue("Should be focusable on keyguard", mScrimBehind.isFocusable());
570 Assert.assertTrue("Should be focusable on keyguard", mScrimInFront.isFocusable());
571 }
572
Lucas Dupind5107302018-03-19 15:30:29 -0700573 @Test
574 public void testHidesShowWhenLockedActivity() {
575 mScrimController.setWallpaperSupportsAmbientMode(true);
576 mScrimController.setKeyguardOccluded(true);
577 mScrimController.transitionTo(ScrimState.AOD);
578 mScrimController.finishAnimationsImmediately();
579 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
580
581 mScrimController.transitionTo(ScrimState.PULSING);
582 mScrimController.finishAnimationsImmediately();
583 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
584 }
585
Lucas Dupin78949b82018-04-03 18:54:39 -0700586 @Test
Lucas Dupin63d72172018-06-06 11:42:55 -0700587 public void testHidesShowWhenLockedActivity_whenAlreadyInAod() {
588 mScrimController.setWallpaperSupportsAmbientMode(true);
589 mScrimController.transitionTo(ScrimState.AOD);
590 mScrimController.finishAnimationsImmediately();
591 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
592
593 mScrimController.setKeyguardOccluded(true);
594 mScrimController.finishAnimationsImmediately();
595 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
596 }
597
598 @Test
Lucas Dupin78949b82018-04-03 18:54:39 -0700599 public void testEatsTouchEvent() {
600 HashSet<ScrimState> eatsTouches =
Lucas Dupin1c327432019-01-03 13:37:53 -0800601 new HashSet<>(Collections.singletonList(ScrimState.AOD));
Lucas Dupin78949b82018-04-03 18:54:39 -0700602 for (ScrimState state : ScrimState.values()) {
603 if (state == ScrimState.UNINITIALIZED) {
604 continue;
605 }
606 mScrimController.transitionTo(state);
607 mScrimController.finishAnimationsImmediately();
608 Assert.assertEquals("Should be clickable unless AOD or PULSING, was: " + state,
609 mScrimBehind.getViewAlpha() != 0 && !eatsTouches.contains(state),
610 mScrimBehind.isClickable());
611 }
612 }
613
Lucas Dupinea0116e2018-04-05 10:09:29 -0700614 @Test
615 public void testAnimatesTransitionToAod() {
616 when(mDozeParamenters.shouldControlScreenOff()).thenReturn(false);
617 ScrimState.AOD.prepare(ScrimState.KEYGUARD);
618 Assert.assertFalse("No animation when ColorFade kicks in",
619 ScrimState.AOD.getAnimateChange());
620
621 reset(mDozeParamenters);
622 when(mDozeParamenters.shouldControlScreenOff()).thenReturn(true);
623 ScrimState.AOD.prepare(ScrimState.KEYGUARD);
624 Assert.assertTrue("Animate scrims when ColorFade won't be triggered",
625 ScrimState.AOD.getAnimateChange());
626 }
627
Lucas Dupin373356b2018-04-07 10:50:25 -0700628 @Test
629 public void testViewsDontHaveFocusHighlight() {
630 Assert.assertFalse("Scrim shouldn't have focus highlight",
631 mScrimInFront.getDefaultFocusHighlightEnabled());
632 Assert.assertFalse("Scrim shouldn't have focus highlight",
633 mScrimBehind.getDefaultFocusHighlightEnabled());
634 }
635
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800636 private void assertScrimTint(ScrimView scrimView, boolean tinted) {
637 final boolean viewIsTinted = scrimView.getTint() != Color.TRANSPARENT;
638 final String name = scrimView == mScrimInFront ? "front" : "back";
639 Assert.assertEquals("Tint test failed at state " + mScrimController.getState()
640 +" with scrim: " + name + " and tint: " + Integer.toHexString(scrimView.getTint()),
641 tinted, viewIsTinted);
642 }
643
Lucas Dupin82aa1632017-12-13 00:13:57 -0800644 private void assertScrimVisibility(int inFront, int behind) {
645 boolean inFrontVisible = inFront != ScrimController.VISIBILITY_FULLY_TRANSPARENT;
646 boolean behindVisible = behind != ScrimController.VISIBILITY_FULLY_TRANSPARENT;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800647 Assert.assertEquals("Unexpected front scrim visibility. Alpha is "
Lucas Dupin82aa1632017-12-13 00:13:57 -0800648 + mScrimInFront.getViewAlpha(), inFrontVisible, mScrimInFront.getViewAlpha() > 0);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800649 Assert.assertEquals("Unexpected back scrim visibility. Alpha is "
Lucas Dupin82aa1632017-12-13 00:13:57 -0800650 + mScrimBehind.getViewAlpha(), behindVisible, mScrimBehind.getViewAlpha() > 0);
651
652 final int visibility;
653 if (inFront == VISIBILITY_FULLY_OPAQUE || behind == VISIBILITY_FULLY_OPAQUE) {
654 visibility = VISIBILITY_FULLY_OPAQUE;
655 } else if (inFront > VISIBILITY_FULLY_TRANSPARENT || behind > VISIBILITY_FULLY_TRANSPARENT) {
656 visibility = VISIBILITY_SEMI_TRANSPARENT;
657 } else {
658 visibility = VISIBILITY_FULLY_TRANSPARENT;
659 }
660 Assert.assertEquals("Invalid visibility.", visibility, mScrimVisibility);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800661 }
662
663 /**
664 * Special version of ScrimController where animations have 0 duration for test purposes.
665 */
666 private class SynchronousScrimController extends ScrimController {
667
668 private FakeHandler mHandler;
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800669 private boolean mAnimationCancelled;
Lucas Dupin16cfe452018-02-08 13:14:50 -0800670 boolean mOnPreDrawCalled;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800671
shawnlin317db372018-04-09 19:49:48 +0800672 SynchronousScrimController(ScrimView scrimBehind, ScrimView scrimInFront,
Yohei Yukawa795f0102018-04-13 14:55:30 -0700673 TriConsumer<ScrimState, Float, GradientColors> scrimStateListener,
Lucas Dupin82aa1632017-12-13 00:13:57 -0800674 Consumer<Integer> scrimVisibleListener, DozeParameters dozeParameters,
675 AlarmManager alarmManager) {
Yohei Yukawa795f0102018-04-13 14:55:30 -0700676 super(scrimBehind, scrimInFront, scrimStateListener, scrimVisibleListener,
677 dozeParameters, alarmManager);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800678 mHandler = new FakeHandler(Looper.myLooper());
679 }
680
Lucas Dupin16cfe452018-02-08 13:14:50 -0800681 @Override
682 public boolean onPreDraw() {
683 mOnPreDrawCalled = true;
684 return super.onPreDraw();
685 }
686
Lucas Dupin3503c5f2018-03-02 19:04:00 -0800687 void finishAnimationsImmediately() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800688 boolean[] animationFinished = {false};
689 setOnAnimationFinished(()-> animationFinished[0] = true);
690
691 // Execute code that will trigger animations.
692 onPreDraw();
693
694 // Force finish screen blanking.
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800695 mHandler.dispatchQueuedMessages();
696 // Force finish all animations.
697 endAnimation(mScrimBehind, TAG_KEY_ANIM);
698 endAnimation(mScrimInFront, TAG_KEY_ANIM);
699
700 if (!animationFinished[0]) {
701 throw new IllegalStateException("Animation never finished");
702 }
703 }
704
Lucas Dupin3503c5f2018-03-02 19:04:00 -0800705 boolean wasAnimationJustCancelled() {
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800706 final boolean wasCancelled = mAnimationCancelled;
707 mAnimationCancelled = false;
708 return wasCancelled;
709 }
710
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800711 private void endAnimation(View scrimView, int tag) {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800712 Animator animator = (Animator) scrimView.getTag(tag);
713 if (animator != null) {
714 animator.end();
715 }
716 }
717
718 @Override
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800719 protected void cancelAnimator(ValueAnimator previousAnimator) {
720 super.cancelAnimator(previousAnimator);
721 mAnimationCancelled = true;
722 }
723
724 @Override
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800725 protected Handler getHandler() {
726 return mHandler;
727 }
728
729 @Override
730 protected WakeLock createWakeLock() {
731 return mWakeLock;
732 }
Lucas Dupin8c7cb022018-02-05 10:49:03 -0800733
734 /**
735 * Do not wait for a frame since we're in a test environment.
736 * @param callback What to execute.
737 */
738 @Override
Lucas Dupin0791d972018-03-26 13:32:16 -0700739 protected void doOnTheNextFrame(Runnable callback) {
740 callback.run();
Lucas Dupin8c7cb022018-02-05 10:49:03 -0800741 }
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800742 }
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800743}