blob: 58c6bc7687e20413478b07cc9117a285e786ec5e [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 Dupin067136c2018-03-27 18:03:25 -070029import static org.mockito.Mockito.spy;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080030import static org.mockito.Mockito.verify;
Lucas Dupineea53b32017-12-18 13:47:14 -080031import static org.mockito.Mockito.verifyZeroInteractions;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080032import static org.mockito.Mockito.when;
33
34import android.animation.Animator;
Lucas Dupin80a3fcc2018-02-07 10:49:55 -080035import android.animation.ValueAnimator;
Lucas Dupin82aa1632017-12-13 00:13:57 -080036import android.app.AlarmManager;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080037import android.graphics.Color;
38import android.os.Handler;
39import android.os.Looper;
40import android.support.test.filters.SmallTest;
41import android.testing.AndroidTestingRunner;
42import android.testing.TestableLooper;
43import android.view.View;
44
shawnlin317db372018-04-09 19:49:48 +080045import com.android.internal.colorextraction.ColorExtractor.GradientColors;
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
Lucas Dupin78949b82018-04-03 18:54:39 -070057import java.util.Arrays;
58import java.util.HashSet;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080059import java.util.function.Consumer;
60
61@RunWith(AndroidTestingRunner.class)
62@TestableLooper.RunWithLooper
63@SmallTest
64public class ScrimControllerTest extends SysuiTestCase {
65
66 private SynchronousScrimController mScrimController;
67 private ScrimView mScrimBehind;
68 private ScrimView mScrimInFront;
shawnlin317db372018-04-09 19:49:48 +080069 private Consumer<Float> mScrimBehindAlphaCallback;
70 private Consumer<GradientColors> mScrimInFrontColorCallback;
Lucas Dupin82aa1632017-12-13 00:13:57 -080071 private Consumer<Integer> mScrimVisibilityCallback;
shawnlin317db372018-04-09 19:49:48 +080072 private float mScrimBehindAlpha;
73 private GradientColors mScrimInFrontColor;
Lucas Dupin82aa1632017-12-13 00:13:57 -080074 private int mScrimVisibility;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080075 private DozeParameters mDozeParamenters;
76 private WakeLock mWakeLock;
77 private boolean mAlwaysOnEnabled;
Lucas Dupin82aa1632017-12-13 00:13:57 -080078 private AlarmManager mAlarmManager;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080079
80 @Before
81 public void setup() {
Lucas Dupin067136c2018-03-27 18:03:25 -070082 mScrimBehind = spy(new ScrimView(getContext()));
Lucas Dupin9e3fa102017-11-08 17:16:55 -080083 mScrimInFront = new ScrimView(getContext());
Lucas Dupin9e3fa102017-11-08 17:16:55 -080084 mWakeLock = mock(WakeLock.class);
Lucas Dupin82aa1632017-12-13 00:13:57 -080085 mAlarmManager = mock(AlarmManager.class);
Lucas Dupin9e3fa102017-11-08 17:16:55 -080086 mAlwaysOnEnabled = true;
shawnlin317db372018-04-09 19:49:48 +080087 mScrimBehindAlphaCallback = (Float alpha) -> mScrimBehindAlpha = alpha;
88 mScrimInFrontColorCallback = (GradientColors color) -> mScrimInFrontColor = color;
Lucas Dupin82aa1632017-12-13 00:13:57 -080089 mScrimVisibilityCallback = (Integer visible) -> mScrimVisibility = visible;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080090 mDozeParamenters = mock(DozeParameters.class);
91 when(mDozeParamenters.getAlwaysOn()).thenAnswer(invocation -> mAlwaysOnEnabled);
Lucas Dupin43d0d732017-11-16 11:23:49 -080092 when(mDozeParamenters.getDisplayNeedsBlanking()).thenReturn(true);
shawnlin317db372018-04-09 19:49:48 +080093 mScrimController = new SynchronousScrimController(mScrimBehind, mScrimInFront,
94 mScrimBehindAlphaCallback, mScrimInFrontColorCallback, mScrimVisibilityCallback,
95 mDozeParamenters, mAlarmManager);
Lucas Dupin9e3fa102017-11-08 17:16:55 -080096 }
97
98 @Test
99 public void initialState() {
100 Assert.assertEquals("ScrimController should start initialized",
101 mScrimController.getState(), ScrimState.UNINITIALIZED);
102 }
103
104 @Test
105 public void transitionToKeyguard() {
106 mScrimController.transitionTo(ScrimState.KEYGUARD);
107 mScrimController.finishAnimationsImmediately();
108 // Front scrim should be transparent
109 // Back scrim should be visible without tint
Lucas Dupin82aa1632017-12-13 00:13:57 -0800110 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800111 assertScrimTint(mScrimBehind, false /* tinted */);
112 }
113
114 @Test
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700115 public void transitionToAod_withRegularWallpaper() {
116 mScrimController.transitionTo(ScrimState.AOD);
117 mScrimController.finishAnimationsImmediately();
118 // Front scrim should be transparent
119 // Back scrim should be visible with tint
Lucas Dupin82aa1632017-12-13 00:13:57 -0800120 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700121 assertScrimTint(mScrimBehind, true /* tinted */);
122 assertScrimTint(mScrimInFront, true /* tinted */);
123 }
124
125 @Test
126 public void transitionToAod_withAodWallpaper() {
127 mScrimController.setWallpaperSupportsAmbientMode(true);
128 mScrimController.transitionTo(ScrimState.AOD);
129 mScrimController.finishAnimationsImmediately();
130 // Front scrim should be transparent
131 // Back scrim should be transparent
Lucas Dupin82aa1632017-12-13 00:13:57 -0800132 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
133
134 // Move on to PULSING and check if the back scrim is still transparent
135 mScrimController.transitionTo(ScrimState.PULSING);
136 mScrimController.finishAnimationsImmediately();
137 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700138 }
139
140 @Test
141 public void transitionToAod_withAodWallpaperAndLockScreenWallpaper() {
142 ScrimState.AOD.mKeyguardUpdateMonitor = new KeyguardUpdateMonitor(getContext()) {
143 @Override
144 public boolean hasLockscreenWallpaper() {
145 return true;
146 }
147 };
148 mScrimController.setWallpaperSupportsAmbientMode(true);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800149 mScrimController.transitionTo(ScrimState.AOD);
150 mScrimController.finishAnimationsImmediately();
151 // Front scrim should be transparent
152 // Back scrim should be visible with tint
Lucas Dupin82aa1632017-12-13 00:13:57 -0800153 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800154 assertScrimTint(mScrimBehind, true /* tinted */);
155 assertScrimTint(mScrimInFront, true /* tinted */);
156 }
157
158 @Test
Michael Wrightcae88752018-04-16 23:13:54 +0100159 public void transitionToAod_withFrontAlphaUpdates() {
160 // Assert that setting the AOD front scrim alpha doesn't take effect in a non-AOD state.
161 mScrimController.transitionTo(ScrimState.KEYGUARD);
162 mScrimController.setAodFrontScrimAlpha(0.5f);
163 mScrimController.finishAnimationsImmediately();
164 // Front scrim should be transparent
165 // Back scrim should be visible without tint
166 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
167
168 // ... but that it does take effect once we enter the AOD state.
169 mScrimController.transitionTo(ScrimState.AOD);
170 mScrimController.finishAnimationsImmediately();
171 // Front scrim should be semi-transparent
172 // Back scrim should be visible
173 assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
174
175 // ... and that if we set it while we're in AOD, it does take immediate effect.
176 mScrimController.setAodFrontScrimAlpha(1f);
177 assertScrimVisibility(VISIBILITY_FULLY_OPAQUE, VISIBILITY_FULLY_OPAQUE);
178
179 // ... and make sure we recall the previous front scrim alpha even if we transition away
180 // for a bit.
181 mScrimController.transitionTo(ScrimState.UNLOCKED);
182 mScrimController.transitionTo(ScrimState.AOD);
183 mScrimController.finishAnimationsImmediately();
184 assertScrimVisibility(VISIBILITY_FULLY_OPAQUE, VISIBILITY_FULLY_OPAQUE);
185
186 // Reset value since enums are static.
187 mScrimController.setAodFrontScrimAlpha(0f);
188 }
189
190 @Test
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800191 public void transitionToPulsing() {
Lucas Dupin82aa1632017-12-13 00:13:57 -0800192 // Pre-condition
193 // Need to go to AoD first because PULSING doesn't change
194 // the back scrim opacity - otherwise it would hide AoD wallpapers.
195 mScrimController.setWallpaperSupportsAmbientMode(false);
196 mScrimController.transitionTo(ScrimState.AOD);
197 mScrimController.finishAnimationsImmediately();
198 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
199
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800200 mScrimController.transitionTo(ScrimState.PULSING);
201 mScrimController.finishAnimationsImmediately();
202 // Front scrim should be transparent
203 // Back scrim should be visible with tint
204 // Pulse callback should have been invoked
Lucas Dupin82aa1632017-12-13 00:13:57 -0800205 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800206 assertScrimTint(mScrimBehind, true /* tinted */);
207 }
208
209 @Test
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800210 public void transitionToKeyguardBouncer() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800211 mScrimController.transitionTo(ScrimState.BOUNCER);
212 mScrimController.finishAnimationsImmediately();
213 // Front scrim should be transparent
214 // Back scrim should be visible without tint
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800215 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
216 assertScrimTint(mScrimBehind, false /* tinted */);
217 }
218
219 @Test
220 public void transitionToBouncer() {
Lucas Dupin05726cd2018-03-13 14:00:24 -0700221 mScrimController.transitionTo(ScrimState.BOUNCER_SCRIMMED);
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800222 mScrimController.finishAnimationsImmediately();
223 // Front scrim should be transparent
224 // Back scrim should be visible without tint
225 assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800226 assertScrimTint(mScrimBehind, false /* tinted */);
227 }
228
229 @Test
230 public void transitionToUnlocked() {
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800231 mScrimController.setPanelExpansion(0f);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800232 mScrimController.transitionTo(ScrimState.UNLOCKED);
233 mScrimController.finishAnimationsImmediately();
234 // Front scrim should be transparent
235 // Back scrim should be transparent
Lucas Dupin82aa1632017-12-13 00:13:57 -0800236 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800237 assertScrimTint(mScrimBehind, false /* tinted */);
238 assertScrimTint(mScrimInFront, false /* tinted */);
239
240 // Back scrim should be visible after start dragging
241 mScrimController.setPanelExpansion(0.5f);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800242 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800243 }
244
245 @Test
shawnlin317db372018-04-09 19:49:48 +0800246 public void panelExpansion() {
247 mScrimController.setPanelExpansion(0f);
248 mScrimController.setPanelExpansion(0.5f);
249 mScrimController.transitionTo(ScrimState.UNLOCKED);
250 mScrimController.finishAnimationsImmediately();
251
252 reset(mScrimBehind);
253 mScrimController.setPanelExpansion(0f);
254 mScrimController.setPanelExpansion(1.0f);
255 mScrimController.onPreDraw();
256
257 Assert.assertEquals("Scrim alpha should change after setPanelExpansion",
258 mScrimBehindAlpha, mScrimBehind.getViewAlpha(), 0.01f);
259
260 mScrimController.setPanelExpansion(0f);
261 mScrimController.onPreDraw();
262
263 Assert.assertEquals("Scrim alpha should change after setPanelExpansion",
264 mScrimBehindAlpha, mScrimBehind.getViewAlpha(), 0.01f);
265 }
266
267 @Test
Lucas Dupin67f02632018-03-12 11:08:31 -0700268 public void panelExpansionAffectsAlpha() {
269 mScrimController.setPanelExpansion(0f);
270 mScrimController.setPanelExpansion(0.5f);
271 mScrimController.transitionTo(ScrimState.UNLOCKED);
272 mScrimController.finishAnimationsImmediately();
273
274 final float scrimAlpha = mScrimBehind.getViewAlpha();
Lucas Dupin067136c2018-03-27 18:03:25 -0700275 reset(mScrimBehind);
Lucas Dupin67f02632018-03-12 11:08:31 -0700276 mScrimController.setExpansionAffectsAlpha(false);
277 mScrimController.setPanelExpansion(0.8f);
Lucas Dupin067136c2018-03-27 18:03:25 -0700278 verifyZeroInteractions(mScrimBehind);
Lucas Dupin67f02632018-03-12 11:08:31 -0700279 Assert.assertEquals("Scrim opacity shouldn't change when setExpansionAffectsAlpha "
280 + "is false", scrimAlpha, mScrimBehind.getViewAlpha(), 0.01f);
281
282 mScrimController.setExpansionAffectsAlpha(true);
283 mScrimController.setPanelExpansion(0.1f);
284 Assert.assertNotEquals("Scrim opacity should change when setExpansionAffectsAlpha "
285 + "is true", scrimAlpha, mScrimBehind.getViewAlpha(), 0.01f);
286 }
287
288 @Test
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800289 public void transitionToUnlockedFromAod() {
290 // Simulate unlock with fingerprint
291 mScrimController.transitionTo(ScrimState.AOD);
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800292 mScrimController.setPanelExpansion(0f);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800293 mScrimController.finishAnimationsImmediately();
294 mScrimController.transitionTo(ScrimState.UNLOCKED);
295 // Immediately tinted after the transition starts
296 assertScrimTint(mScrimInFront, true /* tinted */);
297 assertScrimTint(mScrimBehind, true /* tinted */);
298 mScrimController.finishAnimationsImmediately();
299 // Front scrim should be transparent
300 // Back scrim should be transparent
301 // Neither scrims should be tinted anymore after the animation.
Lucas Dupin82aa1632017-12-13 00:13:57 -0800302 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800303 assertScrimTint(mScrimInFront, false /* tinted */);
304 assertScrimTint(mScrimBehind, false /* tinted */);
305 }
306
307 @Test
Lucas Dupinea0116e2018-04-05 10:09:29 -0700308 public void scrimBlanksBeforeLeavingAod() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800309 // Simulate unlock with fingerprint
310 mScrimController.transitionTo(ScrimState.AOD);
311 mScrimController.finishAnimationsImmediately();
312 mScrimController.transitionTo(ScrimState.UNLOCKED,
313 new ScrimController.Callback() {
314 @Override
315 public void onDisplayBlanked() {
316 // Front scrim should be black in the middle of the transition
317 Assert.assertTrue("Scrim should be visible during transition. Alpha: "
318 + mScrimInFront.getViewAlpha(), mScrimInFront.getViewAlpha() > 0);
319 assertScrimTint(mScrimInFront, true /* tinted */);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800320 Assert.assertSame("Scrim should be visible during transition.",
321 mScrimVisibility, VISIBILITY_FULLY_OPAQUE);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800322 }
323 });
324 mScrimController.finishAnimationsImmediately();
325 }
326
327 @Test
328 public void testScrimCallback() {
329 int[] callOrder = {0, 0, 0};
330 int[] currentCall = {0};
331 mScrimController.transitionTo(ScrimState.AOD, new ScrimController.Callback() {
332 @Override
333 public void onStart() {
334 callOrder[0] = ++currentCall[0];
335 }
336
337 @Override
338 public void onDisplayBlanked() {
339 callOrder[1] = ++currentCall[0];
340 }
341
342 @Override
343 public void onFinished() {
344 callOrder[2] = ++currentCall[0];
345 }
346 });
347 mScrimController.finishAnimationsImmediately();
348 Assert.assertEquals("onStart called in wrong order", 1, callOrder[0]);
349 Assert.assertEquals("onDisplayBlanked called in wrong order", 2, callOrder[1]);
350 Assert.assertEquals("onFinished called in wrong order", 3, callOrder[2]);
351 }
352
353 @Test
354 public void testScrimCallbacksWithoutAmbientDisplay() {
355 mAlwaysOnEnabled = false;
356 testScrimCallback();
357 }
358
359 @Test
360 public void testScrimCallbackCancelled() {
361 boolean[] cancelledCalled = {false};
362 mScrimController.transitionTo(ScrimState.AOD, new ScrimController.Callback() {
363 @Override
364 public void onCancelled() {
365 cancelledCalled[0] = true;
366 }
367 });
368 mScrimController.transitionTo(ScrimState.PULSING);
369 Assert.assertTrue("onCancelled should have been called", cancelledCalled[0]);
370 }
371
372 @Test
Lucas Dupineea53b32017-12-18 13:47:14 -0800373 public void testHoldsWakeLock_whenAOD() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800374 mScrimController.transitionTo(ScrimState.AOD);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800375 verify(mWakeLock).acquire();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800376 verify(mWakeLock, never()).release();
377 mScrimController.finishAnimationsImmediately();
Lucas Dupin82aa1632017-12-13 00:13:57 -0800378 verify(mWakeLock).release();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800379 }
380
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800381 @Test
Lucas Dupineea53b32017-12-18 13:47:14 -0800382 public void testDoesNotHoldWakeLock_whenUnlocking() {
383 mScrimController.transitionTo(ScrimState.UNLOCKED);
384 mScrimController.finishAnimationsImmediately();
385 verifyZeroInteractions(mWakeLock);
386 }
387
388 @Test
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800389 public void testCallbackInvokedOnSameStateTransition() {
390 mScrimController.transitionTo(ScrimState.UNLOCKED);
391 mScrimController.finishAnimationsImmediately();
392 ScrimController.Callback callback = mock(ScrimController.Callback.class);
393 mScrimController.transitionTo(ScrimState.UNLOCKED, callback);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800394 verify(callback).onFinished();
395 }
396
397 @Test
398 public void testHoldsAodWallpaperAnimationLock() {
399 // Pre-conditions
400 mScrimController.transitionTo(ScrimState.AOD);
401 mScrimController.finishAnimationsImmediately();
402 reset(mWakeLock);
403
404 mScrimController.onHideWallpaperTimeout();
405 verify(mWakeLock).acquire();
406 verify(mWakeLock, never()).release();
407 mScrimController.finishAnimationsImmediately();
408 verify(mWakeLock).release();
409 }
410
411 @Test
Lucas Dupin16cfe452018-02-08 13:14:50 -0800412 public void testWillHideAodWallpaper() {
Lucas Dupin82aa1632017-12-13 00:13:57 -0800413 mScrimController.setWallpaperSupportsAmbientMode(true);
414 mScrimController.transitionTo(ScrimState.AOD);
415 verify(mAlarmManager).setExact(anyInt(), anyLong(), any(), any(), any());
416 mScrimController.transitionTo(ScrimState.KEYGUARD);
417 verify(mAlarmManager).cancel(any(AlarmManager.OnAlarmListener.class));
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800418 }
419
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800420 @Test
421 public void testConservesExpansionOpacityAfterTransition() {
422 mScrimController.transitionTo(ScrimState.UNLOCKED);
423 mScrimController.setPanelExpansion(0.5f);
424 mScrimController.finishAnimationsImmediately();
425
426 final float expandedAlpha = mScrimBehind.getViewAlpha();
427
428 mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR);
429 mScrimController.finishAnimationsImmediately();
430 mScrimController.transitionTo(ScrimState.UNLOCKED);
431 mScrimController.finishAnimationsImmediately();
432
433 Assert.assertEquals("Scrim expansion opacity wasn't conserved when transitioning back",
434 expandedAlpha, mScrimBehind.getViewAlpha(), 0.01f);
435 }
436
437 @Test
438 public void cancelsOldAnimationBeforeBlanking() {
439 mScrimController.transitionTo(ScrimState.AOD);
440 mScrimController.finishAnimationsImmediately();
441 // Consume whatever value we had before
442 mScrimController.wasAnimationJustCancelled();
443
444 mScrimController.transitionTo(ScrimState.KEYGUARD);
445 mScrimController.finishAnimationsImmediately();
446 Assert.assertTrue(mScrimController.wasAnimationJustCancelled());
447 }
448
Lucas Dupinb380c882018-02-25 21:57:17 -0800449 /**
450 * Number of visible notifications affects scrim opacity.
451 */
452 @Test
453 public void testNotificationDensity() {
454 mScrimController.transitionTo(ScrimState.KEYGUARD);
455 mScrimController.finishAnimationsImmediately();
456
457 mScrimController.setNotificationCount(0);
458 mScrimController.finishAnimationsImmediately();
459 Assert.assertEquals("lower density when no notifications",
460 ScrimController.GRADIENT_SCRIM_ALPHA, mScrimBehind.getViewAlpha(), 0.01f);
461
462 mScrimController.setNotificationCount(3);
463 mScrimController.finishAnimationsImmediately();
464 Assert.assertEquals("stronger density when notifications are visible",
465 ScrimController.GRADIENT_SCRIM_ALPHA_BUSY, mScrimBehind.getViewAlpha(), 0.01f);
466 }
467
468 /**
469 * Moving from/to states conserves old notification density.
470 */
471 @Test
472 public void testConservesNotificationDensity() {
473 testConservesNotificationDensity(0 /* count */, ScrimController.GRADIENT_SCRIM_ALPHA);
474 testConservesNotificationDensity(3 /* count */, ScrimController.GRADIENT_SCRIM_ALPHA_BUSY);
475 }
476
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800477 @Test
Lucas Dupin38962d72018-03-14 12:41:39 -0700478 public void testScrimFocus() {
479 mScrimController.transitionTo(ScrimState.AOD);
480 Assert.assertFalse("Should not be focusable on AOD", mScrimBehind.isFocusable());
481 Assert.assertFalse("Should not be focusable on AOD", mScrimInFront.isFocusable());
482
483 mScrimController.transitionTo(ScrimState.KEYGUARD);
484 Assert.assertTrue("Should be focusable on keyguard", mScrimBehind.isFocusable());
485 Assert.assertTrue("Should be focusable on keyguard", mScrimInFront.isFocusable());
486 }
487
Lucas Dupind5107302018-03-19 15:30:29 -0700488 @Test
489 public void testHidesShowWhenLockedActivity() {
490 mScrimController.setWallpaperSupportsAmbientMode(true);
491 mScrimController.setKeyguardOccluded(true);
492 mScrimController.transitionTo(ScrimState.AOD);
493 mScrimController.finishAnimationsImmediately();
494 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
495
496 mScrimController.transitionTo(ScrimState.PULSING);
497 mScrimController.finishAnimationsImmediately();
498 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
499 }
500
Lucas Dupin78949b82018-04-03 18:54:39 -0700501 @Test
502 public void testEatsTouchEvent() {
503 HashSet<ScrimState> eatsTouches =
504 new HashSet<>(Arrays.asList(ScrimState.AOD, ScrimState.PULSING));
505 for (ScrimState state : ScrimState.values()) {
506 if (state == ScrimState.UNINITIALIZED) {
507 continue;
508 }
509 mScrimController.transitionTo(state);
510 mScrimController.finishAnimationsImmediately();
511 Assert.assertEquals("Should be clickable unless AOD or PULSING, was: " + state,
512 mScrimBehind.getViewAlpha() != 0 && !eatsTouches.contains(state),
513 mScrimBehind.isClickable());
514 }
515 }
516
Lucas Dupinea0116e2018-04-05 10:09:29 -0700517 @Test
518 public void testAnimatesTransitionToAod() {
519 when(mDozeParamenters.shouldControlScreenOff()).thenReturn(false);
520 ScrimState.AOD.prepare(ScrimState.KEYGUARD);
521 Assert.assertFalse("No animation when ColorFade kicks in",
522 ScrimState.AOD.getAnimateChange());
523
524 reset(mDozeParamenters);
525 when(mDozeParamenters.shouldControlScreenOff()).thenReturn(true);
526 ScrimState.AOD.prepare(ScrimState.KEYGUARD);
527 Assert.assertTrue("Animate scrims when ColorFade won't be triggered",
528 ScrimState.AOD.getAnimateChange());
529 }
530
Lucas Dupin373356b2018-04-07 10:50:25 -0700531 @Test
532 public void testViewsDontHaveFocusHighlight() {
533 Assert.assertFalse("Scrim shouldn't have focus highlight",
534 mScrimInFront.getDefaultFocusHighlightEnabled());
535 Assert.assertFalse("Scrim shouldn't have focus highlight",
536 mScrimBehind.getDefaultFocusHighlightEnabled());
537 }
538
Lucas Dupinb380c882018-02-25 21:57:17 -0800539 /**
540 * Conserves old notification density after leaving state and coming back.
541 *
542 * @param count How many notification.
543 * @param expectedAlpha Expected alpha.
544 */
545 private void testConservesNotificationDensity(int count, float expectedAlpha) {
546 mScrimController.setNotificationCount(count);
547 mScrimController.transitionTo(ScrimState.UNLOCKED);
548 mScrimController.finishAnimationsImmediately();
549
550 mScrimController.transitionTo(ScrimState.KEYGUARD);
551 mScrimController.finishAnimationsImmediately();
552
553 Assert.assertEquals("Doesn't respect notification busyness after transition",
554 expectedAlpha, mScrimBehind.getViewAlpha(), 0.01f);
555 }
556
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800557 private void assertScrimTint(ScrimView scrimView, boolean tinted) {
558 final boolean viewIsTinted = scrimView.getTint() != Color.TRANSPARENT;
559 final String name = scrimView == mScrimInFront ? "front" : "back";
560 Assert.assertEquals("Tint test failed at state " + mScrimController.getState()
561 +" with scrim: " + name + " and tint: " + Integer.toHexString(scrimView.getTint()),
562 tinted, viewIsTinted);
563 }
564
Lucas Dupin82aa1632017-12-13 00:13:57 -0800565 private void assertScrimVisibility(int inFront, int behind) {
566 boolean inFrontVisible = inFront != ScrimController.VISIBILITY_FULLY_TRANSPARENT;
567 boolean behindVisible = behind != ScrimController.VISIBILITY_FULLY_TRANSPARENT;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800568 Assert.assertEquals("Unexpected front scrim visibility. Alpha is "
Lucas Dupin82aa1632017-12-13 00:13:57 -0800569 + mScrimInFront.getViewAlpha(), inFrontVisible, mScrimInFront.getViewAlpha() > 0);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800570 Assert.assertEquals("Unexpected back scrim visibility. Alpha is "
Lucas Dupin82aa1632017-12-13 00:13:57 -0800571 + mScrimBehind.getViewAlpha(), behindVisible, mScrimBehind.getViewAlpha() > 0);
572
573 final int visibility;
574 if (inFront == VISIBILITY_FULLY_OPAQUE || behind == VISIBILITY_FULLY_OPAQUE) {
575 visibility = VISIBILITY_FULLY_OPAQUE;
576 } else if (inFront > VISIBILITY_FULLY_TRANSPARENT || behind > VISIBILITY_FULLY_TRANSPARENT) {
577 visibility = VISIBILITY_SEMI_TRANSPARENT;
578 } else {
579 visibility = VISIBILITY_FULLY_TRANSPARENT;
580 }
581 Assert.assertEquals("Invalid visibility.", visibility, mScrimVisibility);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800582 }
583
584 /**
585 * Special version of ScrimController where animations have 0 duration for test purposes.
586 */
587 private class SynchronousScrimController extends ScrimController {
588
589 private FakeHandler mHandler;
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800590 private boolean mAnimationCancelled;
Lucas Dupin16cfe452018-02-08 13:14:50 -0800591 boolean mOnPreDrawCalled;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800592
shawnlin317db372018-04-09 19:49:48 +0800593 SynchronousScrimController(ScrimView scrimBehind, ScrimView scrimInFront,
594 Consumer<Float> scrimBehindAlphaListener,
595 Consumer<GradientColors> scrimInFrontColorListener,
Lucas Dupin82aa1632017-12-13 00:13:57 -0800596 Consumer<Integer> scrimVisibleListener, DozeParameters dozeParameters,
597 AlarmManager alarmManager) {
shawnlin317db372018-04-09 19:49:48 +0800598 super(scrimBehind, scrimInFront, scrimBehindAlphaListener, scrimInFrontColorListener,
Lucas Dupin82aa1632017-12-13 00:13:57 -0800599 scrimVisibleListener, dozeParameters, alarmManager);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800600 mHandler = new FakeHandler(Looper.myLooper());
601 }
602
Lucas Dupin16cfe452018-02-08 13:14:50 -0800603 @Override
604 public boolean onPreDraw() {
605 mOnPreDrawCalled = true;
606 return super.onPreDraw();
607 }
608
Lucas Dupin3503c5f2018-03-02 19:04:00 -0800609 void finishAnimationsImmediately() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800610 boolean[] animationFinished = {false};
611 setOnAnimationFinished(()-> animationFinished[0] = true);
612
613 // Execute code that will trigger animations.
614 onPreDraw();
615
616 // Force finish screen blanking.
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800617 mHandler.dispatchQueuedMessages();
618 // Force finish all animations.
619 endAnimation(mScrimBehind, TAG_KEY_ANIM);
620 endAnimation(mScrimInFront, TAG_KEY_ANIM);
621
622 if (!animationFinished[0]) {
623 throw new IllegalStateException("Animation never finished");
624 }
625 }
626
Lucas Dupin3503c5f2018-03-02 19:04:00 -0800627 boolean wasAnimationJustCancelled() {
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800628 final boolean wasCancelled = mAnimationCancelled;
629 mAnimationCancelled = false;
630 return wasCancelled;
631 }
632
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800633 private void endAnimation(View scrimView, int tag) {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800634 Animator animator = (Animator) scrimView.getTag(tag);
635 if (animator != null) {
636 animator.end();
637 }
638 }
639
640 @Override
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800641 protected void cancelAnimator(ValueAnimator previousAnimator) {
642 super.cancelAnimator(previousAnimator);
643 mAnimationCancelled = true;
644 }
645
646 @Override
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800647 protected Handler getHandler() {
648 return mHandler;
649 }
650
651 @Override
652 protected WakeLock createWakeLock() {
653 return mWakeLock;
654 }
Lucas Dupin8c7cb022018-02-05 10:49:03 -0800655
656 /**
657 * Do not wait for a frame since we're in a test environment.
658 * @param callback What to execute.
659 */
660 @Override
Lucas Dupin0791d972018-03-26 13:32:16 -0700661 protected void doOnTheNextFrame(Runnable callback) {
662 callback.run();
Lucas Dupin8c7cb022018-02-05 10:49:03 -0800663 }
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800664 }
665
666}