blob: b6b65cec95b82b733636758b9112332dacaca826 [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);
TYM Tsaia71c8922019-01-07 15:57:53 +080097 mScrimController.setWallpaperSupportsAmbientMode(false);
Lucas Dupin9e3fa102017-11-08 17:16:55 -080098 }
99
100 @Test
101 public void initialState() {
102 Assert.assertEquals("ScrimController should start initialized",
103 mScrimController.getState(), ScrimState.UNINITIALIZED);
104 }
105
106 @Test
107 public void transitionToKeyguard() {
108 mScrimController.transitionTo(ScrimState.KEYGUARD);
109 mScrimController.finishAnimationsImmediately();
110 // Front scrim should be transparent
111 // Back scrim should be visible without tint
Lucas Dupin82aa1632017-12-13 00:13:57 -0800112 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800113 assertScrimTint(mScrimBehind, false /* tinted */);
114 }
115
116 @Test
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700117 public void transitionToAod_withRegularWallpaper() {
118 mScrimController.transitionTo(ScrimState.AOD);
119 mScrimController.finishAnimationsImmediately();
120 // Front scrim should be transparent
121 // Back scrim should be visible with tint
Lucas Dupin82aa1632017-12-13 00:13:57 -0800122 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700123 assertScrimTint(mScrimBehind, true /* tinted */);
124 assertScrimTint(mScrimInFront, true /* tinted */);
125 }
126
127 @Test
128 public void transitionToAod_withAodWallpaper() {
129 mScrimController.setWallpaperSupportsAmbientMode(true);
130 mScrimController.transitionTo(ScrimState.AOD);
131 mScrimController.finishAnimationsImmediately();
132 // Front scrim should be transparent
133 // Back scrim should be transparent
Lucas Dupin82aa1632017-12-13 00:13:57 -0800134 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
135
136 // Move on to PULSING and check if the back scrim is still transparent
137 mScrimController.transitionTo(ScrimState.PULSING);
138 mScrimController.finishAnimationsImmediately();
139 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700140 }
141
142 @Test
143 public void transitionToAod_withAodWallpaperAndLockScreenWallpaper() {
Lucas Dupinf8463ee2018-06-11 16:18:15 -0700144 mScrimController.setHasBackdrop(true);
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700145 mScrimController.setWallpaperSupportsAmbientMode(true);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800146 mScrimController.transitionTo(ScrimState.AOD);
147 mScrimController.finishAnimationsImmediately();
148 // Front scrim should be transparent
149 // Back scrim should be visible with tint
Lucas Dupin82aa1632017-12-13 00:13:57 -0800150 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800151 assertScrimTint(mScrimBehind, true /* tinted */);
152 assertScrimTint(mScrimInFront, true /* tinted */);
153 }
154
155 @Test
Lucas Dupin9bee5822018-07-09 14:32:53 -0700156 public void setHasBackdrop_withAodWallpaperAndAlbumArt() {
157 mScrimController.setWallpaperSupportsAmbientMode(true);
158 mScrimController.transitionTo(ScrimState.AOD);
159 mScrimController.finishAnimationsImmediately();
160 mScrimController.setHasBackdrop(true);
161 mScrimController.finishAnimationsImmediately();
162 // Front scrim should be transparent
163 // Back scrim should be visible with tint
164 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
165 assertScrimTint(mScrimBehind, true /* tinted */);
166 assertScrimTint(mScrimInFront, true /* tinted */);
167 }
168
169 @Test
Michael Wrightcae88752018-04-16 23:13:54 +0100170 public void transitionToAod_withFrontAlphaUpdates() {
171 // Assert that setting the AOD front scrim alpha doesn't take effect in a non-AOD state.
172 mScrimController.transitionTo(ScrimState.KEYGUARD);
173 mScrimController.setAodFrontScrimAlpha(0.5f);
174 mScrimController.finishAnimationsImmediately();
175 // Front scrim should be transparent
176 // Back scrim should be visible without tint
177 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
178
179 // ... but that it does take effect once we enter the AOD state.
180 mScrimController.transitionTo(ScrimState.AOD);
181 mScrimController.finishAnimationsImmediately();
182 // Front scrim should be semi-transparent
183 // Back scrim should be visible
184 assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
185
186 // ... and that if we set it while we're in AOD, it does take immediate effect.
187 mScrimController.setAodFrontScrimAlpha(1f);
188 assertScrimVisibility(VISIBILITY_FULLY_OPAQUE, VISIBILITY_FULLY_OPAQUE);
189
190 // ... and make sure we recall the previous front scrim alpha even if we transition away
191 // for a bit.
192 mScrimController.transitionTo(ScrimState.UNLOCKED);
193 mScrimController.transitionTo(ScrimState.AOD);
194 mScrimController.finishAnimationsImmediately();
195 assertScrimVisibility(VISIBILITY_FULLY_OPAQUE, VISIBILITY_FULLY_OPAQUE);
196
Lucas Dupin69bda602018-05-18 17:24:52 -0700197 // ... and alpha updates should be completely ignored if always_on is off.
198 // Passing it forward would mess up the wake-up transition.
199 mAlwaysOnEnabled = false;
200 mScrimController.transitionTo(ScrimState.UNLOCKED);
201 mScrimController.transitionTo(ScrimState.AOD);
202 mScrimController.finishAnimationsImmediately();
203 mScrimController.setAodFrontScrimAlpha(0.3f);
204 Assert.assertEquals(ScrimState.AOD.getFrontAlpha(), mScrimInFront.getViewAlpha(), 0.001f);
205 Assert.assertNotEquals(0.3f, mScrimInFront.getViewAlpha(), 0.001f);
206
Michael Wrightcae88752018-04-16 23:13:54 +0100207 // Reset value since enums are static.
208 mScrimController.setAodFrontScrimAlpha(0f);
209 }
210
211 @Test
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800212 public void transitionToPulsing() {
Lucas Dupin82aa1632017-12-13 00:13:57 -0800213 // Pre-condition
214 // Need to go to AoD first because PULSING doesn't change
215 // the back scrim opacity - otherwise it would hide AoD wallpapers.
216 mScrimController.setWallpaperSupportsAmbientMode(false);
217 mScrimController.transitionTo(ScrimState.AOD);
218 mScrimController.finishAnimationsImmediately();
219 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
220
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800221 mScrimController.transitionTo(ScrimState.PULSING);
222 mScrimController.finishAnimationsImmediately();
223 // Front scrim should be transparent
Lucas Dupinde64ee02018-12-21 14:45:12 -0800224 // Back scrim should be semi-transparent so the user can see the wallpaper
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800225 // Pulse callback should have been invoked
Lucas Dupinde64ee02018-12-21 14:45:12 -0800226 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800227 assertScrimTint(mScrimBehind, true /* tinted */);
228 }
229
230 @Test
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800231 public void transitionToKeyguardBouncer() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800232 mScrimController.transitionTo(ScrimState.BOUNCER);
233 mScrimController.finishAnimationsImmediately();
234 // Front scrim should be transparent
235 // Back scrim should be visible without tint
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800236 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
237 assertScrimTint(mScrimBehind, false /* tinted */);
238 }
239
240 @Test
241 public void transitionToBouncer() {
Lucas Dupin05726cd2018-03-13 14:00:24 -0700242 mScrimController.transitionTo(ScrimState.BOUNCER_SCRIMMED);
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800243 mScrimController.finishAnimationsImmediately();
244 // Front scrim should be transparent
245 // Back scrim should be visible without tint
246 assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800247 assertScrimTint(mScrimBehind, false /* tinted */);
248 }
249
250 @Test
251 public void transitionToUnlocked() {
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800252 mScrimController.setPanelExpansion(0f);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800253 mScrimController.transitionTo(ScrimState.UNLOCKED);
254 mScrimController.finishAnimationsImmediately();
255 // Front scrim should be transparent
256 // Back scrim should be transparent
Lucas Dupin82aa1632017-12-13 00:13:57 -0800257 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800258 assertScrimTint(mScrimBehind, false /* tinted */);
259 assertScrimTint(mScrimInFront, false /* tinted */);
260
261 // Back scrim should be visible after start dragging
262 mScrimController.setPanelExpansion(0.5f);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800263 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800264 }
265
266 @Test
Mady Mellor0c333772018-11-06 18:05:54 -0800267 public void transitionToBubbleExpanded() {
268 mScrimController.transitionTo(ScrimState.BUBBLE_EXPANDED);
269 mScrimController.finishAnimationsImmediately();
270
271 // Front scrim should be transparent
272 Assert.assertEquals(ScrimController.VISIBILITY_FULLY_TRANSPARENT,
273 mScrimInFront.getViewAlpha(), 0.0f);
274 // Back scrim should be visible
275 Assert.assertEquals(ScrimController.GRADIENT_SCRIM_ALPHA_BUSY,
276 mScrimBehind.getViewAlpha(), 0.0f);
277 }
278
279 @Test
Yohei Yukawa795f0102018-04-13 14:55:30 -0700280 public void scrimStateCallback() {
281 mScrimController.transitionTo(ScrimState.UNLOCKED);
282 mScrimController.finishAnimationsImmediately();
283 Assert.assertEquals(mScrimState, ScrimState.UNLOCKED);
284
285 mScrimController.transitionTo(ScrimState.BOUNCER);
286 mScrimController.finishAnimationsImmediately();
287 Assert.assertEquals(mScrimState, ScrimState.BOUNCER);
288
289 mScrimController.transitionTo(ScrimState.BOUNCER_SCRIMMED);
290 mScrimController.finishAnimationsImmediately();
291 Assert.assertEquals(mScrimState, ScrimState.BOUNCER_SCRIMMED);
292 }
293
294 @Test
shawnlin317db372018-04-09 19:49:48 +0800295 public void panelExpansion() {
296 mScrimController.setPanelExpansion(0f);
297 mScrimController.setPanelExpansion(0.5f);
298 mScrimController.transitionTo(ScrimState.UNLOCKED);
299 mScrimController.finishAnimationsImmediately();
300
301 reset(mScrimBehind);
302 mScrimController.setPanelExpansion(0f);
303 mScrimController.setPanelExpansion(1.0f);
304 mScrimController.onPreDraw();
305
306 Assert.assertEquals("Scrim alpha should change after setPanelExpansion",
307 mScrimBehindAlpha, mScrimBehind.getViewAlpha(), 0.01f);
308
309 mScrimController.setPanelExpansion(0f);
310 mScrimController.onPreDraw();
311
312 Assert.assertEquals("Scrim alpha should change after setPanelExpansion",
313 mScrimBehindAlpha, mScrimBehind.getViewAlpha(), 0.01f);
314 }
315
316 @Test
Lucas Dupin67f02632018-03-12 11:08:31 -0700317 public void panelExpansionAffectsAlpha() {
318 mScrimController.setPanelExpansion(0f);
319 mScrimController.setPanelExpansion(0.5f);
320 mScrimController.transitionTo(ScrimState.UNLOCKED);
321 mScrimController.finishAnimationsImmediately();
322
323 final float scrimAlpha = mScrimBehind.getViewAlpha();
Lucas Dupin067136c2018-03-27 18:03:25 -0700324 reset(mScrimBehind);
Lucas Dupin67f02632018-03-12 11:08:31 -0700325 mScrimController.setExpansionAffectsAlpha(false);
326 mScrimController.setPanelExpansion(0.8f);
Lucas Dupin067136c2018-03-27 18:03:25 -0700327 verifyZeroInteractions(mScrimBehind);
Lucas Dupin67f02632018-03-12 11:08:31 -0700328 Assert.assertEquals("Scrim opacity shouldn't change when setExpansionAffectsAlpha "
329 + "is false", scrimAlpha, mScrimBehind.getViewAlpha(), 0.01f);
330
331 mScrimController.setExpansionAffectsAlpha(true);
332 mScrimController.setPanelExpansion(0.1f);
333 Assert.assertNotEquals("Scrim opacity should change when setExpansionAffectsAlpha "
334 + "is true", scrimAlpha, mScrimBehind.getViewAlpha(), 0.01f);
335 }
336
337 @Test
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800338 public void transitionToUnlockedFromAod() {
339 // Simulate unlock with fingerprint
340 mScrimController.transitionTo(ScrimState.AOD);
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800341 mScrimController.setPanelExpansion(0f);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800342 mScrimController.finishAnimationsImmediately();
343 mScrimController.transitionTo(ScrimState.UNLOCKED);
344 // Immediately tinted after the transition starts
345 assertScrimTint(mScrimInFront, true /* tinted */);
346 assertScrimTint(mScrimBehind, true /* tinted */);
347 mScrimController.finishAnimationsImmediately();
348 // Front scrim should be transparent
349 // Back scrim should be transparent
350 // Neither scrims should be tinted anymore after the animation.
Lucas Dupin82aa1632017-12-13 00:13:57 -0800351 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800352 assertScrimTint(mScrimInFront, false /* tinted */);
353 assertScrimTint(mScrimBehind, false /* tinted */);
354 }
355
356 @Test
Lucas Dupinea0116e2018-04-05 10:09:29 -0700357 public void scrimBlanksBeforeLeavingAod() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800358 // Simulate unlock with fingerprint
359 mScrimController.transitionTo(ScrimState.AOD);
360 mScrimController.finishAnimationsImmediately();
361 mScrimController.transitionTo(ScrimState.UNLOCKED,
362 new ScrimController.Callback() {
363 @Override
364 public void onDisplayBlanked() {
365 // Front scrim should be black in the middle of the transition
366 Assert.assertTrue("Scrim should be visible during transition. Alpha: "
367 + mScrimInFront.getViewAlpha(), mScrimInFront.getViewAlpha() > 0);
368 assertScrimTint(mScrimInFront, true /* tinted */);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800369 Assert.assertSame("Scrim should be visible during transition.",
370 mScrimVisibility, VISIBILITY_FULLY_OPAQUE);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800371 }
372 });
373 mScrimController.finishAnimationsImmediately();
374 }
375
376 @Test
Lucas Dupineb840ea2018-06-01 00:28:58 -0700377 public void scrimBlanksWhenUnlockingFromPulse() {
378 boolean[] blanked = {false};
379 // Simulate unlock with fingerprint
380 mScrimController.transitionTo(ScrimState.PULSING);
381 mScrimController.finishAnimationsImmediately();
382 mScrimController.transitionTo(ScrimState.UNLOCKED,
383 new ScrimController.Callback() {
384 @Override
385 public void onDisplayBlanked() {
386 blanked[0] = true;
387 }
388 });
389 mScrimController.finishAnimationsImmediately();
390 Assert.assertTrue("Scrim should blank when unlocking from pulse.", blanked[0]);
391 }
392
393 @Test
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800394 public void testScrimCallback() {
395 int[] callOrder = {0, 0, 0};
396 int[] currentCall = {0};
397 mScrimController.transitionTo(ScrimState.AOD, new ScrimController.Callback() {
398 @Override
399 public void onStart() {
400 callOrder[0] = ++currentCall[0];
401 }
402
403 @Override
404 public void onDisplayBlanked() {
405 callOrder[1] = ++currentCall[0];
406 }
407
408 @Override
409 public void onFinished() {
410 callOrder[2] = ++currentCall[0];
411 }
412 });
413 mScrimController.finishAnimationsImmediately();
414 Assert.assertEquals("onStart called in wrong order", 1, callOrder[0]);
415 Assert.assertEquals("onDisplayBlanked called in wrong order", 2, callOrder[1]);
416 Assert.assertEquals("onFinished called in wrong order", 3, callOrder[2]);
417 }
418
419 @Test
420 public void testScrimCallbacksWithoutAmbientDisplay() {
421 mAlwaysOnEnabled = false;
422 testScrimCallback();
423 }
424
425 @Test
426 public void testScrimCallbackCancelled() {
427 boolean[] cancelledCalled = {false};
428 mScrimController.transitionTo(ScrimState.AOD, new ScrimController.Callback() {
429 @Override
430 public void onCancelled() {
431 cancelledCalled[0] = true;
432 }
433 });
434 mScrimController.transitionTo(ScrimState.PULSING);
435 Assert.assertTrue("onCancelled should have been called", cancelledCalled[0]);
436 }
437
438 @Test
Lucas Dupineea53b32017-12-18 13:47:14 -0800439 public void testHoldsWakeLock_whenAOD() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800440 mScrimController.transitionTo(ScrimState.AOD);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800441 verify(mWakeLock).acquire();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800442 verify(mWakeLock, never()).release();
443 mScrimController.finishAnimationsImmediately();
Lucas Dupin82aa1632017-12-13 00:13:57 -0800444 verify(mWakeLock).release();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800445 }
446
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800447 @Test
Lucas Dupineea53b32017-12-18 13:47:14 -0800448 public void testDoesNotHoldWakeLock_whenUnlocking() {
449 mScrimController.transitionTo(ScrimState.UNLOCKED);
450 mScrimController.finishAnimationsImmediately();
451 verifyZeroInteractions(mWakeLock);
452 }
453
454 @Test
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800455 public void testCallbackInvokedOnSameStateTransition() {
456 mScrimController.transitionTo(ScrimState.UNLOCKED);
457 mScrimController.finishAnimationsImmediately();
458 ScrimController.Callback callback = mock(ScrimController.Callback.class);
459 mScrimController.transitionTo(ScrimState.UNLOCKED, callback);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800460 verify(callback).onFinished();
461 }
462
463 @Test
464 public void testHoldsAodWallpaperAnimationLock() {
465 // Pre-conditions
466 mScrimController.transitionTo(ScrimState.AOD);
467 mScrimController.finishAnimationsImmediately();
468 reset(mWakeLock);
469
470 mScrimController.onHideWallpaperTimeout();
471 verify(mWakeLock).acquire();
472 verify(mWakeLock, never()).release();
473 mScrimController.finishAnimationsImmediately();
474 verify(mWakeLock).release();
475 }
476
477 @Test
TYM Tsaia71c8922019-01-07 15:57:53 +0800478 public void testHoldsPulsingWallpaperAnimationLock() {
479 // Pre-conditions
480 mScrimController.transitionTo(ScrimState.PULSING, new ScrimController.Callback() {
481 @Override
482 public boolean isFadeOutWallpaper() {
483 return true;
484 }
485 });
486 mScrimController.finishAnimationsImmediately();
487 reset(mWakeLock);
488
489 mScrimController.onHideWallpaperTimeout();
490 verify(mWakeLock).acquire();
491 verify(mWakeLock, never()).release();
492 mScrimController.finishAnimationsImmediately();
493 verify(mWakeLock).release();
494 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
495 }
496
497 @Test
Lucas Dupin16cfe452018-02-08 13:14:50 -0800498 public void testWillHideAodWallpaper() {
Lucas Dupin82aa1632017-12-13 00:13:57 -0800499 mScrimController.setWallpaperSupportsAmbientMode(true);
500 mScrimController.transitionTo(ScrimState.AOD);
501 verify(mAlarmManager).setExact(anyInt(), anyLong(), any(), any(), any());
502 mScrimController.transitionTo(ScrimState.KEYGUARD);
503 verify(mAlarmManager).cancel(any(AlarmManager.OnAlarmListener.class));
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800504 }
505
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800506 @Test
TYM Tsaia71c8922019-01-07 15:57:53 +0800507 public void testWillHidePulsingWallpaper_withRequestFadeOut() {
508 mScrimController.setWallpaperSupportsAmbientMode(true);
509 mScrimController.transitionTo(ScrimState.PULSING, new ScrimController.Callback() {
510 @Override
511 public boolean isFadeOutWallpaper() {
512 return true;
513 }
514 });
515 verify(mAlarmManager).setExact(anyInt(), anyLong(), any(), any(), any());
516 mScrimController.transitionTo(ScrimState.KEYGUARD);
517 verify(mAlarmManager).cancel(any(AlarmManager.OnAlarmListener.class));
518 }
519
520 @Test
521 public void testDoesNotHidePulsingWallpaper_withoutRequestFadeOut() {
522 mScrimController.setWallpaperSupportsAmbientMode(true);
523 mScrimController.transitionTo(ScrimState.PULSING, new ScrimController.Callback() {});
524 verify(mAlarmManager, never()).setExact(anyInt(), anyLong(), any(), any(), any());
525 }
526
527 @Test
528 public void testDoesNotHidePulsingWallpaper_withoutCallback() {
529 mScrimController.setWallpaperSupportsAmbientMode(true);
530 mScrimController.transitionTo(ScrimState.PULSING);
531 verify(mAlarmManager, never()).setExact(anyInt(), anyLong(), any(), any(), any());
532 }
533
534 @Test
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800535 public void testConservesExpansionOpacityAfterTransition() {
536 mScrimController.transitionTo(ScrimState.UNLOCKED);
537 mScrimController.setPanelExpansion(0.5f);
538 mScrimController.finishAnimationsImmediately();
539
540 final float expandedAlpha = mScrimBehind.getViewAlpha();
541
542 mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR);
543 mScrimController.finishAnimationsImmediately();
544 mScrimController.transitionTo(ScrimState.UNLOCKED);
545 mScrimController.finishAnimationsImmediately();
546
547 Assert.assertEquals("Scrim expansion opacity wasn't conserved when transitioning back",
548 expandedAlpha, mScrimBehind.getViewAlpha(), 0.01f);
549 }
550
551 @Test
552 public void cancelsOldAnimationBeforeBlanking() {
553 mScrimController.transitionTo(ScrimState.AOD);
554 mScrimController.finishAnimationsImmediately();
555 // Consume whatever value we had before
556 mScrimController.wasAnimationJustCancelled();
557
558 mScrimController.transitionTo(ScrimState.KEYGUARD);
559 mScrimController.finishAnimationsImmediately();
560 Assert.assertTrue(mScrimController.wasAnimationJustCancelled());
561 }
562
Lucas Dupinb380c882018-02-25 21:57:17 -0800563 /**
564 * Number of visible notifications affects scrim opacity.
565 */
566 @Test
567 public void testNotificationDensity() {
568 mScrimController.transitionTo(ScrimState.KEYGUARD);
569 mScrimController.finishAnimationsImmediately();
570
571 mScrimController.setNotificationCount(0);
572 mScrimController.finishAnimationsImmediately();
573 Assert.assertEquals("lower density when no notifications",
574 ScrimController.GRADIENT_SCRIM_ALPHA, mScrimBehind.getViewAlpha(), 0.01f);
575
576 mScrimController.setNotificationCount(3);
577 mScrimController.finishAnimationsImmediately();
578 Assert.assertEquals("stronger density when notifications are visible",
579 ScrimController.GRADIENT_SCRIM_ALPHA_BUSY, mScrimBehind.getViewAlpha(), 0.01f);
580 }
581
582 /**
583 * Moving from/to states conserves old notification density.
584 */
585 @Test
586 public void testConservesNotificationDensity() {
587 testConservesNotificationDensity(0 /* count */, ScrimController.GRADIENT_SCRIM_ALPHA);
588 testConservesNotificationDensity(3 /* count */, ScrimController.GRADIENT_SCRIM_ALPHA_BUSY);
589 }
590
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800591 @Test
Lucas Dupin38962d72018-03-14 12:41:39 -0700592 public void testScrimFocus() {
593 mScrimController.transitionTo(ScrimState.AOD);
594 Assert.assertFalse("Should not be focusable on AOD", mScrimBehind.isFocusable());
595 Assert.assertFalse("Should not be focusable on AOD", mScrimInFront.isFocusable());
596
597 mScrimController.transitionTo(ScrimState.KEYGUARD);
598 Assert.assertTrue("Should be focusable on keyguard", mScrimBehind.isFocusable());
599 Assert.assertTrue("Should be focusable on keyguard", mScrimInFront.isFocusable());
600 }
601
Lucas Dupind5107302018-03-19 15:30:29 -0700602 @Test
603 public void testHidesShowWhenLockedActivity() {
604 mScrimController.setWallpaperSupportsAmbientMode(true);
605 mScrimController.setKeyguardOccluded(true);
606 mScrimController.transitionTo(ScrimState.AOD);
607 mScrimController.finishAnimationsImmediately();
608 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
609
610 mScrimController.transitionTo(ScrimState.PULSING);
611 mScrimController.finishAnimationsImmediately();
612 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
613 }
614
Lucas Dupin78949b82018-04-03 18:54:39 -0700615 @Test
Lucas Dupin63d72172018-06-06 11:42:55 -0700616 public void testHidesShowWhenLockedActivity_whenAlreadyInAod() {
617 mScrimController.setWallpaperSupportsAmbientMode(true);
618 mScrimController.transitionTo(ScrimState.AOD);
619 mScrimController.finishAnimationsImmediately();
620 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
621
622 mScrimController.setKeyguardOccluded(true);
623 mScrimController.finishAnimationsImmediately();
624 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
625 }
626
627 @Test
Lucas Dupin78949b82018-04-03 18:54:39 -0700628 public void testEatsTouchEvent() {
629 HashSet<ScrimState> eatsTouches =
630 new HashSet<>(Arrays.asList(ScrimState.AOD, ScrimState.PULSING));
631 for (ScrimState state : ScrimState.values()) {
632 if (state == ScrimState.UNINITIALIZED) {
633 continue;
634 }
635 mScrimController.transitionTo(state);
636 mScrimController.finishAnimationsImmediately();
637 Assert.assertEquals("Should be clickable unless AOD or PULSING, was: " + state,
638 mScrimBehind.getViewAlpha() != 0 && !eatsTouches.contains(state),
639 mScrimBehind.isClickable());
640 }
641 }
642
Lucas Dupinea0116e2018-04-05 10:09:29 -0700643 @Test
644 public void testAnimatesTransitionToAod() {
645 when(mDozeParamenters.shouldControlScreenOff()).thenReturn(false);
646 ScrimState.AOD.prepare(ScrimState.KEYGUARD);
647 Assert.assertFalse("No animation when ColorFade kicks in",
648 ScrimState.AOD.getAnimateChange());
649
650 reset(mDozeParamenters);
651 when(mDozeParamenters.shouldControlScreenOff()).thenReturn(true);
652 ScrimState.AOD.prepare(ScrimState.KEYGUARD);
653 Assert.assertTrue("Animate scrims when ColorFade won't be triggered",
654 ScrimState.AOD.getAnimateChange());
655 }
656
Lucas Dupin373356b2018-04-07 10:50:25 -0700657 @Test
658 public void testViewsDontHaveFocusHighlight() {
659 Assert.assertFalse("Scrim shouldn't have focus highlight",
660 mScrimInFront.getDefaultFocusHighlightEnabled());
661 Assert.assertFalse("Scrim shouldn't have focus highlight",
662 mScrimBehind.getDefaultFocusHighlightEnabled());
663 }
664
Lucas Dupinb380c882018-02-25 21:57:17 -0800665 /**
666 * Conserves old notification density after leaving state and coming back.
667 *
668 * @param count How many notification.
669 * @param expectedAlpha Expected alpha.
670 */
671 private void testConservesNotificationDensity(int count, float expectedAlpha) {
672 mScrimController.setNotificationCount(count);
673 mScrimController.transitionTo(ScrimState.UNLOCKED);
674 mScrimController.finishAnimationsImmediately();
675
676 mScrimController.transitionTo(ScrimState.KEYGUARD);
677 mScrimController.finishAnimationsImmediately();
678
679 Assert.assertEquals("Doesn't respect notification busyness after transition",
680 expectedAlpha, mScrimBehind.getViewAlpha(), 0.01f);
681 }
682
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800683 private void assertScrimTint(ScrimView scrimView, boolean tinted) {
684 final boolean viewIsTinted = scrimView.getTint() != Color.TRANSPARENT;
685 final String name = scrimView == mScrimInFront ? "front" : "back";
686 Assert.assertEquals("Tint test failed at state " + mScrimController.getState()
687 +" with scrim: " + name + " and tint: " + Integer.toHexString(scrimView.getTint()),
688 tinted, viewIsTinted);
689 }
690
Lucas Dupin82aa1632017-12-13 00:13:57 -0800691 private void assertScrimVisibility(int inFront, int behind) {
692 boolean inFrontVisible = inFront != ScrimController.VISIBILITY_FULLY_TRANSPARENT;
693 boolean behindVisible = behind != ScrimController.VISIBILITY_FULLY_TRANSPARENT;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800694 Assert.assertEquals("Unexpected front scrim visibility. Alpha is "
Lucas Dupin82aa1632017-12-13 00:13:57 -0800695 + mScrimInFront.getViewAlpha(), inFrontVisible, mScrimInFront.getViewAlpha() > 0);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800696 Assert.assertEquals("Unexpected back scrim visibility. Alpha is "
Lucas Dupin82aa1632017-12-13 00:13:57 -0800697 + mScrimBehind.getViewAlpha(), behindVisible, mScrimBehind.getViewAlpha() > 0);
698
699 final int visibility;
700 if (inFront == VISIBILITY_FULLY_OPAQUE || behind == VISIBILITY_FULLY_OPAQUE) {
701 visibility = VISIBILITY_FULLY_OPAQUE;
702 } else if (inFront > VISIBILITY_FULLY_TRANSPARENT || behind > VISIBILITY_FULLY_TRANSPARENT) {
703 visibility = VISIBILITY_SEMI_TRANSPARENT;
704 } else {
705 visibility = VISIBILITY_FULLY_TRANSPARENT;
706 }
707 Assert.assertEquals("Invalid visibility.", visibility, mScrimVisibility);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800708 }
709
710 /**
711 * Special version of ScrimController where animations have 0 duration for test purposes.
712 */
713 private class SynchronousScrimController extends ScrimController {
714
715 private FakeHandler mHandler;
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800716 private boolean mAnimationCancelled;
Lucas Dupin16cfe452018-02-08 13:14:50 -0800717 boolean mOnPreDrawCalled;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800718
shawnlin317db372018-04-09 19:49:48 +0800719 SynchronousScrimController(ScrimView scrimBehind, ScrimView scrimInFront,
Yohei Yukawa795f0102018-04-13 14:55:30 -0700720 TriConsumer<ScrimState, Float, GradientColors> scrimStateListener,
Lucas Dupin82aa1632017-12-13 00:13:57 -0800721 Consumer<Integer> scrimVisibleListener, DozeParameters dozeParameters,
722 AlarmManager alarmManager) {
Yohei Yukawa795f0102018-04-13 14:55:30 -0700723 super(scrimBehind, scrimInFront, scrimStateListener, scrimVisibleListener,
724 dozeParameters, alarmManager);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800725 mHandler = new FakeHandler(Looper.myLooper());
726 }
727
Lucas Dupin16cfe452018-02-08 13:14:50 -0800728 @Override
729 public boolean onPreDraw() {
730 mOnPreDrawCalled = true;
731 return super.onPreDraw();
732 }
733
Lucas Dupin3503c5f2018-03-02 19:04:00 -0800734 void finishAnimationsImmediately() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800735 boolean[] animationFinished = {false};
736 setOnAnimationFinished(()-> animationFinished[0] = true);
737
738 // Execute code that will trigger animations.
739 onPreDraw();
740
741 // Force finish screen blanking.
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800742 mHandler.dispatchQueuedMessages();
743 // Force finish all animations.
744 endAnimation(mScrimBehind, TAG_KEY_ANIM);
745 endAnimation(mScrimInFront, TAG_KEY_ANIM);
746
747 if (!animationFinished[0]) {
748 throw new IllegalStateException("Animation never finished");
749 }
750 }
751
Lucas Dupin3503c5f2018-03-02 19:04:00 -0800752 boolean wasAnimationJustCancelled() {
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800753 final boolean wasCancelled = mAnimationCancelled;
754 mAnimationCancelled = false;
755 return wasCancelled;
756 }
757
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800758 private void endAnimation(View scrimView, int tag) {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800759 Animator animator = (Animator) scrimView.getTag(tag);
760 if (animator != null) {
761 animator.end();
762 }
763 }
764
765 @Override
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800766 protected void cancelAnimator(ValueAnimator previousAnimator) {
767 super.cancelAnimator(previousAnimator);
768 mAnimationCancelled = true;
769 }
770
771 @Override
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800772 protected Handler getHandler() {
773 return mHandler;
774 }
775
776 @Override
777 protected WakeLock createWakeLock() {
778 return mWakeLock;
779 }
Lucas Dupin8c7cb022018-02-05 10:49:03 -0800780
781 /**
782 * Do not wait for a frame since we're in a test environment.
783 * @param callback What to execute.
784 */
785 @Override
Lucas Dupin0791d972018-03-26 13:32:16 -0700786 protected void doOnTheNextFrame(Runnable callback) {
787 callback.run();
Lucas Dupin8c7cb022018-02-05 10:49:03 -0800788 }
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800789 }
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800790}