blob: 89d562a2099cee04e367bc48470035caeac48246 [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;
Yohei Yukawa795f0102018-04-13 14:55:30 -070046import com.android.internal.util.function.TriConsumer;
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;
Yohei Yukawa795f0102018-04-13 14:55:30 -070069 private ScrimState mScrimState;
shawnlin317db372018-04-09 19:49:48 +080070 private float mScrimBehindAlpha;
71 private GradientColors mScrimInFrontColor;
Lucas Dupin82aa1632017-12-13 00:13:57 -080072 private int mScrimVisibility;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080073 private DozeParameters mDozeParamenters;
74 private WakeLock mWakeLock;
75 private boolean mAlwaysOnEnabled;
Lucas Dupin82aa1632017-12-13 00:13:57 -080076 private AlarmManager mAlarmManager;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080077
Yohei Yukawa795f0102018-04-13 14:55:30 -070078
Lucas Dupin9e3fa102017-11-08 17:16:55 -080079 @Before
80 public void setup() {
Lucas Dupin067136c2018-03-27 18:03:25 -070081 mScrimBehind = spy(new ScrimView(getContext()));
Lucas Dupin9e3fa102017-11-08 17:16:55 -080082 mScrimInFront = new ScrimView(getContext());
Lucas Dupin9e3fa102017-11-08 17:16:55 -080083 mWakeLock = mock(WakeLock.class);
Lucas Dupin82aa1632017-12-13 00:13:57 -080084 mAlarmManager = mock(AlarmManager.class);
Lucas Dupin9e3fa102017-11-08 17:16:55 -080085 mAlwaysOnEnabled = true;
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);
shawnlin317db372018-04-09 19:49:48 +080089 mScrimController = new SynchronousScrimController(mScrimBehind, mScrimInFront,
Yohei Yukawa795f0102018-04-13 14:55:30 -070090 (scrimState, scrimBehindAlpha, scrimInFrontColor) -> {
91 mScrimState = scrimState;
92 mScrimBehindAlpha = scrimBehindAlpha;
93 mScrimInFrontColor = scrimInFrontColor;
94 },
95 visible -> mScrimVisibility = visible, mDozeParamenters, mAlarmManager);
Lucas Dupinf8463ee2018-06-11 16:18:15 -070096 mScrimController.setHasBackdrop(false);
Lucas Dupin9e3fa102017-11-08 17:16:55 -080097 }
98
99 @Test
100 public void initialState() {
101 Assert.assertEquals("ScrimController should start initialized",
102 mScrimController.getState(), ScrimState.UNINITIALIZED);
103 }
104
105 @Test
106 public void transitionToKeyguard() {
107 mScrimController.transitionTo(ScrimState.KEYGUARD);
108 mScrimController.finishAnimationsImmediately();
109 // Front scrim should be transparent
110 // Back scrim should be visible without tint
Lucas Dupin82aa1632017-12-13 00:13:57 -0800111 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800112 assertScrimTint(mScrimBehind, false /* tinted */);
113 }
114
115 @Test
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700116 public void transitionToAod_withRegularWallpaper() {
117 mScrimController.transitionTo(ScrimState.AOD);
118 mScrimController.finishAnimationsImmediately();
119 // Front scrim should be transparent
120 // Back scrim should be visible with tint
Lucas Dupin82aa1632017-12-13 00:13:57 -0800121 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700122 assertScrimTint(mScrimBehind, true /* tinted */);
123 assertScrimTint(mScrimInFront, true /* tinted */);
124 }
125
126 @Test
127 public void transitionToAod_withAodWallpaper() {
128 mScrimController.setWallpaperSupportsAmbientMode(true);
129 mScrimController.transitionTo(ScrimState.AOD);
130 mScrimController.finishAnimationsImmediately();
131 // Front scrim should be transparent
132 // Back scrim should be transparent
Lucas Dupin82aa1632017-12-13 00:13:57 -0800133 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
134
135 // Move on to PULSING and check if the back scrim is still transparent
136 mScrimController.transitionTo(ScrimState.PULSING);
137 mScrimController.finishAnimationsImmediately();
138 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700139 }
140
141 @Test
142 public void transitionToAod_withAodWallpaperAndLockScreenWallpaper() {
Lucas Dupinf8463ee2018-06-11 16:18:15 -0700143 mScrimController.setHasBackdrop(true);
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700144 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
Michael Wrightcae88752018-04-16 23:13:54 +0100155 public void transitionToAod_withFrontAlphaUpdates() {
156 // Assert that setting the AOD front scrim alpha doesn't take effect in a non-AOD state.
157 mScrimController.transitionTo(ScrimState.KEYGUARD);
158 mScrimController.setAodFrontScrimAlpha(0.5f);
159 mScrimController.finishAnimationsImmediately();
160 // Front scrim should be transparent
161 // Back scrim should be visible without tint
162 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
163
164 // ... but that it does take effect once we enter the AOD state.
165 mScrimController.transitionTo(ScrimState.AOD);
166 mScrimController.finishAnimationsImmediately();
167 // Front scrim should be semi-transparent
168 // Back scrim should be visible
169 assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
170
171 // ... and that if we set it while we're in AOD, it does take immediate effect.
172 mScrimController.setAodFrontScrimAlpha(1f);
173 assertScrimVisibility(VISIBILITY_FULLY_OPAQUE, VISIBILITY_FULLY_OPAQUE);
174
175 // ... and make sure we recall the previous front scrim alpha even if we transition away
176 // for a bit.
177 mScrimController.transitionTo(ScrimState.UNLOCKED);
178 mScrimController.transitionTo(ScrimState.AOD);
179 mScrimController.finishAnimationsImmediately();
180 assertScrimVisibility(VISIBILITY_FULLY_OPAQUE, VISIBILITY_FULLY_OPAQUE);
181
Lucas Dupin69bda602018-05-18 17:24:52 -0700182 // ... and alpha updates should be completely ignored if always_on is off.
183 // Passing it forward would mess up the wake-up transition.
184 mAlwaysOnEnabled = false;
185 mScrimController.transitionTo(ScrimState.UNLOCKED);
186 mScrimController.transitionTo(ScrimState.AOD);
187 mScrimController.finishAnimationsImmediately();
188 mScrimController.setAodFrontScrimAlpha(0.3f);
189 Assert.assertEquals(ScrimState.AOD.getFrontAlpha(), mScrimInFront.getViewAlpha(), 0.001f);
190 Assert.assertNotEquals(0.3f, mScrimInFront.getViewAlpha(), 0.001f);
191
Michael Wrightcae88752018-04-16 23:13:54 +0100192 // Reset value since enums are static.
193 mScrimController.setAodFrontScrimAlpha(0f);
194 }
195
196 @Test
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800197 public void transitionToPulsing() {
Lucas Dupin82aa1632017-12-13 00:13:57 -0800198 // Pre-condition
199 // Need to go to AoD first because PULSING doesn't change
200 // the back scrim opacity - otherwise it would hide AoD wallpapers.
201 mScrimController.setWallpaperSupportsAmbientMode(false);
202 mScrimController.transitionTo(ScrimState.AOD);
203 mScrimController.finishAnimationsImmediately();
204 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
205
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800206 mScrimController.transitionTo(ScrimState.PULSING);
207 mScrimController.finishAnimationsImmediately();
208 // Front scrim should be transparent
209 // Back scrim should be visible with tint
210 // Pulse callback should have been invoked
Lucas Dupin82aa1632017-12-13 00:13:57 -0800211 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800212 assertScrimTint(mScrimBehind, true /* tinted */);
213 }
214
215 @Test
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800216 public void transitionToKeyguardBouncer() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800217 mScrimController.transitionTo(ScrimState.BOUNCER);
218 mScrimController.finishAnimationsImmediately();
219 // Front scrim should be transparent
220 // Back scrim should be visible without tint
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800221 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
222 assertScrimTint(mScrimBehind, false /* tinted */);
223 }
224
225 @Test
226 public void transitionToBouncer() {
Lucas Dupin05726cd2018-03-13 14:00:24 -0700227 mScrimController.transitionTo(ScrimState.BOUNCER_SCRIMMED);
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800228 mScrimController.finishAnimationsImmediately();
229 // Front scrim should be transparent
230 // Back scrim should be visible without tint
231 assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800232 assertScrimTint(mScrimBehind, false /* tinted */);
233 }
234
235 @Test
236 public void transitionToUnlocked() {
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800237 mScrimController.setPanelExpansion(0f);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800238 mScrimController.transitionTo(ScrimState.UNLOCKED);
239 mScrimController.finishAnimationsImmediately();
240 // Front scrim should be transparent
241 // Back scrim should be transparent
Lucas Dupin82aa1632017-12-13 00:13:57 -0800242 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800243 assertScrimTint(mScrimBehind, false /* tinted */);
244 assertScrimTint(mScrimInFront, false /* tinted */);
245
246 // Back scrim should be visible after start dragging
247 mScrimController.setPanelExpansion(0.5f);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800248 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800249 }
250
251 @Test
Yohei Yukawa795f0102018-04-13 14:55:30 -0700252 public void scrimStateCallback() {
253 mScrimController.transitionTo(ScrimState.UNLOCKED);
254 mScrimController.finishAnimationsImmediately();
255 Assert.assertEquals(mScrimState, ScrimState.UNLOCKED);
256
257 mScrimController.transitionTo(ScrimState.BOUNCER);
258 mScrimController.finishAnimationsImmediately();
259 Assert.assertEquals(mScrimState, ScrimState.BOUNCER);
260
261 mScrimController.transitionTo(ScrimState.BOUNCER_SCRIMMED);
262 mScrimController.finishAnimationsImmediately();
263 Assert.assertEquals(mScrimState, ScrimState.BOUNCER_SCRIMMED);
264 }
265
266 @Test
shawnlin317db372018-04-09 19:49:48 +0800267 public void panelExpansion() {
268 mScrimController.setPanelExpansion(0f);
269 mScrimController.setPanelExpansion(0.5f);
270 mScrimController.transitionTo(ScrimState.UNLOCKED);
271 mScrimController.finishAnimationsImmediately();
272
273 reset(mScrimBehind);
274 mScrimController.setPanelExpansion(0f);
275 mScrimController.setPanelExpansion(1.0f);
276 mScrimController.onPreDraw();
277
278 Assert.assertEquals("Scrim alpha should change after setPanelExpansion",
279 mScrimBehindAlpha, mScrimBehind.getViewAlpha(), 0.01f);
280
281 mScrimController.setPanelExpansion(0f);
282 mScrimController.onPreDraw();
283
284 Assert.assertEquals("Scrim alpha should change after setPanelExpansion",
285 mScrimBehindAlpha, mScrimBehind.getViewAlpha(), 0.01f);
286 }
287
288 @Test
Lucas Dupin67f02632018-03-12 11:08:31 -0700289 public void panelExpansionAffectsAlpha() {
290 mScrimController.setPanelExpansion(0f);
291 mScrimController.setPanelExpansion(0.5f);
292 mScrimController.transitionTo(ScrimState.UNLOCKED);
293 mScrimController.finishAnimationsImmediately();
294
295 final float scrimAlpha = mScrimBehind.getViewAlpha();
Lucas Dupin067136c2018-03-27 18:03:25 -0700296 reset(mScrimBehind);
Lucas Dupin67f02632018-03-12 11:08:31 -0700297 mScrimController.setExpansionAffectsAlpha(false);
298 mScrimController.setPanelExpansion(0.8f);
Lucas Dupin067136c2018-03-27 18:03:25 -0700299 verifyZeroInteractions(mScrimBehind);
Lucas Dupin67f02632018-03-12 11:08:31 -0700300 Assert.assertEquals("Scrim opacity shouldn't change when setExpansionAffectsAlpha "
301 + "is false", scrimAlpha, mScrimBehind.getViewAlpha(), 0.01f);
302
303 mScrimController.setExpansionAffectsAlpha(true);
304 mScrimController.setPanelExpansion(0.1f);
305 Assert.assertNotEquals("Scrim opacity should change when setExpansionAffectsAlpha "
306 + "is true", scrimAlpha, mScrimBehind.getViewAlpha(), 0.01f);
307 }
308
309 @Test
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800310 public void transitionToUnlockedFromAod() {
311 // Simulate unlock with fingerprint
312 mScrimController.transitionTo(ScrimState.AOD);
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800313 mScrimController.setPanelExpansion(0f);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800314 mScrimController.finishAnimationsImmediately();
315 mScrimController.transitionTo(ScrimState.UNLOCKED);
316 // Immediately tinted after the transition starts
317 assertScrimTint(mScrimInFront, true /* tinted */);
318 assertScrimTint(mScrimBehind, true /* tinted */);
319 mScrimController.finishAnimationsImmediately();
320 // Front scrim should be transparent
321 // Back scrim should be transparent
322 // Neither scrims should be tinted anymore after the animation.
Lucas Dupin82aa1632017-12-13 00:13:57 -0800323 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800324 assertScrimTint(mScrimInFront, false /* tinted */);
325 assertScrimTint(mScrimBehind, false /* tinted */);
326 }
327
328 @Test
Lucas Dupinea0116e2018-04-05 10:09:29 -0700329 public void scrimBlanksBeforeLeavingAod() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800330 // Simulate unlock with fingerprint
331 mScrimController.transitionTo(ScrimState.AOD);
332 mScrimController.finishAnimationsImmediately();
333 mScrimController.transitionTo(ScrimState.UNLOCKED,
334 new ScrimController.Callback() {
335 @Override
336 public void onDisplayBlanked() {
337 // Front scrim should be black in the middle of the transition
338 Assert.assertTrue("Scrim should be visible during transition. Alpha: "
339 + mScrimInFront.getViewAlpha(), mScrimInFront.getViewAlpha() > 0);
340 assertScrimTint(mScrimInFront, true /* tinted */);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800341 Assert.assertSame("Scrim should be visible during transition.",
342 mScrimVisibility, VISIBILITY_FULLY_OPAQUE);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800343 }
344 });
345 mScrimController.finishAnimationsImmediately();
346 }
347
348 @Test
Lucas Dupineb840ea2018-06-01 00:28:58 -0700349 public void scrimBlanksWhenUnlockingFromPulse() {
350 boolean[] blanked = {false};
351 // Simulate unlock with fingerprint
352 mScrimController.transitionTo(ScrimState.PULSING);
353 mScrimController.finishAnimationsImmediately();
354 mScrimController.transitionTo(ScrimState.UNLOCKED,
355 new ScrimController.Callback() {
356 @Override
357 public void onDisplayBlanked() {
358 blanked[0] = true;
359 }
360 });
361 mScrimController.finishAnimationsImmediately();
362 Assert.assertTrue("Scrim should blank when unlocking from pulse.", blanked[0]);
363 }
364
365 @Test
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800366 public void testScrimCallback() {
367 int[] callOrder = {0, 0, 0};
368 int[] currentCall = {0};
369 mScrimController.transitionTo(ScrimState.AOD, new ScrimController.Callback() {
370 @Override
371 public void onStart() {
372 callOrder[0] = ++currentCall[0];
373 }
374
375 @Override
376 public void onDisplayBlanked() {
377 callOrder[1] = ++currentCall[0];
378 }
379
380 @Override
381 public void onFinished() {
382 callOrder[2] = ++currentCall[0];
383 }
384 });
385 mScrimController.finishAnimationsImmediately();
386 Assert.assertEquals("onStart called in wrong order", 1, callOrder[0]);
387 Assert.assertEquals("onDisplayBlanked called in wrong order", 2, callOrder[1]);
388 Assert.assertEquals("onFinished called in wrong order", 3, callOrder[2]);
389 }
390
391 @Test
392 public void testScrimCallbacksWithoutAmbientDisplay() {
393 mAlwaysOnEnabled = false;
394 testScrimCallback();
395 }
396
397 @Test
398 public void testScrimCallbackCancelled() {
399 boolean[] cancelledCalled = {false};
400 mScrimController.transitionTo(ScrimState.AOD, new ScrimController.Callback() {
401 @Override
402 public void onCancelled() {
403 cancelledCalled[0] = true;
404 }
405 });
406 mScrimController.transitionTo(ScrimState.PULSING);
407 Assert.assertTrue("onCancelled should have been called", cancelledCalled[0]);
408 }
409
410 @Test
Lucas Dupineea53b32017-12-18 13:47:14 -0800411 public void testHoldsWakeLock_whenAOD() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800412 mScrimController.transitionTo(ScrimState.AOD);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800413 verify(mWakeLock).acquire();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800414 verify(mWakeLock, never()).release();
415 mScrimController.finishAnimationsImmediately();
Lucas Dupin82aa1632017-12-13 00:13:57 -0800416 verify(mWakeLock).release();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800417 }
418
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800419 @Test
Lucas Dupineea53b32017-12-18 13:47:14 -0800420 public void testDoesNotHoldWakeLock_whenUnlocking() {
421 mScrimController.transitionTo(ScrimState.UNLOCKED);
422 mScrimController.finishAnimationsImmediately();
423 verifyZeroInteractions(mWakeLock);
424 }
425
426 @Test
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800427 public void testCallbackInvokedOnSameStateTransition() {
428 mScrimController.transitionTo(ScrimState.UNLOCKED);
429 mScrimController.finishAnimationsImmediately();
430 ScrimController.Callback callback = mock(ScrimController.Callback.class);
431 mScrimController.transitionTo(ScrimState.UNLOCKED, callback);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800432 verify(callback).onFinished();
433 }
434
435 @Test
436 public void testHoldsAodWallpaperAnimationLock() {
437 // Pre-conditions
438 mScrimController.transitionTo(ScrimState.AOD);
439 mScrimController.finishAnimationsImmediately();
440 reset(mWakeLock);
441
442 mScrimController.onHideWallpaperTimeout();
443 verify(mWakeLock).acquire();
444 verify(mWakeLock, never()).release();
445 mScrimController.finishAnimationsImmediately();
446 verify(mWakeLock).release();
447 }
448
449 @Test
Lucas Dupin16cfe452018-02-08 13:14:50 -0800450 public void testWillHideAodWallpaper() {
Lucas Dupin82aa1632017-12-13 00:13:57 -0800451 mScrimController.setWallpaperSupportsAmbientMode(true);
452 mScrimController.transitionTo(ScrimState.AOD);
453 verify(mAlarmManager).setExact(anyInt(), anyLong(), any(), any(), any());
454 mScrimController.transitionTo(ScrimState.KEYGUARD);
455 verify(mAlarmManager).cancel(any(AlarmManager.OnAlarmListener.class));
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800456 }
457
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800458 @Test
459 public void testConservesExpansionOpacityAfterTransition() {
460 mScrimController.transitionTo(ScrimState.UNLOCKED);
461 mScrimController.setPanelExpansion(0.5f);
462 mScrimController.finishAnimationsImmediately();
463
464 final float expandedAlpha = mScrimBehind.getViewAlpha();
465
466 mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR);
467 mScrimController.finishAnimationsImmediately();
468 mScrimController.transitionTo(ScrimState.UNLOCKED);
469 mScrimController.finishAnimationsImmediately();
470
471 Assert.assertEquals("Scrim expansion opacity wasn't conserved when transitioning back",
472 expandedAlpha, mScrimBehind.getViewAlpha(), 0.01f);
473 }
474
475 @Test
476 public void cancelsOldAnimationBeforeBlanking() {
477 mScrimController.transitionTo(ScrimState.AOD);
478 mScrimController.finishAnimationsImmediately();
479 // Consume whatever value we had before
480 mScrimController.wasAnimationJustCancelled();
481
482 mScrimController.transitionTo(ScrimState.KEYGUARD);
483 mScrimController.finishAnimationsImmediately();
484 Assert.assertTrue(mScrimController.wasAnimationJustCancelled());
485 }
486
Lucas Dupinb380c882018-02-25 21:57:17 -0800487 /**
488 * Number of visible notifications affects scrim opacity.
489 */
490 @Test
491 public void testNotificationDensity() {
492 mScrimController.transitionTo(ScrimState.KEYGUARD);
493 mScrimController.finishAnimationsImmediately();
494
495 mScrimController.setNotificationCount(0);
496 mScrimController.finishAnimationsImmediately();
497 Assert.assertEquals("lower density when no notifications",
498 ScrimController.GRADIENT_SCRIM_ALPHA, mScrimBehind.getViewAlpha(), 0.01f);
499
500 mScrimController.setNotificationCount(3);
501 mScrimController.finishAnimationsImmediately();
502 Assert.assertEquals("stronger density when notifications are visible",
503 ScrimController.GRADIENT_SCRIM_ALPHA_BUSY, mScrimBehind.getViewAlpha(), 0.01f);
504 }
505
506 /**
507 * Moving from/to states conserves old notification density.
508 */
509 @Test
510 public void testConservesNotificationDensity() {
511 testConservesNotificationDensity(0 /* count */, ScrimController.GRADIENT_SCRIM_ALPHA);
512 testConservesNotificationDensity(3 /* count */, ScrimController.GRADIENT_SCRIM_ALPHA_BUSY);
513 }
514
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800515 @Test
Lucas Dupin38962d72018-03-14 12:41:39 -0700516 public void testScrimFocus() {
517 mScrimController.transitionTo(ScrimState.AOD);
518 Assert.assertFalse("Should not be focusable on AOD", mScrimBehind.isFocusable());
519 Assert.assertFalse("Should not be focusable on AOD", mScrimInFront.isFocusable());
520
521 mScrimController.transitionTo(ScrimState.KEYGUARD);
522 Assert.assertTrue("Should be focusable on keyguard", mScrimBehind.isFocusable());
523 Assert.assertTrue("Should be focusable on keyguard", mScrimInFront.isFocusable());
524 }
525
Lucas Dupind5107302018-03-19 15:30:29 -0700526 @Test
527 public void testHidesShowWhenLockedActivity() {
528 mScrimController.setWallpaperSupportsAmbientMode(true);
529 mScrimController.setKeyguardOccluded(true);
530 mScrimController.transitionTo(ScrimState.AOD);
531 mScrimController.finishAnimationsImmediately();
532 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
533
534 mScrimController.transitionTo(ScrimState.PULSING);
535 mScrimController.finishAnimationsImmediately();
536 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
537 }
538
Lucas Dupin78949b82018-04-03 18:54:39 -0700539 @Test
Lucas Dupin63d72172018-06-06 11:42:55 -0700540 public void testHidesShowWhenLockedActivity_whenAlreadyInAod() {
541 mScrimController.setWallpaperSupportsAmbientMode(true);
542 mScrimController.transitionTo(ScrimState.AOD);
543 mScrimController.finishAnimationsImmediately();
544 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
545
546 mScrimController.setKeyguardOccluded(true);
547 mScrimController.finishAnimationsImmediately();
548 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
549 }
550
551 @Test
Lucas Dupin78949b82018-04-03 18:54:39 -0700552 public void testEatsTouchEvent() {
553 HashSet<ScrimState> eatsTouches =
554 new HashSet<>(Arrays.asList(ScrimState.AOD, ScrimState.PULSING));
555 for (ScrimState state : ScrimState.values()) {
556 if (state == ScrimState.UNINITIALIZED) {
557 continue;
558 }
559 mScrimController.transitionTo(state);
560 mScrimController.finishAnimationsImmediately();
561 Assert.assertEquals("Should be clickable unless AOD or PULSING, was: " + state,
562 mScrimBehind.getViewAlpha() != 0 && !eatsTouches.contains(state),
563 mScrimBehind.isClickable());
564 }
565 }
566
Lucas Dupinea0116e2018-04-05 10:09:29 -0700567 @Test
568 public void testAnimatesTransitionToAod() {
569 when(mDozeParamenters.shouldControlScreenOff()).thenReturn(false);
570 ScrimState.AOD.prepare(ScrimState.KEYGUARD);
571 Assert.assertFalse("No animation when ColorFade kicks in",
572 ScrimState.AOD.getAnimateChange());
573
574 reset(mDozeParamenters);
575 when(mDozeParamenters.shouldControlScreenOff()).thenReturn(true);
576 ScrimState.AOD.prepare(ScrimState.KEYGUARD);
577 Assert.assertTrue("Animate scrims when ColorFade won't be triggered",
578 ScrimState.AOD.getAnimateChange());
579 }
580
Lucas Dupin373356b2018-04-07 10:50:25 -0700581 @Test
582 public void testViewsDontHaveFocusHighlight() {
583 Assert.assertFalse("Scrim shouldn't have focus highlight",
584 mScrimInFront.getDefaultFocusHighlightEnabled());
585 Assert.assertFalse("Scrim shouldn't have focus highlight",
586 mScrimBehind.getDefaultFocusHighlightEnabled());
587 }
588
Lucas Dupinb380c882018-02-25 21:57:17 -0800589 /**
590 * Conserves old notification density after leaving state and coming back.
591 *
592 * @param count How many notification.
593 * @param expectedAlpha Expected alpha.
594 */
595 private void testConservesNotificationDensity(int count, float expectedAlpha) {
596 mScrimController.setNotificationCount(count);
597 mScrimController.transitionTo(ScrimState.UNLOCKED);
598 mScrimController.finishAnimationsImmediately();
599
600 mScrimController.transitionTo(ScrimState.KEYGUARD);
601 mScrimController.finishAnimationsImmediately();
602
603 Assert.assertEquals("Doesn't respect notification busyness after transition",
604 expectedAlpha, mScrimBehind.getViewAlpha(), 0.01f);
605 }
606
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800607 private void assertScrimTint(ScrimView scrimView, boolean tinted) {
608 final boolean viewIsTinted = scrimView.getTint() != Color.TRANSPARENT;
609 final String name = scrimView == mScrimInFront ? "front" : "back";
610 Assert.assertEquals("Tint test failed at state " + mScrimController.getState()
611 +" with scrim: " + name + " and tint: " + Integer.toHexString(scrimView.getTint()),
612 tinted, viewIsTinted);
613 }
614
Lucas Dupin82aa1632017-12-13 00:13:57 -0800615 private void assertScrimVisibility(int inFront, int behind) {
616 boolean inFrontVisible = inFront != ScrimController.VISIBILITY_FULLY_TRANSPARENT;
617 boolean behindVisible = behind != ScrimController.VISIBILITY_FULLY_TRANSPARENT;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800618 Assert.assertEquals("Unexpected front scrim visibility. Alpha is "
Lucas Dupin82aa1632017-12-13 00:13:57 -0800619 + mScrimInFront.getViewAlpha(), inFrontVisible, mScrimInFront.getViewAlpha() > 0);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800620 Assert.assertEquals("Unexpected back scrim visibility. Alpha is "
Lucas Dupin82aa1632017-12-13 00:13:57 -0800621 + mScrimBehind.getViewAlpha(), behindVisible, mScrimBehind.getViewAlpha() > 0);
622
623 final int visibility;
624 if (inFront == VISIBILITY_FULLY_OPAQUE || behind == VISIBILITY_FULLY_OPAQUE) {
625 visibility = VISIBILITY_FULLY_OPAQUE;
626 } else if (inFront > VISIBILITY_FULLY_TRANSPARENT || behind > VISIBILITY_FULLY_TRANSPARENT) {
627 visibility = VISIBILITY_SEMI_TRANSPARENT;
628 } else {
629 visibility = VISIBILITY_FULLY_TRANSPARENT;
630 }
631 Assert.assertEquals("Invalid visibility.", visibility, mScrimVisibility);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800632 }
633
634 /**
635 * Special version of ScrimController where animations have 0 duration for test purposes.
636 */
637 private class SynchronousScrimController extends ScrimController {
638
639 private FakeHandler mHandler;
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800640 private boolean mAnimationCancelled;
Lucas Dupin16cfe452018-02-08 13:14:50 -0800641 boolean mOnPreDrawCalled;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800642
shawnlin317db372018-04-09 19:49:48 +0800643 SynchronousScrimController(ScrimView scrimBehind, ScrimView scrimInFront,
Yohei Yukawa795f0102018-04-13 14:55:30 -0700644 TriConsumer<ScrimState, Float, GradientColors> scrimStateListener,
Lucas Dupin82aa1632017-12-13 00:13:57 -0800645 Consumer<Integer> scrimVisibleListener, DozeParameters dozeParameters,
646 AlarmManager alarmManager) {
Yohei Yukawa795f0102018-04-13 14:55:30 -0700647 super(scrimBehind, scrimInFront, scrimStateListener, scrimVisibleListener,
648 dozeParameters, alarmManager);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800649 mHandler = new FakeHandler(Looper.myLooper());
650 }
651
Lucas Dupin16cfe452018-02-08 13:14:50 -0800652 @Override
653 public boolean onPreDraw() {
654 mOnPreDrawCalled = true;
655 return super.onPreDraw();
656 }
657
Lucas Dupin3503c5f2018-03-02 19:04:00 -0800658 void finishAnimationsImmediately() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800659 boolean[] animationFinished = {false};
660 setOnAnimationFinished(()-> animationFinished[0] = true);
661
662 // Execute code that will trigger animations.
663 onPreDraw();
664
665 // Force finish screen blanking.
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800666 mHandler.dispatchQueuedMessages();
667 // Force finish all animations.
668 endAnimation(mScrimBehind, TAG_KEY_ANIM);
669 endAnimation(mScrimInFront, TAG_KEY_ANIM);
670
671 if (!animationFinished[0]) {
672 throw new IllegalStateException("Animation never finished");
673 }
674 }
675
Lucas Dupin3503c5f2018-03-02 19:04:00 -0800676 boolean wasAnimationJustCancelled() {
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800677 final boolean wasCancelled = mAnimationCancelled;
678 mAnimationCancelled = false;
679 return wasCancelled;
680 }
681
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800682 private void endAnimation(View scrimView, int tag) {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800683 Animator animator = (Animator) scrimView.getTag(tag);
684 if (animator != null) {
685 animator.end();
686 }
687 }
688
689 @Override
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800690 protected void cancelAnimator(ValueAnimator previousAnimator) {
691 super.cancelAnimator(previousAnimator);
692 mAnimationCancelled = true;
693 }
694
695 @Override
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800696 protected Handler getHandler() {
697 return mHandler;
698 }
699
700 @Override
701 protected WakeLock createWakeLock() {
702 return mWakeLock;
703 }
Lucas Dupin8c7cb022018-02-05 10:49:03 -0800704
705 /**
706 * Do not wait for a frame since we're in a test environment.
707 * @param callback What to execute.
708 */
709 @Override
Lucas Dupin0791d972018-03-26 13:32:16 -0700710 protected void doOnTheNextFrame(Runnable callback) {
711 callback.run();
Lucas Dupin8c7cb022018-02-05 10:49:03 -0800712 }
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800713 }
714
715}