blob: 191c983ad156459ff2b54587c7152b3e69a262f3 [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 Dupinee4c9b72019-02-18 17:04:58 -080026import static org.mockito.ArgumentMatchers.anyString;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080027import static org.mockito.Mockito.mock;
28import static org.mockito.Mockito.never;
Lucas Dupin82aa1632017-12-13 00:13:57 -080029import static org.mockito.Mockito.reset;
Lucas Dupin067136c2018-03-27 18:03:25 -070030import static org.mockito.Mockito.spy;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080031import static org.mockito.Mockito.verify;
Lucas Dupineea53b32017-12-18 13:47:14 -080032import static org.mockito.Mockito.verifyZeroInteractions;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080033import static org.mockito.Mockito.when;
34
35import android.animation.Animator;
Lucas Dupin80a3fcc2018-02-07 10:49:55 -080036import android.animation.ValueAnimator;
Lucas Dupin82aa1632017-12-13 00:13:57 -080037import android.app.AlarmManager;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080038import android.graphics.Color;
39import android.os.Handler;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080040import android.testing.AndroidTestingRunner;
41import android.testing.TestableLooper;
42import android.view.View;
43
Brett Chabot84151d92019-02-27 15:37:59 -080044import androidx.test.filters.SmallTest;
45
shawnlin317db372018-04-09 19:49:48 +080046import com.android.internal.colorextraction.ColorExtractor.GradientColors;
Yohei Yukawa795f0102018-04-13 14:55:30 -070047import com.android.internal.util.function.TriConsumer;
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
Lucas Dupin4dbe5182019-03-07 18:20:11 -080053import org.junit.After;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080054import org.junit.Assert;
55import org.junit.Before;
56import org.junit.Test;
57import org.junit.runner.RunWith;
58
Lucas Dupin1c327432019-01-03 13:37:53 -080059import java.util.Collections;
Lucas Dupin78949b82018-04-03 18:54:39 -070060import java.util.HashSet;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080061import java.util.function.Consumer;
62
63@RunWith(AndroidTestingRunner.class)
64@TestableLooper.RunWithLooper
65@SmallTest
66public class ScrimControllerTest extends SysuiTestCase {
67
68 private SynchronousScrimController mScrimController;
69 private ScrimView mScrimBehind;
70 private ScrimView mScrimInFront;
Yohei Yukawa795f0102018-04-13 14:55:30 -070071 private ScrimState mScrimState;
shawnlin317db372018-04-09 19:49:48 +080072 private float mScrimBehindAlpha;
73 private GradientColors mScrimInFrontColor;
Lucas Dupin82aa1632017-12-13 00:13:57 -080074 private int mScrimVisibility;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080075 private DozeParameters mDozeParamenters;
76 private WakeLock mWakeLock;
77 private boolean mAlwaysOnEnabled;
Lucas Dupin82aa1632017-12-13 00:13:57 -080078 private AlarmManager mAlarmManager;
Lucas Dupin54fbfb32019-03-05 18:08:13 -080079 private TestableLooper mLooper;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080080
Yohei Yukawa795f0102018-04-13 14:55:30 -070081
Lucas Dupin9e3fa102017-11-08 17:16:55 -080082 @Before
83 public void setup() {
Lucas Dupin067136c2018-03-27 18:03:25 -070084 mScrimBehind = spy(new ScrimView(getContext()));
Lucas Dupin9e3fa102017-11-08 17:16:55 -080085 mScrimInFront = new ScrimView(getContext());
Lucas Dupin9e3fa102017-11-08 17:16:55 -080086 mWakeLock = mock(WakeLock.class);
Lucas Dupin82aa1632017-12-13 00:13:57 -080087 mAlarmManager = mock(AlarmManager.class);
Lucas Dupin9e3fa102017-11-08 17:16:55 -080088 mAlwaysOnEnabled = true;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080089 mDozeParamenters = mock(DozeParameters.class);
Lucas Dupin54fbfb32019-03-05 18:08:13 -080090 mLooper = TestableLooper.get(this);
Lucas Dupin9e3fa102017-11-08 17:16:55 -080091 when(mDozeParamenters.getAlwaysOn()).thenAnswer(invocation -> mAlwaysOnEnabled);
Lucas Dupin43d0d732017-11-16 11:23:49 -080092 when(mDozeParamenters.getDisplayNeedsBlanking()).thenReturn(true);
shawnlin317db372018-04-09 19:49:48 +080093 mScrimController = new SynchronousScrimController(mScrimBehind, mScrimInFront,
Yohei Yukawa795f0102018-04-13 14:55:30 -070094 (scrimState, scrimBehindAlpha, scrimInFrontColor) -> {
95 mScrimState = scrimState;
96 mScrimBehindAlpha = scrimBehindAlpha;
97 mScrimInFrontColor = scrimInFrontColor;
98 },
99 visible -> mScrimVisibility = visible, mDozeParamenters, mAlarmManager);
Lucas Dupinf8463ee2018-06-11 16:18:15 -0700100 mScrimController.setHasBackdrop(false);
TYM Tsaia71c8922019-01-07 15:57:53 +0800101 mScrimController.setWallpaperSupportsAmbientMode(false);
Lucas Dupin4dbe5182019-03-07 18:20:11 -0800102 mScrimController.transitionTo(ScrimState.KEYGUARD);
103 mScrimController.finishAnimationsImmediately();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800104 }
105
Lucas Dupin4dbe5182019-03-07 18:20:11 -0800106 @After
107 public void tearDown() {
108 mScrimController.finishAnimationsImmediately();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800109 }
110
111 @Test
112 public void transitionToKeyguard() {
113 mScrimController.transitionTo(ScrimState.KEYGUARD);
114 mScrimController.finishAnimationsImmediately();
115 // Front scrim should be transparent
116 // Back scrim should be visible without tint
Lucas Dupin82aa1632017-12-13 00:13:57 -0800117 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
Lucas Dupin1113fdf2019-03-07 17:32:00 -0800118 assertScrimTint(mScrimBehind, true /* tinted */);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800119 }
120
121 @Test
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700122 public void transitionToAod_withRegularWallpaper() {
123 mScrimController.transitionTo(ScrimState.AOD);
124 mScrimController.finishAnimationsImmediately();
125 // Front scrim should be transparent
126 // Back scrim should be visible with tint
Lucas Dupin82aa1632017-12-13 00:13:57 -0800127 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700128 assertScrimTint(mScrimBehind, true /* tinted */);
129 assertScrimTint(mScrimInFront, true /* tinted */);
130 }
131
132 @Test
133 public void transitionToAod_withAodWallpaper() {
134 mScrimController.setWallpaperSupportsAmbientMode(true);
135 mScrimController.transitionTo(ScrimState.AOD);
136 mScrimController.finishAnimationsImmediately();
137 // Front scrim should be transparent
138 // Back scrim should be transparent
Lucas Dupin82aa1632017-12-13 00:13:57 -0800139 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
140
Lucas Dupin00be88f2019-01-03 17:50:52 -0800141 // Pulsing notification should conserve AOD wallpaper.
Lucas Dupin82aa1632017-12-13 00:13:57 -0800142 mScrimController.transitionTo(ScrimState.PULSING);
143 mScrimController.finishAnimationsImmediately();
Lucas Dupin00be88f2019-01-03 17:50:52 -0800144 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700145 }
146
147 @Test
148 public void transitionToAod_withAodWallpaperAndLockScreenWallpaper() {
Lucas Dupinf8463ee2018-06-11 16:18:15 -0700149 mScrimController.setHasBackdrop(true);
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700150 mScrimController.setWallpaperSupportsAmbientMode(true);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800151 mScrimController.transitionTo(ScrimState.AOD);
152 mScrimController.finishAnimationsImmediately();
153 // Front scrim should be transparent
154 // Back scrim should be visible with tint
Lucas Dupin82aa1632017-12-13 00:13:57 -0800155 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800156 assertScrimTint(mScrimBehind, true /* tinted */);
157 assertScrimTint(mScrimInFront, true /* tinted */);
158 }
159
160 @Test
Lucas Dupin9bee5822018-07-09 14:32:53 -0700161 public void setHasBackdrop_withAodWallpaperAndAlbumArt() {
162 mScrimController.setWallpaperSupportsAmbientMode(true);
163 mScrimController.transitionTo(ScrimState.AOD);
164 mScrimController.finishAnimationsImmediately();
165 mScrimController.setHasBackdrop(true);
166 mScrimController.finishAnimationsImmediately();
167 // Front scrim should be transparent
168 // Back scrim should be visible with tint
169 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
170 assertScrimTint(mScrimBehind, true /* tinted */);
171 assertScrimTint(mScrimInFront, true /* tinted */);
172 }
173
174 @Test
Michael Wrightcae88752018-04-16 23:13:54 +0100175 public void transitionToAod_withFrontAlphaUpdates() {
176 // Assert that setting the AOD front scrim alpha doesn't take effect in a non-AOD state.
177 mScrimController.transitionTo(ScrimState.KEYGUARD);
178 mScrimController.setAodFrontScrimAlpha(0.5f);
179 mScrimController.finishAnimationsImmediately();
180 // Front scrim should be transparent
181 // Back scrim should be visible without tint
182 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
183
184 // ... but that it does take effect once we enter the AOD state.
185 mScrimController.transitionTo(ScrimState.AOD);
186 mScrimController.finishAnimationsImmediately();
187 // Front scrim should be semi-transparent
188 // Back scrim should be visible
189 assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
190
191 // ... and that if we set it while we're in AOD, it does take immediate effect.
192 mScrimController.setAodFrontScrimAlpha(1f);
193 assertScrimVisibility(VISIBILITY_FULLY_OPAQUE, VISIBILITY_FULLY_OPAQUE);
194
195 // ... and make sure we recall the previous front scrim alpha even if we transition away
196 // for a bit.
197 mScrimController.transitionTo(ScrimState.UNLOCKED);
198 mScrimController.transitionTo(ScrimState.AOD);
199 mScrimController.finishAnimationsImmediately();
200 assertScrimVisibility(VISIBILITY_FULLY_OPAQUE, VISIBILITY_FULLY_OPAQUE);
201
Lucas Dupin69bda602018-05-18 17:24:52 -0700202 // ... and alpha updates should be completely ignored if always_on is off.
203 // Passing it forward would mess up the wake-up transition.
204 mAlwaysOnEnabled = false;
205 mScrimController.transitionTo(ScrimState.UNLOCKED);
206 mScrimController.transitionTo(ScrimState.AOD);
207 mScrimController.finishAnimationsImmediately();
208 mScrimController.setAodFrontScrimAlpha(0.3f);
209 Assert.assertEquals(ScrimState.AOD.getFrontAlpha(), mScrimInFront.getViewAlpha(), 0.001f);
210 Assert.assertNotEquals(0.3f, mScrimInFront.getViewAlpha(), 0.001f);
211
Michael Wrightcae88752018-04-16 23:13:54 +0100212 // Reset value since enums are static.
213 mScrimController.setAodFrontScrimAlpha(0f);
214 }
215
216 @Test
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800217 public void transitionToPulsing() {
Lucas Dupin82aa1632017-12-13 00:13:57 -0800218 // Pre-condition
219 // Need to go to AoD first because PULSING doesn't change
220 // the back scrim opacity - otherwise it would hide AoD wallpapers.
221 mScrimController.setWallpaperSupportsAmbientMode(false);
222 mScrimController.transitionTo(ScrimState.AOD);
223 mScrimController.finishAnimationsImmediately();
224 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
225
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800226 mScrimController.transitionTo(ScrimState.PULSING);
227 mScrimController.finishAnimationsImmediately();
228 // Front scrim should be transparent
Lucas Dupinde64ee02018-12-21 14:45:12 -0800229 // Back scrim should be semi-transparent so the user can see the wallpaper
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800230 // Pulse callback should have been invoked
Lucas Dupin5f00fa52019-03-27 22:46:53 -0700231 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
Lucas Dupin3113db62019-03-08 18:21:27 -0800232 assertScrimTint(mScrimBehind, true /* tinted */);
Lucas Dupin5f00fa52019-03-27 22:46:53 -0700233
234 mScrimController.setWakeLockScreenSensorActive(true);
235 mScrimController.finishAnimationsImmediately();
236 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800237 }
238
239 @Test
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800240 public void transitionToKeyguardBouncer() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800241 mScrimController.transitionTo(ScrimState.BOUNCER);
242 mScrimController.finishAnimationsImmediately();
243 // Front scrim should be transparent
244 // Back scrim should be visible without tint
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800245 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
246 assertScrimTint(mScrimBehind, false /* tinted */);
247 }
248
249 @Test
250 public void transitionToBouncer() {
Lucas Dupin05726cd2018-03-13 14:00:24 -0700251 mScrimController.transitionTo(ScrimState.BOUNCER_SCRIMMED);
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800252 mScrimController.finishAnimationsImmediately();
253 // Front scrim should be transparent
254 // Back scrim should be visible without tint
255 assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800256 assertScrimTint(mScrimBehind, false /* tinted */);
257 }
258
259 @Test
260 public void transitionToUnlocked() {
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800261 mScrimController.setPanelExpansion(0f);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800262 mScrimController.transitionTo(ScrimState.UNLOCKED);
263 mScrimController.finishAnimationsImmediately();
264 // Front scrim should be transparent
265 // Back scrim should be transparent
Lucas Dupin82aa1632017-12-13 00:13:57 -0800266 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800267 assertScrimTint(mScrimBehind, false /* tinted */);
268 assertScrimTint(mScrimInFront, false /* tinted */);
269
270 // Back scrim should be visible after start dragging
271 mScrimController.setPanelExpansion(0.5f);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800272 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800273 }
274
275 @Test
Mady Mellor0c333772018-11-06 18:05:54 -0800276 public void transitionToBubbleExpanded() {
277 mScrimController.transitionTo(ScrimState.BUBBLE_EXPANDED);
278 mScrimController.finishAnimationsImmediately();
279
280 // Front scrim should be transparent
281 Assert.assertEquals(ScrimController.VISIBILITY_FULLY_TRANSPARENT,
282 mScrimInFront.getViewAlpha(), 0.0f);
283 // Back scrim should be visible
284 Assert.assertEquals(ScrimController.GRADIENT_SCRIM_ALPHA_BUSY,
285 mScrimBehind.getViewAlpha(), 0.0f);
286 }
287
288 @Test
Yohei Yukawa795f0102018-04-13 14:55:30 -0700289 public void scrimStateCallback() {
290 mScrimController.transitionTo(ScrimState.UNLOCKED);
291 mScrimController.finishAnimationsImmediately();
292 Assert.assertEquals(mScrimState, ScrimState.UNLOCKED);
293
294 mScrimController.transitionTo(ScrimState.BOUNCER);
295 mScrimController.finishAnimationsImmediately();
296 Assert.assertEquals(mScrimState, ScrimState.BOUNCER);
297
298 mScrimController.transitionTo(ScrimState.BOUNCER_SCRIMMED);
299 mScrimController.finishAnimationsImmediately();
300 Assert.assertEquals(mScrimState, ScrimState.BOUNCER_SCRIMMED);
301 }
302
303 @Test
shawnlin317db372018-04-09 19:49:48 +0800304 public void panelExpansion() {
305 mScrimController.setPanelExpansion(0f);
306 mScrimController.setPanelExpansion(0.5f);
307 mScrimController.transitionTo(ScrimState.UNLOCKED);
308 mScrimController.finishAnimationsImmediately();
309
310 reset(mScrimBehind);
311 mScrimController.setPanelExpansion(0f);
312 mScrimController.setPanelExpansion(1.0f);
Lucas Dupin4dbe5182019-03-07 18:20:11 -0800313 mScrimController.finishAnimationsImmediately();
shawnlin317db372018-04-09 19:49:48 +0800314
315 Assert.assertEquals("Scrim alpha should change after setPanelExpansion",
316 mScrimBehindAlpha, mScrimBehind.getViewAlpha(), 0.01f);
317
318 mScrimController.setPanelExpansion(0f);
Lucas Dupin4dbe5182019-03-07 18:20:11 -0800319 mScrimController.finishAnimationsImmediately();
shawnlin317db372018-04-09 19:49:48 +0800320
321 Assert.assertEquals("Scrim alpha should change after setPanelExpansion",
322 mScrimBehindAlpha, mScrimBehind.getViewAlpha(), 0.01f);
323 }
324
325 @Test
Lucas Dupin67f02632018-03-12 11:08:31 -0700326 public void panelExpansionAffectsAlpha() {
327 mScrimController.setPanelExpansion(0f);
328 mScrimController.setPanelExpansion(0.5f);
329 mScrimController.transitionTo(ScrimState.UNLOCKED);
330 mScrimController.finishAnimationsImmediately();
331
332 final float scrimAlpha = mScrimBehind.getViewAlpha();
Lucas Dupin067136c2018-03-27 18:03:25 -0700333 reset(mScrimBehind);
Lucas Dupin67f02632018-03-12 11:08:31 -0700334 mScrimController.setExpansionAffectsAlpha(false);
335 mScrimController.setPanelExpansion(0.8f);
Lucas Dupin067136c2018-03-27 18:03:25 -0700336 verifyZeroInteractions(mScrimBehind);
Lucas Dupin67f02632018-03-12 11:08:31 -0700337 Assert.assertEquals("Scrim opacity shouldn't change when setExpansionAffectsAlpha "
338 + "is false", scrimAlpha, mScrimBehind.getViewAlpha(), 0.01f);
339
340 mScrimController.setExpansionAffectsAlpha(true);
341 mScrimController.setPanelExpansion(0.1f);
Lucas Dupin4dbe5182019-03-07 18:20:11 -0800342 mScrimController.finishAnimationsImmediately();
Lucas Dupin67f02632018-03-12 11:08:31 -0700343 Assert.assertNotEquals("Scrim opacity should change when setExpansionAffectsAlpha "
344 + "is true", scrimAlpha, mScrimBehind.getViewAlpha(), 0.01f);
345 }
346
347 @Test
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800348 public void transitionToUnlockedFromAod() {
349 // Simulate unlock with fingerprint
350 mScrimController.transitionTo(ScrimState.AOD);
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800351 mScrimController.setPanelExpansion(0f);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800352 mScrimController.finishAnimationsImmediately();
353 mScrimController.transitionTo(ScrimState.UNLOCKED);
354 // Immediately tinted after the transition starts
355 assertScrimTint(mScrimInFront, true /* tinted */);
356 assertScrimTint(mScrimBehind, true /* tinted */);
357 mScrimController.finishAnimationsImmediately();
358 // Front scrim should be transparent
359 // Back scrim should be transparent
360 // Neither scrims should be tinted anymore after the animation.
Lucas Dupin82aa1632017-12-13 00:13:57 -0800361 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800362 assertScrimTint(mScrimInFront, false /* tinted */);
363 assertScrimTint(mScrimBehind, false /* tinted */);
364 }
365
366 @Test
Lucas Dupinea0116e2018-04-05 10:09:29 -0700367 public void scrimBlanksBeforeLeavingAod() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800368 // Simulate unlock with fingerprint
369 mScrimController.transitionTo(ScrimState.AOD);
370 mScrimController.finishAnimationsImmediately();
371 mScrimController.transitionTo(ScrimState.UNLOCKED,
372 new ScrimController.Callback() {
373 @Override
374 public void onDisplayBlanked() {
375 // Front scrim should be black in the middle of the transition
376 Assert.assertTrue("Scrim should be visible during transition. Alpha: "
377 + mScrimInFront.getViewAlpha(), mScrimInFront.getViewAlpha() > 0);
378 assertScrimTint(mScrimInFront, true /* tinted */);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800379 Assert.assertSame("Scrim should be visible during transition.",
380 mScrimVisibility, VISIBILITY_FULLY_OPAQUE);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800381 }
382 });
383 mScrimController.finishAnimationsImmediately();
384 }
385
386 @Test
Lucas Dupineb840ea2018-06-01 00:28:58 -0700387 public void scrimBlanksWhenUnlockingFromPulse() {
388 boolean[] blanked = {false};
389 // Simulate unlock with fingerprint
390 mScrimController.transitionTo(ScrimState.PULSING);
391 mScrimController.finishAnimationsImmediately();
392 mScrimController.transitionTo(ScrimState.UNLOCKED,
393 new ScrimController.Callback() {
394 @Override
395 public void onDisplayBlanked() {
396 blanked[0] = true;
397 }
398 });
399 mScrimController.finishAnimationsImmediately();
400 Assert.assertTrue("Scrim should blank when unlocking from pulse.", blanked[0]);
401 }
402
403 @Test
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800404 public void testScrimCallback() {
405 int[] callOrder = {0, 0, 0};
406 int[] currentCall = {0};
407 mScrimController.transitionTo(ScrimState.AOD, new ScrimController.Callback() {
408 @Override
409 public void onStart() {
410 callOrder[0] = ++currentCall[0];
411 }
412
413 @Override
414 public void onDisplayBlanked() {
415 callOrder[1] = ++currentCall[0];
416 }
417
418 @Override
419 public void onFinished() {
420 callOrder[2] = ++currentCall[0];
421 }
422 });
423 mScrimController.finishAnimationsImmediately();
424 Assert.assertEquals("onStart called in wrong order", 1, callOrder[0]);
425 Assert.assertEquals("onDisplayBlanked called in wrong order", 2, callOrder[1]);
426 Assert.assertEquals("onFinished called in wrong order", 3, callOrder[2]);
427 }
428
429 @Test
430 public void testScrimCallbacksWithoutAmbientDisplay() {
431 mAlwaysOnEnabled = false;
432 testScrimCallback();
433 }
434
435 @Test
436 public void testScrimCallbackCancelled() {
437 boolean[] cancelledCalled = {false};
438 mScrimController.transitionTo(ScrimState.AOD, new ScrimController.Callback() {
439 @Override
440 public void onCancelled() {
441 cancelledCalled[0] = true;
442 }
443 });
444 mScrimController.transitionTo(ScrimState.PULSING);
445 Assert.assertTrue("onCancelled should have been called", cancelledCalled[0]);
446 }
447
448 @Test
Lucas Dupineea53b32017-12-18 13:47:14 -0800449 public void testHoldsWakeLock_whenAOD() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800450 mScrimController.transitionTo(ScrimState.AOD);
Lucas Dupinee4c9b72019-02-18 17:04:58 -0800451 verify(mWakeLock).acquire(anyString());
452 verify(mWakeLock, never()).release(anyString());
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800453 mScrimController.finishAnimationsImmediately();
Lucas Dupinee4c9b72019-02-18 17:04:58 -0800454 verify(mWakeLock).release(anyString());
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800455 }
456
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800457 @Test
Lucas Dupineea53b32017-12-18 13:47:14 -0800458 public void testDoesNotHoldWakeLock_whenUnlocking() {
459 mScrimController.transitionTo(ScrimState.UNLOCKED);
460 mScrimController.finishAnimationsImmediately();
461 verifyZeroInteractions(mWakeLock);
462 }
463
464 @Test
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800465 public void testCallbackInvokedOnSameStateTransition() {
466 mScrimController.transitionTo(ScrimState.UNLOCKED);
467 mScrimController.finishAnimationsImmediately();
468 ScrimController.Callback callback = mock(ScrimController.Callback.class);
469 mScrimController.transitionTo(ScrimState.UNLOCKED, callback);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800470 verify(callback).onFinished();
471 }
472
473 @Test
474 public void testHoldsAodWallpaperAnimationLock() {
475 // Pre-conditions
476 mScrimController.transitionTo(ScrimState.AOD);
477 mScrimController.finishAnimationsImmediately();
478 reset(mWakeLock);
479
480 mScrimController.onHideWallpaperTimeout();
Lucas Dupinee4c9b72019-02-18 17:04:58 -0800481 verify(mWakeLock).acquire(anyString());
482 verify(mWakeLock, never()).release(anyString());
Lucas Dupin82aa1632017-12-13 00:13:57 -0800483 mScrimController.finishAnimationsImmediately();
Lucas Dupinee4c9b72019-02-18 17:04:58 -0800484 verify(mWakeLock).release(anyString());
Lucas Dupin82aa1632017-12-13 00:13:57 -0800485 }
486
487 @Test
TYM Tsaia71c8922019-01-07 15:57:53 +0800488 public void testHoldsPulsingWallpaperAnimationLock() {
489 // Pre-conditions
Lucas Dupin00be88f2019-01-03 17:50:52 -0800490 mScrimController.transitionTo(ScrimState.PULSING);
TYM Tsaia71c8922019-01-07 15:57:53 +0800491 mScrimController.finishAnimationsImmediately();
492 reset(mWakeLock);
493
494 mScrimController.onHideWallpaperTimeout();
Lucas Dupinee4c9b72019-02-18 17:04:58 -0800495 verify(mWakeLock).acquire(anyString());
496 verify(mWakeLock, never()).release(anyString());
TYM Tsaia71c8922019-01-07 15:57:53 +0800497 mScrimController.finishAnimationsImmediately();
Lucas Dupinee4c9b72019-02-18 17:04:58 -0800498 verify(mWakeLock).release(anyString());
TYM Tsaia71c8922019-01-07 15:57:53 +0800499 }
500
501 @Test
Lucas Dupin16cfe452018-02-08 13:14:50 -0800502 public void testWillHideAodWallpaper() {
Lucas Dupin82aa1632017-12-13 00:13:57 -0800503 mScrimController.setWallpaperSupportsAmbientMode(true);
504 mScrimController.transitionTo(ScrimState.AOD);
505 verify(mAlarmManager).setExact(anyInt(), anyLong(), any(), any(), any());
506 mScrimController.transitionTo(ScrimState.KEYGUARD);
507 verify(mAlarmManager).cancel(any(AlarmManager.OnAlarmListener.class));
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800508 }
509
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800510 @Test
511 public void testConservesExpansionOpacityAfterTransition() {
512 mScrimController.transitionTo(ScrimState.UNLOCKED);
513 mScrimController.setPanelExpansion(0.5f);
514 mScrimController.finishAnimationsImmediately();
515
516 final float expandedAlpha = mScrimBehind.getViewAlpha();
517
518 mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR);
519 mScrimController.finishAnimationsImmediately();
520 mScrimController.transitionTo(ScrimState.UNLOCKED);
521 mScrimController.finishAnimationsImmediately();
522
523 Assert.assertEquals("Scrim expansion opacity wasn't conserved when transitioning back",
524 expandedAlpha, mScrimBehind.getViewAlpha(), 0.01f);
525 }
526
527 @Test
528 public void cancelsOldAnimationBeforeBlanking() {
529 mScrimController.transitionTo(ScrimState.AOD);
530 mScrimController.finishAnimationsImmediately();
531 // Consume whatever value we had before
532 mScrimController.wasAnimationJustCancelled();
533
534 mScrimController.transitionTo(ScrimState.KEYGUARD);
535 mScrimController.finishAnimationsImmediately();
536 Assert.assertTrue(mScrimController.wasAnimationJustCancelled());
537 }
538
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800539 @Test
Lucas Dupin38962d72018-03-14 12:41:39 -0700540 public void testScrimFocus() {
541 mScrimController.transitionTo(ScrimState.AOD);
542 Assert.assertFalse("Should not be focusable on AOD", mScrimBehind.isFocusable());
543 Assert.assertFalse("Should not be focusable on AOD", mScrimInFront.isFocusable());
544
545 mScrimController.transitionTo(ScrimState.KEYGUARD);
546 Assert.assertTrue("Should be focusable on keyguard", mScrimBehind.isFocusable());
547 Assert.assertTrue("Should be focusable on keyguard", mScrimInFront.isFocusable());
548 }
549
Lucas Dupind5107302018-03-19 15:30:29 -0700550 @Test
551 public void testHidesShowWhenLockedActivity() {
552 mScrimController.setWallpaperSupportsAmbientMode(true);
553 mScrimController.setKeyguardOccluded(true);
554 mScrimController.transitionTo(ScrimState.AOD);
555 mScrimController.finishAnimationsImmediately();
556 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
557
558 mScrimController.transitionTo(ScrimState.PULSING);
559 mScrimController.finishAnimationsImmediately();
560 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
561 }
562
Lucas Dupin78949b82018-04-03 18:54:39 -0700563 @Test
Lucas Dupin63d72172018-06-06 11:42:55 -0700564 public void testHidesShowWhenLockedActivity_whenAlreadyInAod() {
565 mScrimController.setWallpaperSupportsAmbientMode(true);
566 mScrimController.transitionTo(ScrimState.AOD);
567 mScrimController.finishAnimationsImmediately();
568 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
569
570 mScrimController.setKeyguardOccluded(true);
571 mScrimController.finishAnimationsImmediately();
572 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
573 }
574
575 @Test
Lucas Dupin78949b82018-04-03 18:54:39 -0700576 public void testEatsTouchEvent() {
577 HashSet<ScrimState> eatsTouches =
Lucas Dupin1c327432019-01-03 13:37:53 -0800578 new HashSet<>(Collections.singletonList(ScrimState.AOD));
Lucas Dupin78949b82018-04-03 18:54:39 -0700579 for (ScrimState state : ScrimState.values()) {
580 if (state == ScrimState.UNINITIALIZED) {
581 continue;
582 }
583 mScrimController.transitionTo(state);
584 mScrimController.finishAnimationsImmediately();
585 Assert.assertEquals("Should be clickable unless AOD or PULSING, was: " + state,
586 mScrimBehind.getViewAlpha() != 0 && !eatsTouches.contains(state),
587 mScrimBehind.isClickable());
588 }
589 }
590
Lucas Dupinea0116e2018-04-05 10:09:29 -0700591 @Test
592 public void testAnimatesTransitionToAod() {
593 when(mDozeParamenters.shouldControlScreenOff()).thenReturn(false);
594 ScrimState.AOD.prepare(ScrimState.KEYGUARD);
595 Assert.assertFalse("No animation when ColorFade kicks in",
596 ScrimState.AOD.getAnimateChange());
597
598 reset(mDozeParamenters);
599 when(mDozeParamenters.shouldControlScreenOff()).thenReturn(true);
600 ScrimState.AOD.prepare(ScrimState.KEYGUARD);
601 Assert.assertTrue("Animate scrims when ColorFade won't be triggered",
602 ScrimState.AOD.getAnimateChange());
603 }
604
Lucas Dupin373356b2018-04-07 10:50:25 -0700605 @Test
606 public void testViewsDontHaveFocusHighlight() {
607 Assert.assertFalse("Scrim shouldn't have focus highlight",
608 mScrimInFront.getDefaultFocusHighlightEnabled());
609 Assert.assertFalse("Scrim shouldn't have focus highlight",
610 mScrimBehind.getDefaultFocusHighlightEnabled());
611 }
612
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800613 private void assertScrimTint(ScrimView scrimView, boolean tinted) {
614 final boolean viewIsTinted = scrimView.getTint() != Color.TRANSPARENT;
615 final String name = scrimView == mScrimInFront ? "front" : "back";
616 Assert.assertEquals("Tint test failed at state " + mScrimController.getState()
617 +" with scrim: " + name + " and tint: " + Integer.toHexString(scrimView.getTint()),
618 tinted, viewIsTinted);
619 }
620
Lucas Dupin82aa1632017-12-13 00:13:57 -0800621 private void assertScrimVisibility(int inFront, int behind) {
622 boolean inFrontVisible = inFront != ScrimController.VISIBILITY_FULLY_TRANSPARENT;
623 boolean behindVisible = behind != ScrimController.VISIBILITY_FULLY_TRANSPARENT;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800624 Assert.assertEquals("Unexpected front scrim visibility. Alpha is "
Lucas Dupin82aa1632017-12-13 00:13:57 -0800625 + mScrimInFront.getViewAlpha(), inFrontVisible, mScrimInFront.getViewAlpha() > 0);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800626 Assert.assertEquals("Unexpected back scrim visibility. Alpha is "
Lucas Dupin82aa1632017-12-13 00:13:57 -0800627 + mScrimBehind.getViewAlpha(), behindVisible, mScrimBehind.getViewAlpha() > 0);
628
629 final int visibility;
630 if (inFront == VISIBILITY_FULLY_OPAQUE || behind == VISIBILITY_FULLY_OPAQUE) {
631 visibility = VISIBILITY_FULLY_OPAQUE;
632 } else if (inFront > VISIBILITY_FULLY_TRANSPARENT || behind > VISIBILITY_FULLY_TRANSPARENT) {
633 visibility = VISIBILITY_SEMI_TRANSPARENT;
634 } else {
635 visibility = VISIBILITY_FULLY_TRANSPARENT;
636 }
637 Assert.assertEquals("Invalid visibility.", visibility, mScrimVisibility);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800638 }
639
640 /**
641 * Special version of ScrimController where animations have 0 duration for test purposes.
642 */
643 private class SynchronousScrimController extends ScrimController {
644
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800645 private boolean mAnimationCancelled;
Lucas Dupin16cfe452018-02-08 13:14:50 -0800646 boolean mOnPreDrawCalled;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800647
shawnlin317db372018-04-09 19:49:48 +0800648 SynchronousScrimController(ScrimView scrimBehind, ScrimView scrimInFront,
Yohei Yukawa795f0102018-04-13 14:55:30 -0700649 TriConsumer<ScrimState, Float, GradientColors> scrimStateListener,
Lucas Dupin82aa1632017-12-13 00:13:57 -0800650 Consumer<Integer> scrimVisibleListener, DozeParameters dozeParameters,
651 AlarmManager alarmManager) {
Yohei Yukawa795f0102018-04-13 14:55:30 -0700652 super(scrimBehind, scrimInFront, scrimStateListener, scrimVisibleListener,
653 dozeParameters, alarmManager);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800654 }
655
Lucas Dupin16cfe452018-02-08 13:14:50 -0800656 @Override
657 public boolean onPreDraw() {
658 mOnPreDrawCalled = true;
659 return super.onPreDraw();
660 }
661
Lucas Dupin3503c5f2018-03-02 19:04:00 -0800662 void finishAnimationsImmediately() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800663 boolean[] animationFinished = {false};
664 setOnAnimationFinished(()-> animationFinished[0] = true);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800665 // Execute code that will trigger animations.
666 onPreDraw();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800667 // Force finish all animations.
Lucas Dupin54fbfb32019-03-05 18:08:13 -0800668 mLooper.processAllMessages();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800669 endAnimation(mScrimBehind, TAG_KEY_ANIM);
670 endAnimation(mScrimInFront, TAG_KEY_ANIM);
671
672 if (!animationFinished[0]) {
673 throw new IllegalStateException("Animation never finished");
674 }
675 }
676
Lucas Dupin3503c5f2018-03-02 19:04:00 -0800677 boolean wasAnimationJustCancelled() {
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800678 final boolean wasCancelled = mAnimationCancelled;
679 mAnimationCancelled = false;
680 return wasCancelled;
681 }
682
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800683 private void endAnimation(View scrimView, int tag) {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800684 Animator animator = (Animator) scrimView.getTag(tag);
685 if (animator != null) {
686 animator.end();
687 }
688 }
689
690 @Override
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800691 protected void cancelAnimator(ValueAnimator previousAnimator) {
692 super.cancelAnimator(previousAnimator);
693 mAnimationCancelled = true;
694 }
695
696 @Override
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800697 protected Handler getHandler() {
Lucas Dupin54fbfb32019-03-05 18:08:13 -0800698 return new FakeHandler(mLooper.getLooper());
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800699 }
700
701 @Override
702 protected WakeLock createWakeLock() {
703 return mWakeLock;
704 }
Lucas Dupin8c7cb022018-02-05 10:49:03 -0800705
706 /**
707 * Do not wait for a frame since we're in a test environment.
708 * @param callback What to execute.
709 */
710 @Override
Lucas Dupin0791d972018-03-26 13:32:16 -0700711 protected void doOnTheNextFrame(Runnable callback) {
712 callback.run();
Lucas Dupin8c7cb022018-02-05 10:49:03 -0800713 }
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800714 }
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800715}