blob: a2a866e79af3c4f1b07a69f8157c3999eb3f1915 [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 Dupin7517b5d2017-08-22 12:51:25 -070047import com.android.keyguard.KeyguardUpdateMonitor;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080048import com.android.systemui.SysuiTestCase;
49import com.android.systemui.statusbar.ScrimView;
50import com.android.systemui.util.wakelock.WakeLock;
51import com.android.systemui.utils.os.FakeHandler;
52
53import org.junit.Assert;
54import org.junit.Before;
55import org.junit.Test;
56import org.junit.runner.RunWith;
57
Lucas Dupin78949b82018-04-03 18:54:39 -070058import java.util.Arrays;
59import java.util.HashSet;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080060import java.util.function.Consumer;
61
62@RunWith(AndroidTestingRunner.class)
63@TestableLooper.RunWithLooper
64@SmallTest
65public class ScrimControllerTest extends SysuiTestCase {
66
67 private SynchronousScrimController mScrimController;
68 private ScrimView mScrimBehind;
69 private ScrimView mScrimInFront;
Yohei Yukawa795f0102018-04-13 14:55:30 -070070 private ScrimState mScrimState;
shawnlin317db372018-04-09 19:49:48 +080071 private float mScrimBehindAlpha;
72 private GradientColors mScrimInFrontColor;
Lucas Dupin82aa1632017-12-13 00:13:57 -080073 private int mScrimVisibility;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080074 private DozeParameters mDozeParamenters;
75 private WakeLock mWakeLock;
76 private boolean mAlwaysOnEnabled;
Lucas Dupin82aa1632017-12-13 00:13:57 -080077 private AlarmManager mAlarmManager;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080078
Yohei Yukawa795f0102018-04-13 14:55:30 -070079
Lucas Dupin9e3fa102017-11-08 17:16:55 -080080 @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;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080087 mDozeParamenters = mock(DozeParameters.class);
88 when(mDozeParamenters.getAlwaysOn()).thenAnswer(invocation -> mAlwaysOnEnabled);
Lucas Dupin43d0d732017-11-16 11:23:49 -080089 when(mDozeParamenters.getDisplayNeedsBlanking()).thenReturn(true);
shawnlin317db372018-04-09 19:49:48 +080090 mScrimController = new SynchronousScrimController(mScrimBehind, mScrimInFront,
Yohei Yukawa795f0102018-04-13 14:55:30 -070091 (scrimState, scrimBehindAlpha, scrimInFrontColor) -> {
92 mScrimState = scrimState;
93 mScrimBehindAlpha = scrimBehindAlpha;
94 mScrimInFrontColor = scrimInFrontColor;
95 },
96 visible -> mScrimVisibility = visible, mDozeParamenters, mAlarmManager);
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() {
143 ScrimState.AOD.mKeyguardUpdateMonitor = new KeyguardUpdateMonitor(getContext()) {
144 @Override
145 public boolean hasLockscreenWallpaper() {
146 return true;
147 }
148 };
149 mScrimController.setWallpaperSupportsAmbientMode(true);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800150 mScrimController.transitionTo(ScrimState.AOD);
151 mScrimController.finishAnimationsImmediately();
152 // Front scrim should be transparent
153 // Back scrim should be visible with tint
Lucas Dupin82aa1632017-12-13 00:13:57 -0800154 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800155 assertScrimTint(mScrimBehind, true /* tinted */);
156 assertScrimTint(mScrimInFront, true /* tinted */);
157 }
158
159 @Test
Michael Wrightcae88752018-04-16 23:13:54 +0100160 public void transitionToAod_withFrontAlphaUpdates() {
161 // Assert that setting the AOD front scrim alpha doesn't take effect in a non-AOD state.
162 mScrimController.transitionTo(ScrimState.KEYGUARD);
163 mScrimController.setAodFrontScrimAlpha(0.5f);
164 mScrimController.finishAnimationsImmediately();
165 // Front scrim should be transparent
166 // Back scrim should be visible without tint
167 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
168
169 // ... but that it does take effect once we enter the AOD state.
170 mScrimController.transitionTo(ScrimState.AOD);
171 mScrimController.finishAnimationsImmediately();
172 // Front scrim should be semi-transparent
173 // Back scrim should be visible
174 assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
175
176 // ... and that if we set it while we're in AOD, it does take immediate effect.
177 mScrimController.setAodFrontScrimAlpha(1f);
178 assertScrimVisibility(VISIBILITY_FULLY_OPAQUE, VISIBILITY_FULLY_OPAQUE);
179
180 // ... and make sure we recall the previous front scrim alpha even if we transition away
181 // for a bit.
182 mScrimController.transitionTo(ScrimState.UNLOCKED);
183 mScrimController.transitionTo(ScrimState.AOD);
184 mScrimController.finishAnimationsImmediately();
185 assertScrimVisibility(VISIBILITY_FULLY_OPAQUE, VISIBILITY_FULLY_OPAQUE);
186
Lucas Dupin69bda602018-05-18 17:24:52 -0700187 // ... and alpha updates should be completely ignored if always_on is off.
188 // Passing it forward would mess up the wake-up transition.
189 mAlwaysOnEnabled = false;
190 mScrimController.transitionTo(ScrimState.UNLOCKED);
191 mScrimController.transitionTo(ScrimState.AOD);
192 mScrimController.finishAnimationsImmediately();
193 mScrimController.setAodFrontScrimAlpha(0.3f);
194 Assert.assertEquals(ScrimState.AOD.getFrontAlpha(), mScrimInFront.getViewAlpha(), 0.001f);
195 Assert.assertNotEquals(0.3f, mScrimInFront.getViewAlpha(), 0.001f);
196
Michael Wrightcae88752018-04-16 23:13:54 +0100197 // Reset value since enums are static.
198 mScrimController.setAodFrontScrimAlpha(0f);
199 }
200
201 @Test
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800202 public void transitionToPulsing() {
Lucas Dupin82aa1632017-12-13 00:13:57 -0800203 // Pre-condition
204 // Need to go to AoD first because PULSING doesn't change
205 // the back scrim opacity - otherwise it would hide AoD wallpapers.
206 mScrimController.setWallpaperSupportsAmbientMode(false);
207 mScrimController.transitionTo(ScrimState.AOD);
208 mScrimController.finishAnimationsImmediately();
209 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
210
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800211 mScrimController.transitionTo(ScrimState.PULSING);
212 mScrimController.finishAnimationsImmediately();
213 // Front scrim should be transparent
214 // Back scrim should be visible with tint
215 // Pulse callback should have been invoked
Lucas Dupin82aa1632017-12-13 00:13:57 -0800216 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800217 assertScrimTint(mScrimBehind, true /* tinted */);
218 }
219
220 @Test
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800221 public void transitionToKeyguardBouncer() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800222 mScrimController.transitionTo(ScrimState.BOUNCER);
223 mScrimController.finishAnimationsImmediately();
224 // Front scrim should be transparent
225 // Back scrim should be visible without tint
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800226 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
227 assertScrimTint(mScrimBehind, false /* tinted */);
228 }
229
230 @Test
231 public void transitionToBouncer() {
Lucas Dupin05726cd2018-03-13 14:00:24 -0700232 mScrimController.transitionTo(ScrimState.BOUNCER_SCRIMMED);
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800233 mScrimController.finishAnimationsImmediately();
234 // Front scrim should be transparent
235 // Back scrim should be visible without tint
236 assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800237 assertScrimTint(mScrimBehind, false /* tinted */);
238 }
239
240 @Test
241 public void transitionToUnlocked() {
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800242 mScrimController.setPanelExpansion(0f);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800243 mScrimController.transitionTo(ScrimState.UNLOCKED);
244 mScrimController.finishAnimationsImmediately();
245 // Front scrim should be transparent
246 // Back scrim should be transparent
Lucas Dupin82aa1632017-12-13 00:13:57 -0800247 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800248 assertScrimTint(mScrimBehind, false /* tinted */);
249 assertScrimTint(mScrimInFront, false /* tinted */);
250
251 // Back scrim should be visible after start dragging
252 mScrimController.setPanelExpansion(0.5f);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800253 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800254 }
255
256 @Test
Yohei Yukawa795f0102018-04-13 14:55:30 -0700257 public void scrimStateCallback() {
258 mScrimController.transitionTo(ScrimState.UNLOCKED);
259 mScrimController.finishAnimationsImmediately();
260 Assert.assertEquals(mScrimState, ScrimState.UNLOCKED);
261
262 mScrimController.transitionTo(ScrimState.BOUNCER);
263 mScrimController.finishAnimationsImmediately();
264 Assert.assertEquals(mScrimState, ScrimState.BOUNCER);
265
266 mScrimController.transitionTo(ScrimState.BOUNCER_SCRIMMED);
267 mScrimController.finishAnimationsImmediately();
268 Assert.assertEquals(mScrimState, ScrimState.BOUNCER_SCRIMMED);
269 }
270
271 @Test
shawnlin317db372018-04-09 19:49:48 +0800272 public void panelExpansion() {
273 mScrimController.setPanelExpansion(0f);
274 mScrimController.setPanelExpansion(0.5f);
275 mScrimController.transitionTo(ScrimState.UNLOCKED);
276 mScrimController.finishAnimationsImmediately();
277
278 reset(mScrimBehind);
279 mScrimController.setPanelExpansion(0f);
280 mScrimController.setPanelExpansion(1.0f);
281 mScrimController.onPreDraw();
282
283 Assert.assertEquals("Scrim alpha should change after setPanelExpansion",
284 mScrimBehindAlpha, mScrimBehind.getViewAlpha(), 0.01f);
285
286 mScrimController.setPanelExpansion(0f);
287 mScrimController.onPreDraw();
288
289 Assert.assertEquals("Scrim alpha should change after setPanelExpansion",
290 mScrimBehindAlpha, mScrimBehind.getViewAlpha(), 0.01f);
291 }
292
293 @Test
Lucas Dupin67f02632018-03-12 11:08:31 -0700294 public void panelExpansionAffectsAlpha() {
295 mScrimController.setPanelExpansion(0f);
296 mScrimController.setPanelExpansion(0.5f);
297 mScrimController.transitionTo(ScrimState.UNLOCKED);
298 mScrimController.finishAnimationsImmediately();
299
300 final float scrimAlpha = mScrimBehind.getViewAlpha();
Lucas Dupin067136c2018-03-27 18:03:25 -0700301 reset(mScrimBehind);
Lucas Dupin67f02632018-03-12 11:08:31 -0700302 mScrimController.setExpansionAffectsAlpha(false);
303 mScrimController.setPanelExpansion(0.8f);
Lucas Dupin067136c2018-03-27 18:03:25 -0700304 verifyZeroInteractions(mScrimBehind);
Lucas Dupin67f02632018-03-12 11:08:31 -0700305 Assert.assertEquals("Scrim opacity shouldn't change when setExpansionAffectsAlpha "
306 + "is false", scrimAlpha, mScrimBehind.getViewAlpha(), 0.01f);
307
308 mScrimController.setExpansionAffectsAlpha(true);
309 mScrimController.setPanelExpansion(0.1f);
310 Assert.assertNotEquals("Scrim opacity should change when setExpansionAffectsAlpha "
311 + "is true", scrimAlpha, mScrimBehind.getViewAlpha(), 0.01f);
312 }
313
314 @Test
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800315 public void transitionToUnlockedFromAod() {
316 // Simulate unlock with fingerprint
317 mScrimController.transitionTo(ScrimState.AOD);
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800318 mScrimController.setPanelExpansion(0f);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800319 mScrimController.finishAnimationsImmediately();
320 mScrimController.transitionTo(ScrimState.UNLOCKED);
321 // Immediately tinted after the transition starts
322 assertScrimTint(mScrimInFront, true /* tinted */);
323 assertScrimTint(mScrimBehind, true /* tinted */);
324 mScrimController.finishAnimationsImmediately();
325 // Front scrim should be transparent
326 // Back scrim should be transparent
327 // Neither scrims should be tinted anymore after the animation.
Lucas Dupin82aa1632017-12-13 00:13:57 -0800328 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800329 assertScrimTint(mScrimInFront, false /* tinted */);
330 assertScrimTint(mScrimBehind, false /* tinted */);
331 }
332
333 @Test
Lucas Dupinea0116e2018-04-05 10:09:29 -0700334 public void scrimBlanksBeforeLeavingAod() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800335 // Simulate unlock with fingerprint
336 mScrimController.transitionTo(ScrimState.AOD);
337 mScrimController.finishAnimationsImmediately();
338 mScrimController.transitionTo(ScrimState.UNLOCKED,
339 new ScrimController.Callback() {
340 @Override
341 public void onDisplayBlanked() {
342 // Front scrim should be black in the middle of the transition
343 Assert.assertTrue("Scrim should be visible during transition. Alpha: "
344 + mScrimInFront.getViewAlpha(), mScrimInFront.getViewAlpha() > 0);
345 assertScrimTint(mScrimInFront, true /* tinted */);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800346 Assert.assertSame("Scrim should be visible during transition.",
347 mScrimVisibility, VISIBILITY_FULLY_OPAQUE);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800348 }
349 });
350 mScrimController.finishAnimationsImmediately();
351 }
352
353 @Test
354 public void testScrimCallback() {
355 int[] callOrder = {0, 0, 0};
356 int[] currentCall = {0};
357 mScrimController.transitionTo(ScrimState.AOD, new ScrimController.Callback() {
358 @Override
359 public void onStart() {
360 callOrder[0] = ++currentCall[0];
361 }
362
363 @Override
364 public void onDisplayBlanked() {
365 callOrder[1] = ++currentCall[0];
366 }
367
368 @Override
369 public void onFinished() {
370 callOrder[2] = ++currentCall[0];
371 }
372 });
373 mScrimController.finishAnimationsImmediately();
374 Assert.assertEquals("onStart called in wrong order", 1, callOrder[0]);
375 Assert.assertEquals("onDisplayBlanked called in wrong order", 2, callOrder[1]);
376 Assert.assertEquals("onFinished called in wrong order", 3, callOrder[2]);
377 }
378
379 @Test
380 public void testScrimCallbacksWithoutAmbientDisplay() {
381 mAlwaysOnEnabled = false;
382 testScrimCallback();
383 }
384
385 @Test
386 public void testScrimCallbackCancelled() {
387 boolean[] cancelledCalled = {false};
388 mScrimController.transitionTo(ScrimState.AOD, new ScrimController.Callback() {
389 @Override
390 public void onCancelled() {
391 cancelledCalled[0] = true;
392 }
393 });
394 mScrimController.transitionTo(ScrimState.PULSING);
395 Assert.assertTrue("onCancelled should have been called", cancelledCalled[0]);
396 }
397
398 @Test
Lucas Dupineea53b32017-12-18 13:47:14 -0800399 public void testHoldsWakeLock_whenAOD() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800400 mScrimController.transitionTo(ScrimState.AOD);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800401 verify(mWakeLock).acquire();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800402 verify(mWakeLock, never()).release();
403 mScrimController.finishAnimationsImmediately();
Lucas Dupin82aa1632017-12-13 00:13:57 -0800404 verify(mWakeLock).release();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800405 }
406
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800407 @Test
Lucas Dupineea53b32017-12-18 13:47:14 -0800408 public void testDoesNotHoldWakeLock_whenUnlocking() {
409 mScrimController.transitionTo(ScrimState.UNLOCKED);
410 mScrimController.finishAnimationsImmediately();
411 verifyZeroInteractions(mWakeLock);
412 }
413
414 @Test
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800415 public void testCallbackInvokedOnSameStateTransition() {
416 mScrimController.transitionTo(ScrimState.UNLOCKED);
417 mScrimController.finishAnimationsImmediately();
418 ScrimController.Callback callback = mock(ScrimController.Callback.class);
419 mScrimController.transitionTo(ScrimState.UNLOCKED, callback);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800420 verify(callback).onFinished();
421 }
422
423 @Test
424 public void testHoldsAodWallpaperAnimationLock() {
425 // Pre-conditions
426 mScrimController.transitionTo(ScrimState.AOD);
427 mScrimController.finishAnimationsImmediately();
428 reset(mWakeLock);
429
430 mScrimController.onHideWallpaperTimeout();
431 verify(mWakeLock).acquire();
432 verify(mWakeLock, never()).release();
433 mScrimController.finishAnimationsImmediately();
434 verify(mWakeLock).release();
435 }
436
437 @Test
Lucas Dupin16cfe452018-02-08 13:14:50 -0800438 public void testWillHideAodWallpaper() {
Lucas Dupin82aa1632017-12-13 00:13:57 -0800439 mScrimController.setWallpaperSupportsAmbientMode(true);
440 mScrimController.transitionTo(ScrimState.AOD);
441 verify(mAlarmManager).setExact(anyInt(), anyLong(), any(), any(), any());
442 mScrimController.transitionTo(ScrimState.KEYGUARD);
443 verify(mAlarmManager).cancel(any(AlarmManager.OnAlarmListener.class));
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800444 }
445
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800446 @Test
447 public void testConservesExpansionOpacityAfterTransition() {
448 mScrimController.transitionTo(ScrimState.UNLOCKED);
449 mScrimController.setPanelExpansion(0.5f);
450 mScrimController.finishAnimationsImmediately();
451
452 final float expandedAlpha = mScrimBehind.getViewAlpha();
453
454 mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR);
455 mScrimController.finishAnimationsImmediately();
456 mScrimController.transitionTo(ScrimState.UNLOCKED);
457 mScrimController.finishAnimationsImmediately();
458
459 Assert.assertEquals("Scrim expansion opacity wasn't conserved when transitioning back",
460 expandedAlpha, mScrimBehind.getViewAlpha(), 0.01f);
461 }
462
463 @Test
464 public void cancelsOldAnimationBeforeBlanking() {
465 mScrimController.transitionTo(ScrimState.AOD);
466 mScrimController.finishAnimationsImmediately();
467 // Consume whatever value we had before
468 mScrimController.wasAnimationJustCancelled();
469
470 mScrimController.transitionTo(ScrimState.KEYGUARD);
471 mScrimController.finishAnimationsImmediately();
472 Assert.assertTrue(mScrimController.wasAnimationJustCancelled());
473 }
474
Lucas Dupinb380c882018-02-25 21:57:17 -0800475 /**
476 * Number of visible notifications affects scrim opacity.
477 */
478 @Test
479 public void testNotificationDensity() {
480 mScrimController.transitionTo(ScrimState.KEYGUARD);
481 mScrimController.finishAnimationsImmediately();
482
483 mScrimController.setNotificationCount(0);
484 mScrimController.finishAnimationsImmediately();
485 Assert.assertEquals("lower density when no notifications",
486 ScrimController.GRADIENT_SCRIM_ALPHA, mScrimBehind.getViewAlpha(), 0.01f);
487
488 mScrimController.setNotificationCount(3);
489 mScrimController.finishAnimationsImmediately();
490 Assert.assertEquals("stronger density when notifications are visible",
491 ScrimController.GRADIENT_SCRIM_ALPHA_BUSY, mScrimBehind.getViewAlpha(), 0.01f);
492 }
493
494 /**
495 * Moving from/to states conserves old notification density.
496 */
497 @Test
498 public void testConservesNotificationDensity() {
499 testConservesNotificationDensity(0 /* count */, ScrimController.GRADIENT_SCRIM_ALPHA);
500 testConservesNotificationDensity(3 /* count */, ScrimController.GRADIENT_SCRIM_ALPHA_BUSY);
501 }
502
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800503 @Test
Lucas Dupin38962d72018-03-14 12:41:39 -0700504 public void testScrimFocus() {
505 mScrimController.transitionTo(ScrimState.AOD);
506 Assert.assertFalse("Should not be focusable on AOD", mScrimBehind.isFocusable());
507 Assert.assertFalse("Should not be focusable on AOD", mScrimInFront.isFocusable());
508
509 mScrimController.transitionTo(ScrimState.KEYGUARD);
510 Assert.assertTrue("Should be focusable on keyguard", mScrimBehind.isFocusable());
511 Assert.assertTrue("Should be focusable on keyguard", mScrimInFront.isFocusable());
512 }
513
Lucas Dupind5107302018-03-19 15:30:29 -0700514 @Test
515 public void testHidesShowWhenLockedActivity() {
516 mScrimController.setWallpaperSupportsAmbientMode(true);
517 mScrimController.setKeyguardOccluded(true);
518 mScrimController.transitionTo(ScrimState.AOD);
519 mScrimController.finishAnimationsImmediately();
520 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
521
522 mScrimController.transitionTo(ScrimState.PULSING);
523 mScrimController.finishAnimationsImmediately();
524 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
525 }
526
Lucas Dupin78949b82018-04-03 18:54:39 -0700527 @Test
528 public void testEatsTouchEvent() {
529 HashSet<ScrimState> eatsTouches =
530 new HashSet<>(Arrays.asList(ScrimState.AOD, ScrimState.PULSING));
531 for (ScrimState state : ScrimState.values()) {
532 if (state == ScrimState.UNINITIALIZED) {
533 continue;
534 }
535 mScrimController.transitionTo(state);
536 mScrimController.finishAnimationsImmediately();
537 Assert.assertEquals("Should be clickable unless AOD or PULSING, was: " + state,
538 mScrimBehind.getViewAlpha() != 0 && !eatsTouches.contains(state),
539 mScrimBehind.isClickable());
540 }
541 }
542
Lucas Dupinea0116e2018-04-05 10:09:29 -0700543 @Test
544 public void testAnimatesTransitionToAod() {
545 when(mDozeParamenters.shouldControlScreenOff()).thenReturn(false);
546 ScrimState.AOD.prepare(ScrimState.KEYGUARD);
547 Assert.assertFalse("No animation when ColorFade kicks in",
548 ScrimState.AOD.getAnimateChange());
549
550 reset(mDozeParamenters);
551 when(mDozeParamenters.shouldControlScreenOff()).thenReturn(true);
552 ScrimState.AOD.prepare(ScrimState.KEYGUARD);
553 Assert.assertTrue("Animate scrims when ColorFade won't be triggered",
554 ScrimState.AOD.getAnimateChange());
555 }
556
Lucas Dupin373356b2018-04-07 10:50:25 -0700557 @Test
558 public void testViewsDontHaveFocusHighlight() {
559 Assert.assertFalse("Scrim shouldn't have focus highlight",
560 mScrimInFront.getDefaultFocusHighlightEnabled());
561 Assert.assertFalse("Scrim shouldn't have focus highlight",
562 mScrimBehind.getDefaultFocusHighlightEnabled());
563 }
564
Lucas Dupinb380c882018-02-25 21:57:17 -0800565 /**
566 * Conserves old notification density after leaving state and coming back.
567 *
568 * @param count How many notification.
569 * @param expectedAlpha Expected alpha.
570 */
571 private void testConservesNotificationDensity(int count, float expectedAlpha) {
572 mScrimController.setNotificationCount(count);
573 mScrimController.transitionTo(ScrimState.UNLOCKED);
574 mScrimController.finishAnimationsImmediately();
575
576 mScrimController.transitionTo(ScrimState.KEYGUARD);
577 mScrimController.finishAnimationsImmediately();
578
579 Assert.assertEquals("Doesn't respect notification busyness after transition",
580 expectedAlpha, mScrimBehind.getViewAlpha(), 0.01f);
581 }
582
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800583 private void assertScrimTint(ScrimView scrimView, boolean tinted) {
584 final boolean viewIsTinted = scrimView.getTint() != Color.TRANSPARENT;
585 final String name = scrimView == mScrimInFront ? "front" : "back";
586 Assert.assertEquals("Tint test failed at state " + mScrimController.getState()
587 +" with scrim: " + name + " and tint: " + Integer.toHexString(scrimView.getTint()),
588 tinted, viewIsTinted);
589 }
590
Lucas Dupin82aa1632017-12-13 00:13:57 -0800591 private void assertScrimVisibility(int inFront, int behind) {
592 boolean inFrontVisible = inFront != ScrimController.VISIBILITY_FULLY_TRANSPARENT;
593 boolean behindVisible = behind != ScrimController.VISIBILITY_FULLY_TRANSPARENT;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800594 Assert.assertEquals("Unexpected front scrim visibility. Alpha is "
Lucas Dupin82aa1632017-12-13 00:13:57 -0800595 + mScrimInFront.getViewAlpha(), inFrontVisible, mScrimInFront.getViewAlpha() > 0);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800596 Assert.assertEquals("Unexpected back scrim visibility. Alpha is "
Lucas Dupin82aa1632017-12-13 00:13:57 -0800597 + mScrimBehind.getViewAlpha(), behindVisible, mScrimBehind.getViewAlpha() > 0);
598
599 final int visibility;
600 if (inFront == VISIBILITY_FULLY_OPAQUE || behind == VISIBILITY_FULLY_OPAQUE) {
601 visibility = VISIBILITY_FULLY_OPAQUE;
602 } else if (inFront > VISIBILITY_FULLY_TRANSPARENT || behind > VISIBILITY_FULLY_TRANSPARENT) {
603 visibility = VISIBILITY_SEMI_TRANSPARENT;
604 } else {
605 visibility = VISIBILITY_FULLY_TRANSPARENT;
606 }
607 Assert.assertEquals("Invalid visibility.", visibility, mScrimVisibility);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800608 }
609
610 /**
611 * Special version of ScrimController where animations have 0 duration for test purposes.
612 */
613 private class SynchronousScrimController extends ScrimController {
614
615 private FakeHandler mHandler;
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800616 private boolean mAnimationCancelled;
Lucas Dupin16cfe452018-02-08 13:14:50 -0800617 boolean mOnPreDrawCalled;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800618
shawnlin317db372018-04-09 19:49:48 +0800619 SynchronousScrimController(ScrimView scrimBehind, ScrimView scrimInFront,
Yohei Yukawa795f0102018-04-13 14:55:30 -0700620 TriConsumer<ScrimState, Float, GradientColors> scrimStateListener,
Lucas Dupin82aa1632017-12-13 00:13:57 -0800621 Consumer<Integer> scrimVisibleListener, DozeParameters dozeParameters,
622 AlarmManager alarmManager) {
Yohei Yukawa795f0102018-04-13 14:55:30 -0700623 super(scrimBehind, scrimInFront, scrimStateListener, scrimVisibleListener,
624 dozeParameters, alarmManager);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800625 mHandler = new FakeHandler(Looper.myLooper());
626 }
627
Lucas Dupin16cfe452018-02-08 13:14:50 -0800628 @Override
629 public boolean onPreDraw() {
630 mOnPreDrawCalled = true;
631 return super.onPreDraw();
632 }
633
Lucas Dupin3503c5f2018-03-02 19:04:00 -0800634 void finishAnimationsImmediately() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800635 boolean[] animationFinished = {false};
636 setOnAnimationFinished(()-> animationFinished[0] = true);
637
638 // Execute code that will trigger animations.
639 onPreDraw();
640
641 // Force finish screen blanking.
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800642 mHandler.dispatchQueuedMessages();
643 // Force finish all animations.
644 endAnimation(mScrimBehind, TAG_KEY_ANIM);
645 endAnimation(mScrimInFront, TAG_KEY_ANIM);
646
647 if (!animationFinished[0]) {
648 throw new IllegalStateException("Animation never finished");
649 }
650 }
651
Lucas Dupin3503c5f2018-03-02 19:04:00 -0800652 boolean wasAnimationJustCancelled() {
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800653 final boolean wasCancelled = mAnimationCancelled;
654 mAnimationCancelled = false;
655 return wasCancelled;
656 }
657
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800658 private void endAnimation(View scrimView, int tag) {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800659 Animator animator = (Animator) scrimView.getTag(tag);
660 if (animator != null) {
661 animator.end();
662 }
663 }
664
665 @Override
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800666 protected void cancelAnimator(ValueAnimator previousAnimator) {
667 super.cancelAnimator(previousAnimator);
668 mAnimationCancelled = true;
669 }
670
671 @Override
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800672 protected Handler getHandler() {
673 return mHandler;
674 }
675
676 @Override
677 protected WakeLock createWakeLock() {
678 return mWakeLock;
679 }
Lucas Dupin8c7cb022018-02-05 10:49:03 -0800680
681 /**
682 * Do not wait for a frame since we're in a test environment.
683 * @param callback What to execute.
684 */
685 @Override
Lucas Dupin0791d972018-03-26 13:32:16 -0700686 protected void doOnTheNextFrame(Runnable callback) {
687 callback.run();
Lucas Dupin8c7cb022018-02-05 10:49:03 -0800688 }
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800689 }
690
691}