blob: 22e49800481ff667a4b72eb72e6809b6d668d10d [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 Dupin38962d72018-03-14 12:41:39 -070045import com.android.internal.util.Preconditions;
Lucas Dupin7517b5d2017-08-22 12:51:25 -070046import com.android.keyguard.KeyguardUpdateMonitor;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080047import com.android.systemui.SysuiTestCase;
48import com.android.systemui.statusbar.ScrimView;
49import com.android.systemui.util.wakelock.WakeLock;
50import com.android.systemui.utils.os.FakeHandler;
51
52import org.junit.Assert;
53import org.junit.Before;
54import org.junit.Test;
55import org.junit.runner.RunWith;
56
57import java.util.function.Consumer;
58
59@RunWith(AndroidTestingRunner.class)
60@TestableLooper.RunWithLooper
61@SmallTest
62public class ScrimControllerTest extends SysuiTestCase {
63
64 private SynchronousScrimController mScrimController;
65 private ScrimView mScrimBehind;
66 private ScrimView mScrimInFront;
67 private View mHeadsUpScrim;
Lucas Dupin82aa1632017-12-13 00:13:57 -080068 private Consumer<Integer> mScrimVisibilityCallback;
69 private int mScrimVisibility;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080070 private LightBarController mLightBarController;
71 private DozeParameters mDozeParamenters;
72 private WakeLock mWakeLock;
73 private boolean mAlwaysOnEnabled;
Lucas Dupin82aa1632017-12-13 00:13:57 -080074 private AlarmManager mAlarmManager;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080075
76 @Before
77 public void setup() {
78 mLightBarController = mock(LightBarController.class);
79 mScrimBehind = new ScrimView(getContext());
80 mScrimInFront = new ScrimView(getContext());
Lucas Dupin3daf3b02018-02-27 17:23:41 -080081 mHeadsUpScrim = new View(getContext());
Lucas Dupin9e3fa102017-11-08 17:16:55 -080082 mWakeLock = mock(WakeLock.class);
Lucas Dupin82aa1632017-12-13 00:13:57 -080083 mAlarmManager = mock(AlarmManager.class);
Lucas Dupin9e3fa102017-11-08 17:16:55 -080084 mAlwaysOnEnabled = true;
Lucas Dupin82aa1632017-12-13 00:13:57 -080085 mScrimVisibilityCallback = (Integer visible) -> mScrimVisibility = visible;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080086 mDozeParamenters = mock(DozeParameters.class);
87 when(mDozeParamenters.getAlwaysOn()).thenAnswer(invocation -> mAlwaysOnEnabled);
Lucas Dupin43d0d732017-11-16 11:23:49 -080088 when(mDozeParamenters.getDisplayNeedsBlanking()).thenReturn(true);
Lucas Dupin9e3fa102017-11-08 17:16:55 -080089 mScrimController = new SynchronousScrimController(mLightBarController, mScrimBehind,
Lucas Dupin82aa1632017-12-13 00:13:57 -080090 mScrimInFront, mHeadsUpScrim, mScrimVisibilityCallback, mDozeParamenters,
91 mAlarmManager);
Lucas Dupin9e3fa102017-11-08 17:16:55 -080092 }
93
94 @Test
95 public void initialState() {
96 Assert.assertEquals("ScrimController should start initialized",
97 mScrimController.getState(), ScrimState.UNINITIALIZED);
98 }
99
100 @Test
101 public void transitionToKeyguard() {
102 mScrimController.transitionTo(ScrimState.KEYGUARD);
103 mScrimController.finishAnimationsImmediately();
104 // Front scrim should be transparent
105 // Back scrim should be visible without tint
Lucas Dupin82aa1632017-12-13 00:13:57 -0800106 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800107 assertScrimTint(mScrimBehind, false /* tinted */);
108 }
109
110 @Test
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700111 public void transitionToAod_withRegularWallpaper() {
112 mScrimController.transitionTo(ScrimState.AOD);
113 mScrimController.finishAnimationsImmediately();
114 // Front scrim should be transparent
115 // Back scrim should be visible with tint
Lucas Dupin82aa1632017-12-13 00:13:57 -0800116 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700117 assertScrimTint(mScrimBehind, true /* tinted */);
118 assertScrimTint(mScrimInFront, true /* tinted */);
119 }
120
121 @Test
122 public void transitionToAod_withAodWallpaper() {
123 mScrimController.setWallpaperSupportsAmbientMode(true);
124 mScrimController.transitionTo(ScrimState.AOD);
125 mScrimController.finishAnimationsImmediately();
126 // Front scrim should be transparent
127 // Back scrim should be transparent
Lucas Dupin82aa1632017-12-13 00:13:57 -0800128 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
129
130 // Move on to PULSING and check if the back scrim is still transparent
131 mScrimController.transitionTo(ScrimState.PULSING);
132 mScrimController.finishAnimationsImmediately();
133 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700134 }
135
136 @Test
137 public void transitionToAod_withAodWallpaperAndLockScreenWallpaper() {
138 ScrimState.AOD.mKeyguardUpdateMonitor = new KeyguardUpdateMonitor(getContext()) {
139 @Override
140 public boolean hasLockscreenWallpaper() {
141 return true;
142 }
143 };
144 mScrimController.setWallpaperSupportsAmbientMode(true);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800145 mScrimController.transitionTo(ScrimState.AOD);
146 mScrimController.finishAnimationsImmediately();
147 // Front scrim should be transparent
148 // Back scrim should be visible with tint
Lucas Dupin82aa1632017-12-13 00:13:57 -0800149 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800150 assertScrimTint(mScrimBehind, true /* tinted */);
151 assertScrimTint(mScrimInFront, true /* tinted */);
152 }
153
154 @Test
155 public void transitionToPulsing() {
Lucas Dupin82aa1632017-12-13 00:13:57 -0800156 // Pre-condition
157 // Need to go to AoD first because PULSING doesn't change
158 // the back scrim opacity - otherwise it would hide AoD wallpapers.
159 mScrimController.setWallpaperSupportsAmbientMode(false);
160 mScrimController.transitionTo(ScrimState.AOD);
161 mScrimController.finishAnimationsImmediately();
162 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
163
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800164 mScrimController.transitionTo(ScrimState.PULSING);
165 mScrimController.finishAnimationsImmediately();
166 // Front scrim should be transparent
167 // Back scrim should be visible with tint
168 // Pulse callback should have been invoked
Lucas Dupin82aa1632017-12-13 00:13:57 -0800169 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800170 assertScrimTint(mScrimBehind, true /* tinted */);
171 }
172
173 @Test
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800174 public void transitionToKeyguardBouncer() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800175 mScrimController.transitionTo(ScrimState.BOUNCER);
176 mScrimController.finishAnimationsImmediately();
177 // Front scrim should be transparent
178 // Back scrim should be visible without tint
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800179 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
180 assertScrimTint(mScrimBehind, false /* tinted */);
181 }
182
183 @Test
184 public void transitionToBouncer() {
Lucas Dupin05726cd2018-03-13 14:00:24 -0700185 mScrimController.transitionTo(ScrimState.BOUNCER_SCRIMMED);
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800186 mScrimController.finishAnimationsImmediately();
187 // Front scrim should be transparent
188 // Back scrim should be visible without tint
189 assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800190 assertScrimTint(mScrimBehind, false /* tinted */);
191 }
192
193 @Test
194 public void transitionToUnlocked() {
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800195 mScrimController.setPanelExpansion(0f);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800196 mScrimController.transitionTo(ScrimState.UNLOCKED);
197 mScrimController.finishAnimationsImmediately();
198 // Front scrim should be transparent
199 // Back scrim should be transparent
Lucas Dupin82aa1632017-12-13 00:13:57 -0800200 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800201 assertScrimTint(mScrimBehind, false /* tinted */);
202 assertScrimTint(mScrimInFront, false /* tinted */);
203
204 // Back scrim should be visible after start dragging
205 mScrimController.setPanelExpansion(0.5f);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800206 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800207 }
208
209 @Test
Lucas Dupin67f02632018-03-12 11:08:31 -0700210 public void panelExpansionAffectsAlpha() {
211 mScrimController.setPanelExpansion(0f);
212 mScrimController.setPanelExpansion(0.5f);
213 mScrimController.transitionTo(ScrimState.UNLOCKED);
214 mScrimController.finishAnimationsImmediately();
215
216 final float scrimAlpha = mScrimBehind.getViewAlpha();
217 mScrimController.setExpansionAffectsAlpha(false);
218 mScrimController.setPanelExpansion(0.8f);
219 Assert.assertEquals("Scrim opacity shouldn't change when setExpansionAffectsAlpha "
220 + "is false", scrimAlpha, mScrimBehind.getViewAlpha(), 0.01f);
221
222 mScrimController.setExpansionAffectsAlpha(true);
223 mScrimController.setPanelExpansion(0.1f);
224 Assert.assertNotEquals("Scrim opacity should change when setExpansionAffectsAlpha "
225 + "is true", scrimAlpha, mScrimBehind.getViewAlpha(), 0.01f);
226 }
227
228 @Test
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800229 public void transitionToUnlockedFromAod() {
230 // Simulate unlock with fingerprint
231 mScrimController.transitionTo(ScrimState.AOD);
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800232 mScrimController.setPanelExpansion(0f);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800233 mScrimController.finishAnimationsImmediately();
234 mScrimController.transitionTo(ScrimState.UNLOCKED);
235 // Immediately tinted after the transition starts
236 assertScrimTint(mScrimInFront, true /* tinted */);
237 assertScrimTint(mScrimBehind, true /* tinted */);
238 mScrimController.finishAnimationsImmediately();
239 // Front scrim should be transparent
240 // Back scrim should be transparent
241 // Neither scrims should be tinted anymore after the animation.
Lucas Dupin82aa1632017-12-13 00:13:57 -0800242 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800243 assertScrimTint(mScrimInFront, false /* tinted */);
244 assertScrimTint(mScrimBehind, false /* tinted */);
245 }
246
247 @Test
248 public void scrimBlanksBeforeLeavingAoD() {
249 // Simulate unlock with fingerprint
250 mScrimController.transitionTo(ScrimState.AOD);
251 mScrimController.finishAnimationsImmediately();
252 mScrimController.transitionTo(ScrimState.UNLOCKED,
253 new ScrimController.Callback() {
254 @Override
255 public void onDisplayBlanked() {
256 // Front scrim should be black in the middle of the transition
257 Assert.assertTrue("Scrim should be visible during transition. Alpha: "
258 + mScrimInFront.getViewAlpha(), mScrimInFront.getViewAlpha() > 0);
259 assertScrimTint(mScrimInFront, true /* tinted */);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800260 Assert.assertSame("Scrim should be visible during transition.",
261 mScrimVisibility, VISIBILITY_FULLY_OPAQUE);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800262 }
263 });
264 mScrimController.finishAnimationsImmediately();
265 }
266
267 @Test
268 public void testScrimCallback() {
269 int[] callOrder = {0, 0, 0};
270 int[] currentCall = {0};
271 mScrimController.transitionTo(ScrimState.AOD, new ScrimController.Callback() {
272 @Override
273 public void onStart() {
274 callOrder[0] = ++currentCall[0];
275 }
276
277 @Override
278 public void onDisplayBlanked() {
279 callOrder[1] = ++currentCall[0];
280 }
281
282 @Override
283 public void onFinished() {
284 callOrder[2] = ++currentCall[0];
285 }
286 });
287 mScrimController.finishAnimationsImmediately();
288 Assert.assertEquals("onStart called in wrong order", 1, callOrder[0]);
289 Assert.assertEquals("onDisplayBlanked called in wrong order", 2, callOrder[1]);
290 Assert.assertEquals("onFinished called in wrong order", 3, callOrder[2]);
291 }
292
293 @Test
294 public void testScrimCallbacksWithoutAmbientDisplay() {
295 mAlwaysOnEnabled = false;
296 testScrimCallback();
297 }
298
299 @Test
300 public void testScrimCallbackCancelled() {
301 boolean[] cancelledCalled = {false};
302 mScrimController.transitionTo(ScrimState.AOD, new ScrimController.Callback() {
303 @Override
304 public void onCancelled() {
305 cancelledCalled[0] = true;
306 }
307 });
308 mScrimController.transitionTo(ScrimState.PULSING);
309 Assert.assertTrue("onCancelled should have been called", cancelledCalled[0]);
310 }
311
312 @Test
Lucas Dupineea53b32017-12-18 13:47:14 -0800313 public void testHoldsWakeLock_whenAOD() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800314 mScrimController.transitionTo(ScrimState.AOD);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800315 verify(mWakeLock).acquire();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800316 verify(mWakeLock, never()).release();
317 mScrimController.finishAnimationsImmediately();
Lucas Dupin82aa1632017-12-13 00:13:57 -0800318 verify(mWakeLock).release();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800319 }
320
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800321 @Test
Lucas Dupineea53b32017-12-18 13:47:14 -0800322 public void testDoesNotHoldWakeLock_whenUnlocking() {
323 mScrimController.transitionTo(ScrimState.UNLOCKED);
324 mScrimController.finishAnimationsImmediately();
325 verifyZeroInteractions(mWakeLock);
326 }
327
328 @Test
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800329 public void testCallbackInvokedOnSameStateTransition() {
330 mScrimController.transitionTo(ScrimState.UNLOCKED);
331 mScrimController.finishAnimationsImmediately();
332 ScrimController.Callback callback = mock(ScrimController.Callback.class);
333 mScrimController.transitionTo(ScrimState.UNLOCKED, callback);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800334 verify(callback).onFinished();
335 }
336
337 @Test
338 public void testHoldsAodWallpaperAnimationLock() {
339 // Pre-conditions
340 mScrimController.transitionTo(ScrimState.AOD);
341 mScrimController.finishAnimationsImmediately();
342 reset(mWakeLock);
343
344 mScrimController.onHideWallpaperTimeout();
345 verify(mWakeLock).acquire();
346 verify(mWakeLock, never()).release();
347 mScrimController.finishAnimationsImmediately();
348 verify(mWakeLock).release();
349 }
350
351 @Test
Lucas Dupin16cfe452018-02-08 13:14:50 -0800352 public void testWillHideAodWallpaper() {
Lucas Dupin82aa1632017-12-13 00:13:57 -0800353 mScrimController.setWallpaperSupportsAmbientMode(true);
354 mScrimController.transitionTo(ScrimState.AOD);
355 verify(mAlarmManager).setExact(anyInt(), anyLong(), any(), any(), any());
356 mScrimController.transitionTo(ScrimState.KEYGUARD);
357 verify(mAlarmManager).cancel(any(AlarmManager.OnAlarmListener.class));
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800358 }
359
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800360 @Test
361 public void testConservesExpansionOpacityAfterTransition() {
362 mScrimController.transitionTo(ScrimState.UNLOCKED);
363 mScrimController.setPanelExpansion(0.5f);
364 mScrimController.finishAnimationsImmediately();
365
366 final float expandedAlpha = mScrimBehind.getViewAlpha();
367
368 mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR);
369 mScrimController.finishAnimationsImmediately();
370 mScrimController.transitionTo(ScrimState.UNLOCKED);
371 mScrimController.finishAnimationsImmediately();
372
373 Assert.assertEquals("Scrim expansion opacity wasn't conserved when transitioning back",
374 expandedAlpha, mScrimBehind.getViewAlpha(), 0.01f);
375 }
376
377 @Test
378 public void cancelsOldAnimationBeforeBlanking() {
379 mScrimController.transitionTo(ScrimState.AOD);
380 mScrimController.finishAnimationsImmediately();
381 // Consume whatever value we had before
382 mScrimController.wasAnimationJustCancelled();
383
384 mScrimController.transitionTo(ScrimState.KEYGUARD);
385 mScrimController.finishAnimationsImmediately();
386 Assert.assertTrue(mScrimController.wasAnimationJustCancelled());
387 }
388
Lucas Dupinb380c882018-02-25 21:57:17 -0800389 /**
390 * Number of visible notifications affects scrim opacity.
391 */
392 @Test
393 public void testNotificationDensity() {
394 mScrimController.transitionTo(ScrimState.KEYGUARD);
395 mScrimController.finishAnimationsImmediately();
396
397 mScrimController.setNotificationCount(0);
398 mScrimController.finishAnimationsImmediately();
399 Assert.assertEquals("lower density when no notifications",
400 ScrimController.GRADIENT_SCRIM_ALPHA, mScrimBehind.getViewAlpha(), 0.01f);
401
402 mScrimController.setNotificationCount(3);
403 mScrimController.finishAnimationsImmediately();
404 Assert.assertEquals("stronger density when notifications are visible",
405 ScrimController.GRADIENT_SCRIM_ALPHA_BUSY, mScrimBehind.getViewAlpha(), 0.01f);
406 }
407
408 /**
409 * Moving from/to states conserves old notification density.
410 */
411 @Test
412 public void testConservesNotificationDensity() {
413 testConservesNotificationDensity(0 /* count */, ScrimController.GRADIENT_SCRIM_ALPHA);
414 testConservesNotificationDensity(3 /* count */, ScrimController.GRADIENT_SCRIM_ALPHA_BUSY);
415 }
416
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800417 @Test
418 public void testHeadsUpScrimOpacity() {
419 mScrimController.setPanelExpansion(0f);
420 mScrimController.onHeadsUpPinned(null /* row */);
421 mScrimController.finishAnimationsImmediately();
422
423 Assert.assertNotEquals("Heads-up scrim should be visible", 0f,
424 mHeadsUpScrim.getAlpha(), 0.01f);
425
426 mScrimController.onHeadsUpUnPinned(null /* row */);
427 mScrimController.finishAnimationsImmediately();
428
429 Assert.assertEquals("Heads-up scrim should have disappeared", 0f,
430 mHeadsUpScrim.getAlpha(), 0.01f);
431 }
432
433 @Test
434 public void testHeadsUpScrimCounting() {
435 mScrimController.setPanelExpansion(0f);
436 mScrimController.onHeadsUpPinned(null /* row */);
437 mScrimController.onHeadsUpPinned(null /* row */);
438 mScrimController.onHeadsUpPinned(null /* row */);
439 mScrimController.finishAnimationsImmediately();
440
441 Assert.assertNotEquals("Heads-up scrim should be visible", 0f,
442 mHeadsUpScrim.getAlpha(), 0.01f);
443
444 mScrimController.onHeadsUpUnPinned(null /* row */);
445 mScrimController.finishAnimationsImmediately();
446
447 Assert.assertEquals("Heads-up scrim should only disappear when counter reaches 0", 1f,
448 mHeadsUpScrim.getAlpha(), 0.01f);
449
450 mScrimController.onHeadsUpUnPinned(null /* row */);
451 mScrimController.onHeadsUpUnPinned(null /* row */);
452 mScrimController.finishAnimationsImmediately();
453 Assert.assertEquals("Heads-up scrim should have disappeared", 0f,
454 mHeadsUpScrim.getAlpha(), 0.01f);
455 }
456
457 @Test
458 public void testNoHeadsUpScrimExpanded() {
459 mScrimController.setPanelExpansion(1f);
460 mScrimController.onHeadsUpPinned(null /* row */);
461 mScrimController.finishAnimationsImmediately();
462
463 Assert.assertEquals("Heads-up scrim should not be visible when shade is expanded", 0f,
464 mHeadsUpScrim.getAlpha(), 0.01f);
465 }
466
Lucas Dupin38962d72018-03-14 12:41:39 -0700467 @Test
468 public void testScrimFocus() {
469 mScrimController.transitionTo(ScrimState.AOD);
470 Assert.assertFalse("Should not be focusable on AOD", mScrimBehind.isFocusable());
471 Assert.assertFalse("Should not be focusable on AOD", mScrimInFront.isFocusable());
472
473 mScrimController.transitionTo(ScrimState.KEYGUARD);
474 Assert.assertTrue("Should be focusable on keyguard", mScrimBehind.isFocusable());
475 Assert.assertTrue("Should be focusable on keyguard", mScrimInFront.isFocusable());
476 }
477
Lucas Dupind5107302018-03-19 15:30:29 -0700478 @Test
479 public void testHidesShowWhenLockedActivity() {
480 mScrimController.setWallpaperSupportsAmbientMode(true);
481 mScrimController.setKeyguardOccluded(true);
482 mScrimController.transitionTo(ScrimState.AOD);
483 mScrimController.finishAnimationsImmediately();
484 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
485
486 mScrimController.transitionTo(ScrimState.PULSING);
487 mScrimController.finishAnimationsImmediately();
488 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
489 }
490
Lucas Dupinb380c882018-02-25 21:57:17 -0800491 /**
492 * Conserves old notification density after leaving state and coming back.
493 *
494 * @param count How many notification.
495 * @param expectedAlpha Expected alpha.
496 */
497 private void testConservesNotificationDensity(int count, float expectedAlpha) {
498 mScrimController.setNotificationCount(count);
499 mScrimController.transitionTo(ScrimState.UNLOCKED);
500 mScrimController.finishAnimationsImmediately();
501
502 mScrimController.transitionTo(ScrimState.KEYGUARD);
503 mScrimController.finishAnimationsImmediately();
504
505 Assert.assertEquals("Doesn't respect notification busyness after transition",
506 expectedAlpha, mScrimBehind.getViewAlpha(), 0.01f);
507 }
508
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800509 private void assertScrimTint(ScrimView scrimView, boolean tinted) {
510 final boolean viewIsTinted = scrimView.getTint() != Color.TRANSPARENT;
511 final String name = scrimView == mScrimInFront ? "front" : "back";
512 Assert.assertEquals("Tint test failed at state " + mScrimController.getState()
513 +" with scrim: " + name + " and tint: " + Integer.toHexString(scrimView.getTint()),
514 tinted, viewIsTinted);
515 }
516
Lucas Dupin82aa1632017-12-13 00:13:57 -0800517 private void assertScrimVisibility(int inFront, int behind) {
518 boolean inFrontVisible = inFront != ScrimController.VISIBILITY_FULLY_TRANSPARENT;
519 boolean behindVisible = behind != ScrimController.VISIBILITY_FULLY_TRANSPARENT;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800520 Assert.assertEquals("Unexpected front scrim visibility. Alpha is "
Lucas Dupin82aa1632017-12-13 00:13:57 -0800521 + mScrimInFront.getViewAlpha(), inFrontVisible, mScrimInFront.getViewAlpha() > 0);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800522 Assert.assertEquals("Unexpected back scrim visibility. Alpha is "
Lucas Dupin82aa1632017-12-13 00:13:57 -0800523 + mScrimBehind.getViewAlpha(), behindVisible, mScrimBehind.getViewAlpha() > 0);
524
525 final int visibility;
526 if (inFront == VISIBILITY_FULLY_OPAQUE || behind == VISIBILITY_FULLY_OPAQUE) {
527 visibility = VISIBILITY_FULLY_OPAQUE;
528 } else if (inFront > VISIBILITY_FULLY_TRANSPARENT || behind > VISIBILITY_FULLY_TRANSPARENT) {
529 visibility = VISIBILITY_SEMI_TRANSPARENT;
530 } else {
531 visibility = VISIBILITY_FULLY_TRANSPARENT;
532 }
533 Assert.assertEquals("Invalid visibility.", visibility, mScrimVisibility);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800534 }
535
536 /**
537 * Special version of ScrimController where animations have 0 duration for test purposes.
538 */
539 private class SynchronousScrimController extends ScrimController {
540
541 private FakeHandler mHandler;
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800542 private boolean mAnimationCancelled;
Lucas Dupin16cfe452018-02-08 13:14:50 -0800543 boolean mOnPreDrawCalled;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800544
Lucas Dupin3503c5f2018-03-02 19:04:00 -0800545 SynchronousScrimController(LightBarController lightBarController,
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800546 ScrimView scrimBehind, ScrimView scrimInFront, View headsUpScrim,
Lucas Dupin82aa1632017-12-13 00:13:57 -0800547 Consumer<Integer> scrimVisibleListener, DozeParameters dozeParameters,
548 AlarmManager alarmManager) {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800549 super(lightBarController, scrimBehind, scrimInFront, headsUpScrim,
Lucas Dupin82aa1632017-12-13 00:13:57 -0800550 scrimVisibleListener, dozeParameters, alarmManager);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800551 mHandler = new FakeHandler(Looper.myLooper());
552 }
553
Lucas Dupin16cfe452018-02-08 13:14:50 -0800554 @Override
555 public boolean onPreDraw() {
556 mOnPreDrawCalled = true;
557 return super.onPreDraw();
558 }
559
Lucas Dupin3503c5f2018-03-02 19:04:00 -0800560 void finishAnimationsImmediately() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800561 boolean[] animationFinished = {false};
562 setOnAnimationFinished(()-> animationFinished[0] = true);
563
564 // Execute code that will trigger animations.
565 onPreDraw();
566
567 // Force finish screen blanking.
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800568 mHandler.dispatchQueuedMessages();
569 // Force finish all animations.
570 endAnimation(mScrimBehind, TAG_KEY_ANIM);
571 endAnimation(mScrimInFront, TAG_KEY_ANIM);
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800572 endAnimation(mHeadsUpScrim, TAG_KEY_ANIM);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800573
574 if (!animationFinished[0]) {
575 throw new IllegalStateException("Animation never finished");
576 }
577 }
578
Lucas Dupin3503c5f2018-03-02 19:04:00 -0800579 boolean wasAnimationJustCancelled() {
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800580 final boolean wasCancelled = mAnimationCancelled;
581 mAnimationCancelled = false;
582 return wasCancelled;
583 }
584
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800585 private void endAnimation(View scrimView, int tag) {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800586 Animator animator = (Animator) scrimView.getTag(tag);
587 if (animator != null) {
588 animator.end();
589 }
590 }
591
592 @Override
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800593 protected void cancelAnimator(ValueAnimator previousAnimator) {
594 super.cancelAnimator(previousAnimator);
595 mAnimationCancelled = true;
596 }
597
598 @Override
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800599 protected Handler getHandler() {
600 return mHandler;
601 }
602
603 @Override
604 protected WakeLock createWakeLock() {
605 return mWakeLock;
606 }
Lucas Dupin8c7cb022018-02-05 10:49:03 -0800607
608 /**
609 * Do not wait for a frame since we're in a test environment.
610 * @param callback What to execute.
611 */
612 @Override
613 protected void doOnTheNextFrame(Choreographer.FrameCallback callback) {
614 callback.doFrame(0);
615 }
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800616 }
617
618}