blob: bfa469eba99fa5f11df67d98fafab6742fc52845 [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 Dupin9e3fa102017-11-08 17:16:55 -080026import static org.mockito.Mockito.mock;
27import static org.mockito.Mockito.never;
Lucas Dupin82aa1632017-12-13 00:13:57 -080028import static org.mockito.Mockito.reset;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080029import static org.mockito.Mockito.verify;
Lucas Dupineea53b32017-12-18 13:47:14 -080030import static org.mockito.Mockito.verifyZeroInteractions;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080031import static org.mockito.Mockito.when;
32
33import android.animation.Animator;
Lucas Dupin80a3fcc2018-02-07 10:49:55 -080034import android.animation.ValueAnimator;
Lucas Dupin82aa1632017-12-13 00:13:57 -080035import android.app.AlarmManager;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080036import android.graphics.Color;
37import android.os.Handler;
38import android.os.Looper;
39import android.support.test.filters.SmallTest;
40import android.testing.AndroidTestingRunner;
41import android.testing.TestableLooper;
Lucas Dupin8c7cb022018-02-05 10:49:03 -080042import android.view.Choreographer;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080043import android.view.View;
44
Lucas Dupin7517b5d2017-08-22 12:51:25 -070045import com.android.keyguard.KeyguardUpdateMonitor;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080046import com.android.systemui.SysuiTestCase;
47import com.android.systemui.statusbar.ScrimView;
48import com.android.systemui.util.wakelock.WakeLock;
49import com.android.systemui.utils.os.FakeHandler;
50
51import org.junit.Assert;
52import org.junit.Before;
53import org.junit.Test;
54import org.junit.runner.RunWith;
55
56import java.util.function.Consumer;
57
58@RunWith(AndroidTestingRunner.class)
59@TestableLooper.RunWithLooper
60@SmallTest
61public class ScrimControllerTest extends SysuiTestCase {
62
63 private SynchronousScrimController mScrimController;
64 private ScrimView mScrimBehind;
65 private ScrimView mScrimInFront;
66 private View mHeadsUpScrim;
Lucas Dupin82aa1632017-12-13 00:13:57 -080067 private Consumer<Integer> mScrimVisibilityCallback;
68 private int mScrimVisibility;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080069 private LightBarController mLightBarController;
70 private DozeParameters mDozeParamenters;
71 private WakeLock mWakeLock;
72 private boolean mAlwaysOnEnabled;
Lucas Dupin82aa1632017-12-13 00:13:57 -080073 private AlarmManager mAlarmManager;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080074
75 @Before
76 public void setup() {
77 mLightBarController = mock(LightBarController.class);
78 mScrimBehind = new ScrimView(getContext());
79 mScrimInFront = new ScrimView(getContext());
Lucas Dupin3daf3b02018-02-27 17:23:41 -080080 mHeadsUpScrim = new View(getContext());
Lucas Dupin9e3fa102017-11-08 17:16:55 -080081 mWakeLock = mock(WakeLock.class);
Lucas Dupin82aa1632017-12-13 00:13:57 -080082 mAlarmManager = mock(AlarmManager.class);
Lucas Dupin9e3fa102017-11-08 17:16:55 -080083 mAlwaysOnEnabled = true;
Lucas Dupin82aa1632017-12-13 00:13:57 -080084 mScrimVisibilityCallback = (Integer visible) -> mScrimVisibility = visible;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080085 mDozeParamenters = mock(DozeParameters.class);
86 when(mDozeParamenters.getAlwaysOn()).thenAnswer(invocation -> mAlwaysOnEnabled);
Lucas Dupin43d0d732017-11-16 11:23:49 -080087 when(mDozeParamenters.getDisplayNeedsBlanking()).thenReturn(true);
Lucas Dupin9e3fa102017-11-08 17:16:55 -080088 mScrimController = new SynchronousScrimController(mLightBarController, mScrimBehind,
Lucas Dupin82aa1632017-12-13 00:13:57 -080089 mScrimInFront, mHeadsUpScrim, mScrimVisibilityCallback, mDozeParamenters,
90 mAlarmManager);
Lucas Dupin9e3fa102017-11-08 17:16:55 -080091 }
92
93 @Test
94 public void initialState() {
95 Assert.assertEquals("ScrimController should start initialized",
96 mScrimController.getState(), ScrimState.UNINITIALIZED);
97 }
98
99 @Test
100 public void transitionToKeyguard() {
101 mScrimController.transitionTo(ScrimState.KEYGUARD);
102 mScrimController.finishAnimationsImmediately();
103 // Front scrim should be transparent
104 // Back scrim should be visible without tint
Lucas Dupin82aa1632017-12-13 00:13:57 -0800105 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800106 assertScrimTint(mScrimBehind, false /* tinted */);
107 }
108
109 @Test
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700110 public void transitionToAod_withRegularWallpaper() {
111 mScrimController.transitionTo(ScrimState.AOD);
112 mScrimController.finishAnimationsImmediately();
113 // Front scrim should be transparent
114 // Back scrim should be visible with tint
Lucas Dupin82aa1632017-12-13 00:13:57 -0800115 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700116 assertScrimTint(mScrimBehind, true /* tinted */);
117 assertScrimTint(mScrimInFront, true /* tinted */);
118 }
119
120 @Test
121 public void transitionToAod_withAodWallpaper() {
122 mScrimController.setWallpaperSupportsAmbientMode(true);
123 mScrimController.transitionTo(ScrimState.AOD);
124 mScrimController.finishAnimationsImmediately();
125 // Front scrim should be transparent
126 // Back scrim should be transparent
Lucas Dupin82aa1632017-12-13 00:13:57 -0800127 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
128
129 // Move on to PULSING and check if the back scrim is still transparent
130 mScrimController.transitionTo(ScrimState.PULSING);
131 mScrimController.finishAnimationsImmediately();
132 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700133 }
134
135 @Test
136 public void transitionToAod_withAodWallpaperAndLockScreenWallpaper() {
137 ScrimState.AOD.mKeyguardUpdateMonitor = new KeyguardUpdateMonitor(getContext()) {
138 @Override
139 public boolean hasLockscreenWallpaper() {
140 return true;
141 }
142 };
143 mScrimController.setWallpaperSupportsAmbientMode(true);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800144 mScrimController.transitionTo(ScrimState.AOD);
145 mScrimController.finishAnimationsImmediately();
146 // Front scrim should be transparent
147 // Back scrim should be visible with tint
Lucas Dupin82aa1632017-12-13 00:13:57 -0800148 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800149 assertScrimTint(mScrimBehind, true /* tinted */);
150 assertScrimTint(mScrimInFront, true /* tinted */);
151 }
152
153 @Test
154 public void transitionToPulsing() {
Lucas Dupin82aa1632017-12-13 00:13:57 -0800155 // Pre-condition
156 // Need to go to AoD first because PULSING doesn't change
157 // the back scrim opacity - otherwise it would hide AoD wallpapers.
158 mScrimController.setWallpaperSupportsAmbientMode(false);
159 mScrimController.transitionTo(ScrimState.AOD);
160 mScrimController.finishAnimationsImmediately();
161 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
162
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800163 mScrimController.transitionTo(ScrimState.PULSING);
164 mScrimController.finishAnimationsImmediately();
165 // Front scrim should be transparent
166 // Back scrim should be visible with tint
167 // Pulse callback should have been invoked
Lucas Dupin82aa1632017-12-13 00:13:57 -0800168 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800169 assertScrimTint(mScrimBehind, true /* tinted */);
170 }
171
172 @Test
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800173 public void transitionToKeyguardBouncer() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800174 mScrimController.transitionTo(ScrimState.BOUNCER);
175 mScrimController.finishAnimationsImmediately();
176 // Front scrim should be transparent
177 // Back scrim should be visible without tint
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800178 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
179 assertScrimTint(mScrimBehind, false /* tinted */);
180 }
181
182 @Test
183 public void transitionToBouncer() {
184 mScrimController.transitionTo(ScrimState.BOUNCER_OCCLUDED);
185 mScrimController.finishAnimationsImmediately();
186 // Front scrim should be transparent
187 // Back scrim should be visible without tint
188 assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800189 assertScrimTint(mScrimBehind, false /* tinted */);
190 }
191
192 @Test
193 public void transitionToUnlocked() {
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800194 mScrimController.setPanelExpansion(0f);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800195 mScrimController.transitionTo(ScrimState.UNLOCKED);
196 mScrimController.finishAnimationsImmediately();
197 // Front scrim should be transparent
198 // Back scrim should be transparent
Lucas Dupin82aa1632017-12-13 00:13:57 -0800199 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800200 assertScrimTint(mScrimBehind, false /* tinted */);
201 assertScrimTint(mScrimInFront, false /* tinted */);
202
203 // Back scrim should be visible after start dragging
204 mScrimController.setPanelExpansion(0.5f);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800205 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800206 }
207
208 @Test
209 public void transitionToUnlockedFromAod() {
210 // Simulate unlock with fingerprint
211 mScrimController.transitionTo(ScrimState.AOD);
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800212 mScrimController.setPanelExpansion(0f);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800213 mScrimController.finishAnimationsImmediately();
214 mScrimController.transitionTo(ScrimState.UNLOCKED);
215 // Immediately tinted after the transition starts
216 assertScrimTint(mScrimInFront, true /* tinted */);
217 assertScrimTint(mScrimBehind, true /* tinted */);
218 mScrimController.finishAnimationsImmediately();
219 // Front scrim should be transparent
220 // Back scrim should be transparent
221 // Neither scrims should be tinted anymore after the animation.
Lucas Dupin82aa1632017-12-13 00:13:57 -0800222 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800223 assertScrimTint(mScrimInFront, false /* tinted */);
224 assertScrimTint(mScrimBehind, false /* tinted */);
225 }
226
227 @Test
228 public void scrimBlanksBeforeLeavingAoD() {
229 // Simulate unlock with fingerprint
230 mScrimController.transitionTo(ScrimState.AOD);
231 mScrimController.finishAnimationsImmediately();
232 mScrimController.transitionTo(ScrimState.UNLOCKED,
233 new ScrimController.Callback() {
234 @Override
235 public void onDisplayBlanked() {
236 // Front scrim should be black in the middle of the transition
237 Assert.assertTrue("Scrim should be visible during transition. Alpha: "
238 + mScrimInFront.getViewAlpha(), mScrimInFront.getViewAlpha() > 0);
239 assertScrimTint(mScrimInFront, true /* tinted */);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800240 Assert.assertSame("Scrim should be visible during transition.",
241 mScrimVisibility, VISIBILITY_FULLY_OPAQUE);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800242 }
243 });
244 mScrimController.finishAnimationsImmediately();
245 }
246
247 @Test
248 public void testScrimCallback() {
249 int[] callOrder = {0, 0, 0};
250 int[] currentCall = {0};
251 mScrimController.transitionTo(ScrimState.AOD, new ScrimController.Callback() {
252 @Override
253 public void onStart() {
254 callOrder[0] = ++currentCall[0];
255 }
256
257 @Override
258 public void onDisplayBlanked() {
259 callOrder[1] = ++currentCall[0];
260 }
261
262 @Override
263 public void onFinished() {
264 callOrder[2] = ++currentCall[0];
265 }
266 });
267 mScrimController.finishAnimationsImmediately();
268 Assert.assertEquals("onStart called in wrong order", 1, callOrder[0]);
269 Assert.assertEquals("onDisplayBlanked called in wrong order", 2, callOrder[1]);
270 Assert.assertEquals("onFinished called in wrong order", 3, callOrder[2]);
271 }
272
273 @Test
274 public void testScrimCallbacksWithoutAmbientDisplay() {
275 mAlwaysOnEnabled = false;
276 testScrimCallback();
277 }
278
279 @Test
280 public void testScrimCallbackCancelled() {
281 boolean[] cancelledCalled = {false};
282 mScrimController.transitionTo(ScrimState.AOD, new ScrimController.Callback() {
283 @Override
284 public void onCancelled() {
285 cancelledCalled[0] = true;
286 }
287 });
288 mScrimController.transitionTo(ScrimState.PULSING);
289 Assert.assertTrue("onCancelled should have been called", cancelledCalled[0]);
290 }
291
292 @Test
Lucas Dupineea53b32017-12-18 13:47:14 -0800293 public void testHoldsWakeLock_whenAOD() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800294 mScrimController.transitionTo(ScrimState.AOD);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800295 verify(mWakeLock).acquire();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800296 verify(mWakeLock, never()).release();
297 mScrimController.finishAnimationsImmediately();
Lucas Dupin82aa1632017-12-13 00:13:57 -0800298 verify(mWakeLock).release();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800299 }
300
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800301 @Test
Lucas Dupineea53b32017-12-18 13:47:14 -0800302 public void testDoesNotHoldWakeLock_whenUnlocking() {
303 mScrimController.transitionTo(ScrimState.UNLOCKED);
304 mScrimController.finishAnimationsImmediately();
305 verifyZeroInteractions(mWakeLock);
306 }
307
308 @Test
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800309 public void testCallbackInvokedOnSameStateTransition() {
310 mScrimController.transitionTo(ScrimState.UNLOCKED);
311 mScrimController.finishAnimationsImmediately();
312 ScrimController.Callback callback = mock(ScrimController.Callback.class);
313 mScrimController.transitionTo(ScrimState.UNLOCKED, callback);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800314 verify(callback).onFinished();
315 }
316
317 @Test
318 public void testHoldsAodWallpaperAnimationLock() {
319 // Pre-conditions
320 mScrimController.transitionTo(ScrimState.AOD);
321 mScrimController.finishAnimationsImmediately();
322 reset(mWakeLock);
323
324 mScrimController.onHideWallpaperTimeout();
325 verify(mWakeLock).acquire();
326 verify(mWakeLock, never()).release();
327 mScrimController.finishAnimationsImmediately();
328 verify(mWakeLock).release();
329 }
330
331 @Test
332 public void testWillHideAoDWallpaper() {
333 mScrimController.setWallpaperSupportsAmbientMode(true);
334 mScrimController.transitionTo(ScrimState.AOD);
335 verify(mAlarmManager).setExact(anyInt(), anyLong(), any(), any(), any());
336 mScrimController.transitionTo(ScrimState.KEYGUARD);
337 verify(mAlarmManager).cancel(any(AlarmManager.OnAlarmListener.class));
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800338 }
339
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800340 @Test
341 public void testConservesExpansionOpacityAfterTransition() {
342 mScrimController.transitionTo(ScrimState.UNLOCKED);
343 mScrimController.setPanelExpansion(0.5f);
344 mScrimController.finishAnimationsImmediately();
345
346 final float expandedAlpha = mScrimBehind.getViewAlpha();
347
348 mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR);
349 mScrimController.finishAnimationsImmediately();
350 mScrimController.transitionTo(ScrimState.UNLOCKED);
351 mScrimController.finishAnimationsImmediately();
352
353 Assert.assertEquals("Scrim expansion opacity wasn't conserved when transitioning back",
354 expandedAlpha, mScrimBehind.getViewAlpha(), 0.01f);
355 }
356
357 @Test
358 public void cancelsOldAnimationBeforeBlanking() {
359 mScrimController.transitionTo(ScrimState.AOD);
360 mScrimController.finishAnimationsImmediately();
361 // Consume whatever value we had before
362 mScrimController.wasAnimationJustCancelled();
363
364 mScrimController.transitionTo(ScrimState.KEYGUARD);
365 mScrimController.finishAnimationsImmediately();
366 Assert.assertTrue(mScrimController.wasAnimationJustCancelled());
367 }
368
Lucas Dupinb380c882018-02-25 21:57:17 -0800369 /**
370 * Number of visible notifications affects scrim opacity.
371 */
372 @Test
373 public void testNotificationDensity() {
374 mScrimController.transitionTo(ScrimState.KEYGUARD);
375 mScrimController.finishAnimationsImmediately();
376
377 mScrimController.setNotificationCount(0);
378 mScrimController.finishAnimationsImmediately();
379 Assert.assertEquals("lower density when no notifications",
380 ScrimController.GRADIENT_SCRIM_ALPHA, mScrimBehind.getViewAlpha(), 0.01f);
381
382 mScrimController.setNotificationCount(3);
383 mScrimController.finishAnimationsImmediately();
384 Assert.assertEquals("stronger density when notifications are visible",
385 ScrimController.GRADIENT_SCRIM_ALPHA_BUSY, mScrimBehind.getViewAlpha(), 0.01f);
386 }
387
388 /**
389 * Moving from/to states conserves old notification density.
390 */
391 @Test
392 public void testConservesNotificationDensity() {
393 testConservesNotificationDensity(0 /* count */, ScrimController.GRADIENT_SCRIM_ALPHA);
394 testConservesNotificationDensity(3 /* count */, ScrimController.GRADIENT_SCRIM_ALPHA_BUSY);
395 }
396
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800397 @Test
398 public void testHeadsUpScrimOpacity() {
399 mScrimController.setPanelExpansion(0f);
400 mScrimController.onHeadsUpPinned(null /* row */);
401 mScrimController.finishAnimationsImmediately();
402
403 Assert.assertNotEquals("Heads-up scrim should be visible", 0f,
404 mHeadsUpScrim.getAlpha(), 0.01f);
405
406 mScrimController.onHeadsUpUnPinned(null /* row */);
407 mScrimController.finishAnimationsImmediately();
408
409 Assert.assertEquals("Heads-up scrim should have disappeared", 0f,
410 mHeadsUpScrim.getAlpha(), 0.01f);
411 }
412
413 @Test
414 public void testHeadsUpScrimCounting() {
415 mScrimController.setPanelExpansion(0f);
416 mScrimController.onHeadsUpPinned(null /* row */);
417 mScrimController.onHeadsUpPinned(null /* row */);
418 mScrimController.onHeadsUpPinned(null /* row */);
419 mScrimController.finishAnimationsImmediately();
420
421 Assert.assertNotEquals("Heads-up scrim should be visible", 0f,
422 mHeadsUpScrim.getAlpha(), 0.01f);
423
424 mScrimController.onHeadsUpUnPinned(null /* row */);
425 mScrimController.finishAnimationsImmediately();
426
427 Assert.assertEquals("Heads-up scrim should only disappear when counter reaches 0", 1f,
428 mHeadsUpScrim.getAlpha(), 0.01f);
429
430 mScrimController.onHeadsUpUnPinned(null /* row */);
431 mScrimController.onHeadsUpUnPinned(null /* row */);
432 mScrimController.finishAnimationsImmediately();
433 Assert.assertEquals("Heads-up scrim should have disappeared", 0f,
434 mHeadsUpScrim.getAlpha(), 0.01f);
435 }
436
437 @Test
438 public void testNoHeadsUpScrimExpanded() {
439 mScrimController.setPanelExpansion(1f);
440 mScrimController.onHeadsUpPinned(null /* row */);
441 mScrimController.finishAnimationsImmediately();
442
443 Assert.assertEquals("Heads-up scrim should not be visible when shade is expanded", 0f,
444 mHeadsUpScrim.getAlpha(), 0.01f);
445 }
446
Lucas Dupinb380c882018-02-25 21:57:17 -0800447 /**
448 * Conserves old notification density after leaving state and coming back.
449 *
450 * @param count How many notification.
451 * @param expectedAlpha Expected alpha.
452 */
453 private void testConservesNotificationDensity(int count, float expectedAlpha) {
454 mScrimController.setNotificationCount(count);
455 mScrimController.transitionTo(ScrimState.UNLOCKED);
456 mScrimController.finishAnimationsImmediately();
457
458 mScrimController.transitionTo(ScrimState.KEYGUARD);
459 mScrimController.finishAnimationsImmediately();
460
461 Assert.assertEquals("Doesn't respect notification busyness after transition",
462 expectedAlpha, mScrimBehind.getViewAlpha(), 0.01f);
463 }
464
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800465 private void assertScrimTint(ScrimView scrimView, boolean tinted) {
466 final boolean viewIsTinted = scrimView.getTint() != Color.TRANSPARENT;
467 final String name = scrimView == mScrimInFront ? "front" : "back";
468 Assert.assertEquals("Tint test failed at state " + mScrimController.getState()
469 +" with scrim: " + name + " and tint: " + Integer.toHexString(scrimView.getTint()),
470 tinted, viewIsTinted);
471 }
472
Lucas Dupin82aa1632017-12-13 00:13:57 -0800473 private void assertScrimVisibility(int inFront, int behind) {
474 boolean inFrontVisible = inFront != ScrimController.VISIBILITY_FULLY_TRANSPARENT;
475 boolean behindVisible = behind != ScrimController.VISIBILITY_FULLY_TRANSPARENT;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800476 Assert.assertEquals("Unexpected front scrim visibility. Alpha is "
Lucas Dupin82aa1632017-12-13 00:13:57 -0800477 + mScrimInFront.getViewAlpha(), inFrontVisible, mScrimInFront.getViewAlpha() > 0);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800478 Assert.assertEquals("Unexpected back scrim visibility. Alpha is "
Lucas Dupin82aa1632017-12-13 00:13:57 -0800479 + mScrimBehind.getViewAlpha(), behindVisible, mScrimBehind.getViewAlpha() > 0);
480
481 final int visibility;
482 if (inFront == VISIBILITY_FULLY_OPAQUE || behind == VISIBILITY_FULLY_OPAQUE) {
483 visibility = VISIBILITY_FULLY_OPAQUE;
484 } else if (inFront > VISIBILITY_FULLY_TRANSPARENT || behind > VISIBILITY_FULLY_TRANSPARENT) {
485 visibility = VISIBILITY_SEMI_TRANSPARENT;
486 } else {
487 visibility = VISIBILITY_FULLY_TRANSPARENT;
488 }
489 Assert.assertEquals("Invalid visibility.", visibility, mScrimVisibility);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800490 }
491
492 /**
493 * Special version of ScrimController where animations have 0 duration for test purposes.
494 */
495 private class SynchronousScrimController extends ScrimController {
496
497 private FakeHandler mHandler;
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800498 private boolean mAnimationCancelled;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800499
Lucas Dupin3503c5f2018-03-02 19:04:00 -0800500 SynchronousScrimController(LightBarController lightBarController,
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800501 ScrimView scrimBehind, ScrimView scrimInFront, View headsUpScrim,
Lucas Dupin82aa1632017-12-13 00:13:57 -0800502 Consumer<Integer> scrimVisibleListener, DozeParameters dozeParameters,
503 AlarmManager alarmManager) {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800504 super(lightBarController, scrimBehind, scrimInFront, headsUpScrim,
Lucas Dupin82aa1632017-12-13 00:13:57 -0800505 scrimVisibleListener, dozeParameters, alarmManager);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800506 mHandler = new FakeHandler(Looper.myLooper());
507 }
508
Lucas Dupin3503c5f2018-03-02 19:04:00 -0800509 void finishAnimationsImmediately() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800510 boolean[] animationFinished = {false};
511 setOnAnimationFinished(()-> animationFinished[0] = true);
512
513 // Execute code that will trigger animations.
514 onPreDraw();
515
516 // Force finish screen blanking.
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800517 mHandler.dispatchQueuedMessages();
518 // Force finish all animations.
519 endAnimation(mScrimBehind, TAG_KEY_ANIM);
520 endAnimation(mScrimInFront, TAG_KEY_ANIM);
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800521 endAnimation(mHeadsUpScrim, TAG_KEY_ANIM);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800522
523 if (!animationFinished[0]) {
524 throw new IllegalStateException("Animation never finished");
525 }
526 }
527
Lucas Dupin3503c5f2018-03-02 19:04:00 -0800528 boolean wasAnimationJustCancelled() {
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800529 final boolean wasCancelled = mAnimationCancelled;
530 mAnimationCancelled = false;
531 return wasCancelled;
532 }
533
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800534 private void endAnimation(View scrimView, int tag) {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800535 Animator animator = (Animator) scrimView.getTag(tag);
536 if (animator != null) {
537 animator.end();
538 }
539 }
540
541 @Override
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800542 protected void cancelAnimator(ValueAnimator previousAnimator) {
543 super.cancelAnimator(previousAnimator);
544 mAnimationCancelled = true;
545 }
546
547 @Override
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800548 protected Handler getHandler() {
549 return mHandler;
550 }
551
552 @Override
553 protected WakeLock createWakeLock() {
554 return mWakeLock;
555 }
Lucas Dupin8c7cb022018-02-05 10:49:03 -0800556
557 /**
558 * Do not wait for a frame since we're in a test environment.
559 * @param callback What to execute.
560 */
561 @Override
562 protected void doOnTheNextFrame(Choreographer.FrameCallback callback) {
563 callback.doFrame(0);
564 }
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800565 }
566
567}