blob: 6fbc0d710cc446bf6722a88219f79f62e5ef891b [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
Lucas Dupin67f02632018-03-12 11:08:31 -0700209 public void panelExpansionAffectsAlpha() {
210 mScrimController.setPanelExpansion(0f);
211 mScrimController.setPanelExpansion(0.5f);
212 mScrimController.transitionTo(ScrimState.UNLOCKED);
213 mScrimController.finishAnimationsImmediately();
214
215 final float scrimAlpha = mScrimBehind.getViewAlpha();
216 mScrimController.setExpansionAffectsAlpha(false);
217 mScrimController.setPanelExpansion(0.8f);
218 Assert.assertEquals("Scrim opacity shouldn't change when setExpansionAffectsAlpha "
219 + "is false", scrimAlpha, mScrimBehind.getViewAlpha(), 0.01f);
220
221 mScrimController.setExpansionAffectsAlpha(true);
222 mScrimController.setPanelExpansion(0.1f);
223 Assert.assertNotEquals("Scrim opacity should change when setExpansionAffectsAlpha "
224 + "is true", scrimAlpha, mScrimBehind.getViewAlpha(), 0.01f);
225 }
226
227 @Test
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800228 public void transitionToUnlockedFromAod() {
229 // Simulate unlock with fingerprint
230 mScrimController.transitionTo(ScrimState.AOD);
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800231 mScrimController.setPanelExpansion(0f);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800232 mScrimController.finishAnimationsImmediately();
233 mScrimController.transitionTo(ScrimState.UNLOCKED);
234 // Immediately tinted after the transition starts
235 assertScrimTint(mScrimInFront, true /* tinted */);
236 assertScrimTint(mScrimBehind, true /* tinted */);
237 mScrimController.finishAnimationsImmediately();
238 // Front scrim should be transparent
239 // Back scrim should be transparent
240 // Neither scrims should be tinted anymore after the animation.
Lucas Dupin82aa1632017-12-13 00:13:57 -0800241 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800242 assertScrimTint(mScrimInFront, false /* tinted */);
243 assertScrimTint(mScrimBehind, false /* tinted */);
244 }
245
246 @Test
247 public void scrimBlanksBeforeLeavingAoD() {
248 // Simulate unlock with fingerprint
249 mScrimController.transitionTo(ScrimState.AOD);
250 mScrimController.finishAnimationsImmediately();
251 mScrimController.transitionTo(ScrimState.UNLOCKED,
252 new ScrimController.Callback() {
253 @Override
254 public void onDisplayBlanked() {
255 // Front scrim should be black in the middle of the transition
256 Assert.assertTrue("Scrim should be visible during transition. Alpha: "
257 + mScrimInFront.getViewAlpha(), mScrimInFront.getViewAlpha() > 0);
258 assertScrimTint(mScrimInFront, true /* tinted */);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800259 Assert.assertSame("Scrim should be visible during transition.",
260 mScrimVisibility, VISIBILITY_FULLY_OPAQUE);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800261 }
262 });
263 mScrimController.finishAnimationsImmediately();
264 }
265
266 @Test
267 public void testScrimCallback() {
268 int[] callOrder = {0, 0, 0};
269 int[] currentCall = {0};
270 mScrimController.transitionTo(ScrimState.AOD, new ScrimController.Callback() {
271 @Override
272 public void onStart() {
273 callOrder[0] = ++currentCall[0];
274 }
275
276 @Override
277 public void onDisplayBlanked() {
278 callOrder[1] = ++currentCall[0];
279 }
280
281 @Override
282 public void onFinished() {
283 callOrder[2] = ++currentCall[0];
284 }
285 });
286 mScrimController.finishAnimationsImmediately();
287 Assert.assertEquals("onStart called in wrong order", 1, callOrder[0]);
288 Assert.assertEquals("onDisplayBlanked called in wrong order", 2, callOrder[1]);
289 Assert.assertEquals("onFinished called in wrong order", 3, callOrder[2]);
290 }
291
292 @Test
293 public void testScrimCallbacksWithoutAmbientDisplay() {
294 mAlwaysOnEnabled = false;
295 testScrimCallback();
296 }
297
298 @Test
299 public void testScrimCallbackCancelled() {
300 boolean[] cancelledCalled = {false};
301 mScrimController.transitionTo(ScrimState.AOD, new ScrimController.Callback() {
302 @Override
303 public void onCancelled() {
304 cancelledCalled[0] = true;
305 }
306 });
307 mScrimController.transitionTo(ScrimState.PULSING);
308 Assert.assertTrue("onCancelled should have been called", cancelledCalled[0]);
309 }
310
311 @Test
Lucas Dupineea53b32017-12-18 13:47:14 -0800312 public void testHoldsWakeLock_whenAOD() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800313 mScrimController.transitionTo(ScrimState.AOD);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800314 verify(mWakeLock).acquire();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800315 verify(mWakeLock, never()).release();
316 mScrimController.finishAnimationsImmediately();
Lucas Dupin82aa1632017-12-13 00:13:57 -0800317 verify(mWakeLock).release();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800318 }
319
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800320 @Test
Lucas Dupineea53b32017-12-18 13:47:14 -0800321 public void testDoesNotHoldWakeLock_whenUnlocking() {
322 mScrimController.transitionTo(ScrimState.UNLOCKED);
323 mScrimController.finishAnimationsImmediately();
324 verifyZeroInteractions(mWakeLock);
325 }
326
327 @Test
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800328 public void testCallbackInvokedOnSameStateTransition() {
329 mScrimController.transitionTo(ScrimState.UNLOCKED);
330 mScrimController.finishAnimationsImmediately();
331 ScrimController.Callback callback = mock(ScrimController.Callback.class);
332 mScrimController.transitionTo(ScrimState.UNLOCKED, callback);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800333 verify(callback).onFinished();
334 }
335
336 @Test
337 public void testHoldsAodWallpaperAnimationLock() {
338 // Pre-conditions
339 mScrimController.transitionTo(ScrimState.AOD);
340 mScrimController.finishAnimationsImmediately();
341 reset(mWakeLock);
342
343 mScrimController.onHideWallpaperTimeout();
344 verify(mWakeLock).acquire();
345 verify(mWakeLock, never()).release();
346 mScrimController.finishAnimationsImmediately();
347 verify(mWakeLock).release();
348 }
349
350 @Test
351 public void testWillHideAoDWallpaper() {
352 mScrimController.setWallpaperSupportsAmbientMode(true);
353 mScrimController.transitionTo(ScrimState.AOD);
354 verify(mAlarmManager).setExact(anyInt(), anyLong(), any(), any(), any());
355 mScrimController.transitionTo(ScrimState.KEYGUARD);
356 verify(mAlarmManager).cancel(any(AlarmManager.OnAlarmListener.class));
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800357 }
358
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800359 @Test
360 public void testConservesExpansionOpacityAfterTransition() {
361 mScrimController.transitionTo(ScrimState.UNLOCKED);
362 mScrimController.setPanelExpansion(0.5f);
363 mScrimController.finishAnimationsImmediately();
364
365 final float expandedAlpha = mScrimBehind.getViewAlpha();
366
367 mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR);
368 mScrimController.finishAnimationsImmediately();
369 mScrimController.transitionTo(ScrimState.UNLOCKED);
370 mScrimController.finishAnimationsImmediately();
371
372 Assert.assertEquals("Scrim expansion opacity wasn't conserved when transitioning back",
373 expandedAlpha, mScrimBehind.getViewAlpha(), 0.01f);
374 }
375
376 @Test
377 public void cancelsOldAnimationBeforeBlanking() {
378 mScrimController.transitionTo(ScrimState.AOD);
379 mScrimController.finishAnimationsImmediately();
380 // Consume whatever value we had before
381 mScrimController.wasAnimationJustCancelled();
382
383 mScrimController.transitionTo(ScrimState.KEYGUARD);
384 mScrimController.finishAnimationsImmediately();
385 Assert.assertTrue(mScrimController.wasAnimationJustCancelled());
386 }
387
Lucas Dupinb380c882018-02-25 21:57:17 -0800388 /**
389 * Number of visible notifications affects scrim opacity.
390 */
391 @Test
392 public void testNotificationDensity() {
393 mScrimController.transitionTo(ScrimState.KEYGUARD);
394 mScrimController.finishAnimationsImmediately();
395
396 mScrimController.setNotificationCount(0);
397 mScrimController.finishAnimationsImmediately();
398 Assert.assertEquals("lower density when no notifications",
399 ScrimController.GRADIENT_SCRIM_ALPHA, mScrimBehind.getViewAlpha(), 0.01f);
400
401 mScrimController.setNotificationCount(3);
402 mScrimController.finishAnimationsImmediately();
403 Assert.assertEquals("stronger density when notifications are visible",
404 ScrimController.GRADIENT_SCRIM_ALPHA_BUSY, mScrimBehind.getViewAlpha(), 0.01f);
405 }
406
407 /**
408 * Moving from/to states conserves old notification density.
409 */
410 @Test
411 public void testConservesNotificationDensity() {
412 testConservesNotificationDensity(0 /* count */, ScrimController.GRADIENT_SCRIM_ALPHA);
413 testConservesNotificationDensity(3 /* count */, ScrimController.GRADIENT_SCRIM_ALPHA_BUSY);
414 }
415
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800416 @Test
417 public void testHeadsUpScrimOpacity() {
418 mScrimController.setPanelExpansion(0f);
419 mScrimController.onHeadsUpPinned(null /* row */);
420 mScrimController.finishAnimationsImmediately();
421
422 Assert.assertNotEquals("Heads-up scrim should be visible", 0f,
423 mHeadsUpScrim.getAlpha(), 0.01f);
424
425 mScrimController.onHeadsUpUnPinned(null /* row */);
426 mScrimController.finishAnimationsImmediately();
427
428 Assert.assertEquals("Heads-up scrim should have disappeared", 0f,
429 mHeadsUpScrim.getAlpha(), 0.01f);
430 }
431
432 @Test
433 public void testHeadsUpScrimCounting() {
434 mScrimController.setPanelExpansion(0f);
435 mScrimController.onHeadsUpPinned(null /* row */);
436 mScrimController.onHeadsUpPinned(null /* row */);
437 mScrimController.onHeadsUpPinned(null /* row */);
438 mScrimController.finishAnimationsImmediately();
439
440 Assert.assertNotEquals("Heads-up scrim should be visible", 0f,
441 mHeadsUpScrim.getAlpha(), 0.01f);
442
443 mScrimController.onHeadsUpUnPinned(null /* row */);
444 mScrimController.finishAnimationsImmediately();
445
446 Assert.assertEquals("Heads-up scrim should only disappear when counter reaches 0", 1f,
447 mHeadsUpScrim.getAlpha(), 0.01f);
448
449 mScrimController.onHeadsUpUnPinned(null /* row */);
450 mScrimController.onHeadsUpUnPinned(null /* row */);
451 mScrimController.finishAnimationsImmediately();
452 Assert.assertEquals("Heads-up scrim should have disappeared", 0f,
453 mHeadsUpScrim.getAlpha(), 0.01f);
454 }
455
456 @Test
457 public void testNoHeadsUpScrimExpanded() {
458 mScrimController.setPanelExpansion(1f);
459 mScrimController.onHeadsUpPinned(null /* row */);
460 mScrimController.finishAnimationsImmediately();
461
462 Assert.assertEquals("Heads-up scrim should not be visible when shade is expanded", 0f,
463 mHeadsUpScrim.getAlpha(), 0.01f);
464 }
465
Lucas Dupinb380c882018-02-25 21:57:17 -0800466 /**
467 * Conserves old notification density after leaving state and coming back.
468 *
469 * @param count How many notification.
470 * @param expectedAlpha Expected alpha.
471 */
472 private void testConservesNotificationDensity(int count, float expectedAlpha) {
473 mScrimController.setNotificationCount(count);
474 mScrimController.transitionTo(ScrimState.UNLOCKED);
475 mScrimController.finishAnimationsImmediately();
476
477 mScrimController.transitionTo(ScrimState.KEYGUARD);
478 mScrimController.finishAnimationsImmediately();
479
480 Assert.assertEquals("Doesn't respect notification busyness after transition",
481 expectedAlpha, mScrimBehind.getViewAlpha(), 0.01f);
482 }
483
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800484 private void assertScrimTint(ScrimView scrimView, boolean tinted) {
485 final boolean viewIsTinted = scrimView.getTint() != Color.TRANSPARENT;
486 final String name = scrimView == mScrimInFront ? "front" : "back";
487 Assert.assertEquals("Tint test failed at state " + mScrimController.getState()
488 +" with scrim: " + name + " and tint: " + Integer.toHexString(scrimView.getTint()),
489 tinted, viewIsTinted);
490 }
491
Lucas Dupin82aa1632017-12-13 00:13:57 -0800492 private void assertScrimVisibility(int inFront, int behind) {
493 boolean inFrontVisible = inFront != ScrimController.VISIBILITY_FULLY_TRANSPARENT;
494 boolean behindVisible = behind != ScrimController.VISIBILITY_FULLY_TRANSPARENT;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800495 Assert.assertEquals("Unexpected front scrim visibility. Alpha is "
Lucas Dupin82aa1632017-12-13 00:13:57 -0800496 + mScrimInFront.getViewAlpha(), inFrontVisible, mScrimInFront.getViewAlpha() > 0);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800497 Assert.assertEquals("Unexpected back scrim visibility. Alpha is "
Lucas Dupin82aa1632017-12-13 00:13:57 -0800498 + mScrimBehind.getViewAlpha(), behindVisible, mScrimBehind.getViewAlpha() > 0);
499
500 final int visibility;
501 if (inFront == VISIBILITY_FULLY_OPAQUE || behind == VISIBILITY_FULLY_OPAQUE) {
502 visibility = VISIBILITY_FULLY_OPAQUE;
503 } else if (inFront > VISIBILITY_FULLY_TRANSPARENT || behind > VISIBILITY_FULLY_TRANSPARENT) {
504 visibility = VISIBILITY_SEMI_TRANSPARENT;
505 } else {
506 visibility = VISIBILITY_FULLY_TRANSPARENT;
507 }
508 Assert.assertEquals("Invalid visibility.", visibility, mScrimVisibility);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800509 }
510
511 /**
512 * Special version of ScrimController where animations have 0 duration for test purposes.
513 */
514 private class SynchronousScrimController extends ScrimController {
515
516 private FakeHandler mHandler;
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800517 private boolean mAnimationCancelled;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800518
Lucas Dupin3503c5f2018-03-02 19:04:00 -0800519 SynchronousScrimController(LightBarController lightBarController,
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800520 ScrimView scrimBehind, ScrimView scrimInFront, View headsUpScrim,
Lucas Dupin82aa1632017-12-13 00:13:57 -0800521 Consumer<Integer> scrimVisibleListener, DozeParameters dozeParameters,
522 AlarmManager alarmManager) {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800523 super(lightBarController, scrimBehind, scrimInFront, headsUpScrim,
Lucas Dupin82aa1632017-12-13 00:13:57 -0800524 scrimVisibleListener, dozeParameters, alarmManager);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800525 mHandler = new FakeHandler(Looper.myLooper());
526 }
527
Lucas Dupin3503c5f2018-03-02 19:04:00 -0800528 void finishAnimationsImmediately() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800529 boolean[] animationFinished = {false};
530 setOnAnimationFinished(()-> animationFinished[0] = true);
531
532 // Execute code that will trigger animations.
533 onPreDraw();
534
535 // Force finish screen blanking.
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800536 mHandler.dispatchQueuedMessages();
537 // Force finish all animations.
538 endAnimation(mScrimBehind, TAG_KEY_ANIM);
539 endAnimation(mScrimInFront, TAG_KEY_ANIM);
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800540 endAnimation(mHeadsUpScrim, TAG_KEY_ANIM);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800541
542 if (!animationFinished[0]) {
543 throw new IllegalStateException("Animation never finished");
544 }
545 }
546
Lucas Dupin3503c5f2018-03-02 19:04:00 -0800547 boolean wasAnimationJustCancelled() {
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800548 final boolean wasCancelled = mAnimationCancelled;
549 mAnimationCancelled = false;
550 return wasCancelled;
551 }
552
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800553 private void endAnimation(View scrimView, int tag) {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800554 Animator animator = (Animator) scrimView.getTag(tag);
555 if (animator != null) {
556 animator.end();
557 }
558 }
559
560 @Override
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800561 protected void cancelAnimator(ValueAnimator previousAnimator) {
562 super.cancelAnimator(previousAnimator);
563 mAnimationCancelled = true;
564 }
565
566 @Override
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800567 protected Handler getHandler() {
568 return mHandler;
569 }
570
571 @Override
572 protected WakeLock createWakeLock() {
573 return mWakeLock;
574 }
Lucas Dupin8c7cb022018-02-05 10:49:03 -0800575
576 /**
577 * Do not wait for a frame since we're in a test environment.
578 * @param callback What to execute.
579 */
580 @Override
581 protected void doOnTheNextFrame(Choreographer.FrameCallback callback) {
582 callback.doFrame(0);
583 }
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800584 }
585
586}