blob: 0bc304ee41b2cd3dc2174314160761da61b3cdda [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
Lucas Dupin9bee5822018-07-09 14:32:53 -0700155 public void setHasBackdrop_withAodWallpaperAndAlbumArt() {
156 mScrimController.setWallpaperSupportsAmbientMode(true);
157 mScrimController.transitionTo(ScrimState.AOD);
158 mScrimController.finishAnimationsImmediately();
159 mScrimController.setHasBackdrop(true);
160 mScrimController.finishAnimationsImmediately();
161 // Front scrim should be transparent
162 // Back scrim should be visible with tint
163 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
164 assertScrimTint(mScrimBehind, true /* tinted */);
165 assertScrimTint(mScrimInFront, true /* tinted */);
166 }
167
168 @Test
Michael Wrightcae88752018-04-16 23:13:54 +0100169 public void transitionToAod_withFrontAlphaUpdates() {
170 // Assert that setting the AOD front scrim alpha doesn't take effect in a non-AOD state.
171 mScrimController.transitionTo(ScrimState.KEYGUARD);
172 mScrimController.setAodFrontScrimAlpha(0.5f);
173 mScrimController.finishAnimationsImmediately();
174 // Front scrim should be transparent
175 // Back scrim should be visible without tint
176 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
177
178 // ... but that it does take effect once we enter the AOD state.
179 mScrimController.transitionTo(ScrimState.AOD);
180 mScrimController.finishAnimationsImmediately();
181 // Front scrim should be semi-transparent
182 // Back scrim should be visible
183 assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
184
185 // ... and that if we set it while we're in AOD, it does take immediate effect.
186 mScrimController.setAodFrontScrimAlpha(1f);
187 assertScrimVisibility(VISIBILITY_FULLY_OPAQUE, VISIBILITY_FULLY_OPAQUE);
188
189 // ... and make sure we recall the previous front scrim alpha even if we transition away
190 // for a bit.
191 mScrimController.transitionTo(ScrimState.UNLOCKED);
192 mScrimController.transitionTo(ScrimState.AOD);
193 mScrimController.finishAnimationsImmediately();
194 assertScrimVisibility(VISIBILITY_FULLY_OPAQUE, VISIBILITY_FULLY_OPAQUE);
195
Lucas Dupin69bda602018-05-18 17:24:52 -0700196 // ... and alpha updates should be completely ignored if always_on is off.
197 // Passing it forward would mess up the wake-up transition.
198 mAlwaysOnEnabled = false;
199 mScrimController.transitionTo(ScrimState.UNLOCKED);
200 mScrimController.transitionTo(ScrimState.AOD);
201 mScrimController.finishAnimationsImmediately();
202 mScrimController.setAodFrontScrimAlpha(0.3f);
203 Assert.assertEquals(ScrimState.AOD.getFrontAlpha(), mScrimInFront.getViewAlpha(), 0.001f);
204 Assert.assertNotEquals(0.3f, mScrimInFront.getViewAlpha(), 0.001f);
205
Michael Wrightcae88752018-04-16 23:13:54 +0100206 // Reset value since enums are static.
207 mScrimController.setAodFrontScrimAlpha(0f);
208 }
209
210 @Test
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800211 public void transitionToPulsing() {
Lucas Dupin82aa1632017-12-13 00:13:57 -0800212 // Pre-condition
213 // Need to go to AoD first because PULSING doesn't change
214 // the back scrim opacity - otherwise it would hide AoD wallpapers.
215 mScrimController.setWallpaperSupportsAmbientMode(false);
216 mScrimController.transitionTo(ScrimState.AOD);
217 mScrimController.finishAnimationsImmediately();
218 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
219
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800220 mScrimController.transitionTo(ScrimState.PULSING);
221 mScrimController.finishAnimationsImmediately();
222 // Front scrim should be transparent
223 // Back scrim should be visible with tint
224 // Pulse callback should have been invoked
Lucas Dupin82aa1632017-12-13 00:13:57 -0800225 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800226 assertScrimTint(mScrimBehind, true /* tinted */);
227 }
228
229 @Test
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800230 public void transitionToKeyguardBouncer() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800231 mScrimController.transitionTo(ScrimState.BOUNCER);
232 mScrimController.finishAnimationsImmediately();
233 // Front scrim should be transparent
234 // Back scrim should be visible without tint
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800235 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
236 assertScrimTint(mScrimBehind, false /* tinted */);
237 }
238
239 @Test
240 public void transitionToBouncer() {
Lucas Dupin05726cd2018-03-13 14:00:24 -0700241 mScrimController.transitionTo(ScrimState.BOUNCER_SCRIMMED);
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800242 mScrimController.finishAnimationsImmediately();
243 // Front scrim should be transparent
244 // Back scrim should be visible without tint
245 assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800246 assertScrimTint(mScrimBehind, false /* tinted */);
247 }
248
249 @Test
250 public void transitionToUnlocked() {
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800251 mScrimController.setPanelExpansion(0f);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800252 mScrimController.transitionTo(ScrimState.UNLOCKED);
253 mScrimController.finishAnimationsImmediately();
254 // Front scrim should be transparent
255 // Back scrim should be transparent
Lucas Dupin82aa1632017-12-13 00:13:57 -0800256 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800257 assertScrimTint(mScrimBehind, false /* tinted */);
258 assertScrimTint(mScrimInFront, false /* tinted */);
259
260 // Back scrim should be visible after start dragging
261 mScrimController.setPanelExpansion(0.5f);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800262 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800263 }
264
265 @Test
Mady Mellor0c333772018-11-06 18:05:54 -0800266 public void transitionToBubbleExpanded() {
267 mScrimController.transitionTo(ScrimState.BUBBLE_EXPANDED);
268 mScrimController.finishAnimationsImmediately();
269
270 // Front scrim should be transparent
271 Assert.assertEquals(ScrimController.VISIBILITY_FULLY_TRANSPARENT,
272 mScrimInFront.getViewAlpha(), 0.0f);
273 // Back scrim should be visible
274 Assert.assertEquals(ScrimController.GRADIENT_SCRIM_ALPHA_BUSY,
275 mScrimBehind.getViewAlpha(), 0.0f);
276 }
277
278 @Test
Yohei Yukawa795f0102018-04-13 14:55:30 -0700279 public void scrimStateCallback() {
280 mScrimController.transitionTo(ScrimState.UNLOCKED);
281 mScrimController.finishAnimationsImmediately();
282 Assert.assertEquals(mScrimState, ScrimState.UNLOCKED);
283
284 mScrimController.transitionTo(ScrimState.BOUNCER);
285 mScrimController.finishAnimationsImmediately();
286 Assert.assertEquals(mScrimState, ScrimState.BOUNCER);
287
288 mScrimController.transitionTo(ScrimState.BOUNCER_SCRIMMED);
289 mScrimController.finishAnimationsImmediately();
290 Assert.assertEquals(mScrimState, ScrimState.BOUNCER_SCRIMMED);
291 }
292
293 @Test
shawnlin317db372018-04-09 19:49:48 +0800294 public void panelExpansion() {
295 mScrimController.setPanelExpansion(0f);
296 mScrimController.setPanelExpansion(0.5f);
297 mScrimController.transitionTo(ScrimState.UNLOCKED);
298 mScrimController.finishAnimationsImmediately();
299
300 reset(mScrimBehind);
301 mScrimController.setPanelExpansion(0f);
302 mScrimController.setPanelExpansion(1.0f);
303 mScrimController.onPreDraw();
304
305 Assert.assertEquals("Scrim alpha should change after setPanelExpansion",
306 mScrimBehindAlpha, mScrimBehind.getViewAlpha(), 0.01f);
307
308 mScrimController.setPanelExpansion(0f);
309 mScrimController.onPreDraw();
310
311 Assert.assertEquals("Scrim alpha should change after setPanelExpansion",
312 mScrimBehindAlpha, mScrimBehind.getViewAlpha(), 0.01f);
313 }
314
315 @Test
Lucas Dupin67f02632018-03-12 11:08:31 -0700316 public void panelExpansionAffectsAlpha() {
317 mScrimController.setPanelExpansion(0f);
318 mScrimController.setPanelExpansion(0.5f);
319 mScrimController.transitionTo(ScrimState.UNLOCKED);
320 mScrimController.finishAnimationsImmediately();
321
322 final float scrimAlpha = mScrimBehind.getViewAlpha();
Lucas Dupin067136c2018-03-27 18:03:25 -0700323 reset(mScrimBehind);
Lucas Dupin67f02632018-03-12 11:08:31 -0700324 mScrimController.setExpansionAffectsAlpha(false);
325 mScrimController.setPanelExpansion(0.8f);
Lucas Dupin067136c2018-03-27 18:03:25 -0700326 verifyZeroInteractions(mScrimBehind);
Lucas Dupin67f02632018-03-12 11:08:31 -0700327 Assert.assertEquals("Scrim opacity shouldn't change when setExpansionAffectsAlpha "
328 + "is false", scrimAlpha, mScrimBehind.getViewAlpha(), 0.01f);
329
330 mScrimController.setExpansionAffectsAlpha(true);
331 mScrimController.setPanelExpansion(0.1f);
332 Assert.assertNotEquals("Scrim opacity should change when setExpansionAffectsAlpha "
333 + "is true", scrimAlpha, mScrimBehind.getViewAlpha(), 0.01f);
334 }
335
336 @Test
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800337 public void transitionToUnlockedFromAod() {
338 // Simulate unlock with fingerprint
339 mScrimController.transitionTo(ScrimState.AOD);
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800340 mScrimController.setPanelExpansion(0f);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800341 mScrimController.finishAnimationsImmediately();
342 mScrimController.transitionTo(ScrimState.UNLOCKED);
343 // Immediately tinted after the transition starts
344 assertScrimTint(mScrimInFront, true /* tinted */);
345 assertScrimTint(mScrimBehind, true /* tinted */);
346 mScrimController.finishAnimationsImmediately();
347 // Front scrim should be transparent
348 // Back scrim should be transparent
349 // Neither scrims should be tinted anymore after the animation.
Lucas Dupin82aa1632017-12-13 00:13:57 -0800350 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800351 assertScrimTint(mScrimInFront, false /* tinted */);
352 assertScrimTint(mScrimBehind, false /* tinted */);
353 }
354
355 @Test
Lucas Dupinea0116e2018-04-05 10:09:29 -0700356 public void scrimBlanksBeforeLeavingAod() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800357 // Simulate unlock with fingerprint
358 mScrimController.transitionTo(ScrimState.AOD);
359 mScrimController.finishAnimationsImmediately();
360 mScrimController.transitionTo(ScrimState.UNLOCKED,
361 new ScrimController.Callback() {
362 @Override
363 public void onDisplayBlanked() {
364 // Front scrim should be black in the middle of the transition
365 Assert.assertTrue("Scrim should be visible during transition. Alpha: "
366 + mScrimInFront.getViewAlpha(), mScrimInFront.getViewAlpha() > 0);
367 assertScrimTint(mScrimInFront, true /* tinted */);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800368 Assert.assertSame("Scrim should be visible during transition.",
369 mScrimVisibility, VISIBILITY_FULLY_OPAQUE);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800370 }
371 });
372 mScrimController.finishAnimationsImmediately();
373 }
374
375 @Test
Lucas Dupineb840ea2018-06-01 00:28:58 -0700376 public void scrimBlanksWhenUnlockingFromPulse() {
377 boolean[] blanked = {false};
378 // Simulate unlock with fingerprint
379 mScrimController.transitionTo(ScrimState.PULSING);
380 mScrimController.finishAnimationsImmediately();
381 mScrimController.transitionTo(ScrimState.UNLOCKED,
382 new ScrimController.Callback() {
383 @Override
384 public void onDisplayBlanked() {
385 blanked[0] = true;
386 }
387 });
388 mScrimController.finishAnimationsImmediately();
389 Assert.assertTrue("Scrim should blank when unlocking from pulse.", blanked[0]);
390 }
391
392 @Test
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800393 public void testScrimCallback() {
394 int[] callOrder = {0, 0, 0};
395 int[] currentCall = {0};
396 mScrimController.transitionTo(ScrimState.AOD, new ScrimController.Callback() {
397 @Override
398 public void onStart() {
399 callOrder[0] = ++currentCall[0];
400 }
401
402 @Override
403 public void onDisplayBlanked() {
404 callOrder[1] = ++currentCall[0];
405 }
406
407 @Override
408 public void onFinished() {
409 callOrder[2] = ++currentCall[0];
410 }
411 });
412 mScrimController.finishAnimationsImmediately();
413 Assert.assertEquals("onStart called in wrong order", 1, callOrder[0]);
414 Assert.assertEquals("onDisplayBlanked called in wrong order", 2, callOrder[1]);
415 Assert.assertEquals("onFinished called in wrong order", 3, callOrder[2]);
416 }
417
418 @Test
419 public void testScrimCallbacksWithoutAmbientDisplay() {
420 mAlwaysOnEnabled = false;
421 testScrimCallback();
422 }
423
424 @Test
425 public void testScrimCallbackCancelled() {
426 boolean[] cancelledCalled = {false};
427 mScrimController.transitionTo(ScrimState.AOD, new ScrimController.Callback() {
428 @Override
429 public void onCancelled() {
430 cancelledCalled[0] = true;
431 }
432 });
433 mScrimController.transitionTo(ScrimState.PULSING);
434 Assert.assertTrue("onCancelled should have been called", cancelledCalled[0]);
435 }
436
437 @Test
Lucas Dupineea53b32017-12-18 13:47:14 -0800438 public void testHoldsWakeLock_whenAOD() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800439 mScrimController.transitionTo(ScrimState.AOD);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800440 verify(mWakeLock).acquire();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800441 verify(mWakeLock, never()).release();
442 mScrimController.finishAnimationsImmediately();
Lucas Dupin82aa1632017-12-13 00:13:57 -0800443 verify(mWakeLock).release();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800444 }
445
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800446 @Test
Lucas Dupineea53b32017-12-18 13:47:14 -0800447 public void testDoesNotHoldWakeLock_whenUnlocking() {
448 mScrimController.transitionTo(ScrimState.UNLOCKED);
449 mScrimController.finishAnimationsImmediately();
450 verifyZeroInteractions(mWakeLock);
451 }
452
453 @Test
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800454 public void testCallbackInvokedOnSameStateTransition() {
455 mScrimController.transitionTo(ScrimState.UNLOCKED);
456 mScrimController.finishAnimationsImmediately();
457 ScrimController.Callback callback = mock(ScrimController.Callback.class);
458 mScrimController.transitionTo(ScrimState.UNLOCKED, callback);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800459 verify(callback).onFinished();
460 }
461
462 @Test
463 public void testHoldsAodWallpaperAnimationLock() {
464 // Pre-conditions
465 mScrimController.transitionTo(ScrimState.AOD);
466 mScrimController.finishAnimationsImmediately();
467 reset(mWakeLock);
468
469 mScrimController.onHideWallpaperTimeout();
470 verify(mWakeLock).acquire();
471 verify(mWakeLock, never()).release();
472 mScrimController.finishAnimationsImmediately();
473 verify(mWakeLock).release();
474 }
475
476 @Test
Lucas Dupin16cfe452018-02-08 13:14:50 -0800477 public void testWillHideAodWallpaper() {
Lucas Dupin82aa1632017-12-13 00:13:57 -0800478 mScrimController.setWallpaperSupportsAmbientMode(true);
479 mScrimController.transitionTo(ScrimState.AOD);
480 verify(mAlarmManager).setExact(anyInt(), anyLong(), any(), any(), any());
481 mScrimController.transitionTo(ScrimState.KEYGUARD);
482 verify(mAlarmManager).cancel(any(AlarmManager.OnAlarmListener.class));
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800483 }
484
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800485 @Test
486 public void testConservesExpansionOpacityAfterTransition() {
487 mScrimController.transitionTo(ScrimState.UNLOCKED);
488 mScrimController.setPanelExpansion(0.5f);
489 mScrimController.finishAnimationsImmediately();
490
491 final float expandedAlpha = mScrimBehind.getViewAlpha();
492
493 mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR);
494 mScrimController.finishAnimationsImmediately();
495 mScrimController.transitionTo(ScrimState.UNLOCKED);
496 mScrimController.finishAnimationsImmediately();
497
498 Assert.assertEquals("Scrim expansion opacity wasn't conserved when transitioning back",
499 expandedAlpha, mScrimBehind.getViewAlpha(), 0.01f);
500 }
501
502 @Test
503 public void cancelsOldAnimationBeforeBlanking() {
504 mScrimController.transitionTo(ScrimState.AOD);
505 mScrimController.finishAnimationsImmediately();
506 // Consume whatever value we had before
507 mScrimController.wasAnimationJustCancelled();
508
509 mScrimController.transitionTo(ScrimState.KEYGUARD);
510 mScrimController.finishAnimationsImmediately();
511 Assert.assertTrue(mScrimController.wasAnimationJustCancelled());
512 }
513
Lucas Dupinb380c882018-02-25 21:57:17 -0800514 /**
515 * Number of visible notifications affects scrim opacity.
516 */
517 @Test
518 public void testNotificationDensity() {
519 mScrimController.transitionTo(ScrimState.KEYGUARD);
520 mScrimController.finishAnimationsImmediately();
521
522 mScrimController.setNotificationCount(0);
523 mScrimController.finishAnimationsImmediately();
524 Assert.assertEquals("lower density when no notifications",
525 ScrimController.GRADIENT_SCRIM_ALPHA, mScrimBehind.getViewAlpha(), 0.01f);
526
527 mScrimController.setNotificationCount(3);
528 mScrimController.finishAnimationsImmediately();
529 Assert.assertEquals("stronger density when notifications are visible",
530 ScrimController.GRADIENT_SCRIM_ALPHA_BUSY, mScrimBehind.getViewAlpha(), 0.01f);
531 }
532
533 /**
534 * Moving from/to states conserves old notification density.
535 */
536 @Test
537 public void testConservesNotificationDensity() {
538 testConservesNotificationDensity(0 /* count */, ScrimController.GRADIENT_SCRIM_ALPHA);
539 testConservesNotificationDensity(3 /* count */, ScrimController.GRADIENT_SCRIM_ALPHA_BUSY);
540 }
541
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800542 @Test
Lucas Dupin38962d72018-03-14 12:41:39 -0700543 public void testScrimFocus() {
544 mScrimController.transitionTo(ScrimState.AOD);
545 Assert.assertFalse("Should not be focusable on AOD", mScrimBehind.isFocusable());
546 Assert.assertFalse("Should not be focusable on AOD", mScrimInFront.isFocusable());
547
548 mScrimController.transitionTo(ScrimState.KEYGUARD);
549 Assert.assertTrue("Should be focusable on keyguard", mScrimBehind.isFocusable());
550 Assert.assertTrue("Should be focusable on keyguard", mScrimInFront.isFocusable());
551 }
552
Lucas Dupind5107302018-03-19 15:30:29 -0700553 @Test
554 public void testHidesShowWhenLockedActivity() {
555 mScrimController.setWallpaperSupportsAmbientMode(true);
556 mScrimController.setKeyguardOccluded(true);
557 mScrimController.transitionTo(ScrimState.AOD);
558 mScrimController.finishAnimationsImmediately();
559 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
560
561 mScrimController.transitionTo(ScrimState.PULSING);
562 mScrimController.finishAnimationsImmediately();
563 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
564 }
565
Lucas Dupin78949b82018-04-03 18:54:39 -0700566 @Test
Lucas Dupin63d72172018-06-06 11:42:55 -0700567 public void testHidesShowWhenLockedActivity_whenAlreadyInAod() {
568 mScrimController.setWallpaperSupportsAmbientMode(true);
569 mScrimController.transitionTo(ScrimState.AOD);
570 mScrimController.finishAnimationsImmediately();
571 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
572
573 mScrimController.setKeyguardOccluded(true);
574 mScrimController.finishAnimationsImmediately();
575 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
576 }
577
578 @Test
Lucas Dupin78949b82018-04-03 18:54:39 -0700579 public void testEatsTouchEvent() {
580 HashSet<ScrimState> eatsTouches =
581 new HashSet<>(Arrays.asList(ScrimState.AOD, ScrimState.PULSING));
582 for (ScrimState state : ScrimState.values()) {
583 if (state == ScrimState.UNINITIALIZED) {
584 continue;
585 }
586 mScrimController.transitionTo(state);
587 mScrimController.finishAnimationsImmediately();
588 Assert.assertEquals("Should be clickable unless AOD or PULSING, was: " + state,
589 mScrimBehind.getViewAlpha() != 0 && !eatsTouches.contains(state),
590 mScrimBehind.isClickable());
591 }
592 }
593
Lucas Dupinea0116e2018-04-05 10:09:29 -0700594 @Test
595 public void testAnimatesTransitionToAod() {
596 when(mDozeParamenters.shouldControlScreenOff()).thenReturn(false);
597 ScrimState.AOD.prepare(ScrimState.KEYGUARD);
598 Assert.assertFalse("No animation when ColorFade kicks in",
599 ScrimState.AOD.getAnimateChange());
600
601 reset(mDozeParamenters);
602 when(mDozeParamenters.shouldControlScreenOff()).thenReturn(true);
603 ScrimState.AOD.prepare(ScrimState.KEYGUARD);
604 Assert.assertTrue("Animate scrims when ColorFade won't be triggered",
605 ScrimState.AOD.getAnimateChange());
606 }
607
Lucas Dupin373356b2018-04-07 10:50:25 -0700608 @Test
609 public void testViewsDontHaveFocusHighlight() {
610 Assert.assertFalse("Scrim shouldn't have focus highlight",
611 mScrimInFront.getDefaultFocusHighlightEnabled());
612 Assert.assertFalse("Scrim shouldn't have focus highlight",
613 mScrimBehind.getDefaultFocusHighlightEnabled());
614 }
615
Lucas Dupinb380c882018-02-25 21:57:17 -0800616 /**
617 * Conserves old notification density after leaving state and coming back.
618 *
619 * @param count How many notification.
620 * @param expectedAlpha Expected alpha.
621 */
622 private void testConservesNotificationDensity(int count, float expectedAlpha) {
623 mScrimController.setNotificationCount(count);
624 mScrimController.transitionTo(ScrimState.UNLOCKED);
625 mScrimController.finishAnimationsImmediately();
626
627 mScrimController.transitionTo(ScrimState.KEYGUARD);
628 mScrimController.finishAnimationsImmediately();
629
630 Assert.assertEquals("Doesn't respect notification busyness after transition",
631 expectedAlpha, mScrimBehind.getViewAlpha(), 0.01f);
632 }
633
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800634 private void assertScrimTint(ScrimView scrimView, boolean tinted) {
635 final boolean viewIsTinted = scrimView.getTint() != Color.TRANSPARENT;
636 final String name = scrimView == mScrimInFront ? "front" : "back";
637 Assert.assertEquals("Tint test failed at state " + mScrimController.getState()
638 +" with scrim: " + name + " and tint: " + Integer.toHexString(scrimView.getTint()),
639 tinted, viewIsTinted);
640 }
641
Lucas Dupin82aa1632017-12-13 00:13:57 -0800642 private void assertScrimVisibility(int inFront, int behind) {
643 boolean inFrontVisible = inFront != ScrimController.VISIBILITY_FULLY_TRANSPARENT;
644 boolean behindVisible = behind != ScrimController.VISIBILITY_FULLY_TRANSPARENT;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800645 Assert.assertEquals("Unexpected front scrim visibility. Alpha is "
Lucas Dupin82aa1632017-12-13 00:13:57 -0800646 + mScrimInFront.getViewAlpha(), inFrontVisible, mScrimInFront.getViewAlpha() > 0);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800647 Assert.assertEquals("Unexpected back scrim visibility. Alpha is "
Lucas Dupin82aa1632017-12-13 00:13:57 -0800648 + mScrimBehind.getViewAlpha(), behindVisible, mScrimBehind.getViewAlpha() > 0);
649
650 final int visibility;
651 if (inFront == VISIBILITY_FULLY_OPAQUE || behind == VISIBILITY_FULLY_OPAQUE) {
652 visibility = VISIBILITY_FULLY_OPAQUE;
653 } else if (inFront > VISIBILITY_FULLY_TRANSPARENT || behind > VISIBILITY_FULLY_TRANSPARENT) {
654 visibility = VISIBILITY_SEMI_TRANSPARENT;
655 } else {
656 visibility = VISIBILITY_FULLY_TRANSPARENT;
657 }
658 Assert.assertEquals("Invalid visibility.", visibility, mScrimVisibility);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800659 }
660
661 /**
662 * Special version of ScrimController where animations have 0 duration for test purposes.
663 */
664 private class SynchronousScrimController extends ScrimController {
665
666 private FakeHandler mHandler;
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800667 private boolean mAnimationCancelled;
Lucas Dupin16cfe452018-02-08 13:14:50 -0800668 boolean mOnPreDrawCalled;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800669
shawnlin317db372018-04-09 19:49:48 +0800670 SynchronousScrimController(ScrimView scrimBehind, ScrimView scrimInFront,
Yohei Yukawa795f0102018-04-13 14:55:30 -0700671 TriConsumer<ScrimState, Float, GradientColors> scrimStateListener,
Lucas Dupin82aa1632017-12-13 00:13:57 -0800672 Consumer<Integer> scrimVisibleListener, DozeParameters dozeParameters,
673 AlarmManager alarmManager) {
Yohei Yukawa795f0102018-04-13 14:55:30 -0700674 super(scrimBehind, scrimInFront, scrimStateListener, scrimVisibleListener,
675 dozeParameters, alarmManager);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800676 mHandler = new FakeHandler(Looper.myLooper());
677 }
678
Lucas Dupin16cfe452018-02-08 13:14:50 -0800679 @Override
680 public boolean onPreDraw() {
681 mOnPreDrawCalled = true;
682 return super.onPreDraw();
683 }
684
Lucas Dupin3503c5f2018-03-02 19:04:00 -0800685 void finishAnimationsImmediately() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800686 boolean[] animationFinished = {false};
687 setOnAnimationFinished(()-> animationFinished[0] = true);
688
689 // Execute code that will trigger animations.
690 onPreDraw();
691
692 // Force finish screen blanking.
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800693 mHandler.dispatchQueuedMessages();
694 // Force finish all animations.
695 endAnimation(mScrimBehind, TAG_KEY_ANIM);
696 endAnimation(mScrimInFront, TAG_KEY_ANIM);
697
698 if (!animationFinished[0]) {
699 throw new IllegalStateException("Animation never finished");
700 }
701 }
702
Lucas Dupin3503c5f2018-03-02 19:04:00 -0800703 boolean wasAnimationJustCancelled() {
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800704 final boolean wasCancelled = mAnimationCancelled;
705 mAnimationCancelled = false;
706 return wasCancelled;
707 }
708
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800709 private void endAnimation(View scrimView, int tag) {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800710 Animator animator = (Animator) scrimView.getTag(tag);
711 if (animator != null) {
712 animator.end();
713 }
714 }
715
716 @Override
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800717 protected void cancelAnimator(ValueAnimator previousAnimator) {
718 super.cancelAnimator(previousAnimator);
719 mAnimationCancelled = true;
720 }
721
722 @Override
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800723 protected Handler getHandler() {
724 return mHandler;
725 }
726
727 @Override
728 protected WakeLock createWakeLock() {
729 return mWakeLock;
730 }
Lucas Dupin8c7cb022018-02-05 10:49:03 -0800731
732 /**
733 * Do not wait for a frame since we're in a test environment.
734 * @param callback What to execute.
735 */
736 @Override
Lucas Dupin0791d972018-03-26 13:32:16 -0700737 protected void doOnTheNextFrame(Runnable callback) {
738 callback.run();
Lucas Dupin8c7cb022018-02-05 10:49:03 -0800739 }
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800740 }
741
742}