blob: 7e5c3db046e1cee73ae887df4b1a994c010fe21b [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;
Lucas Dupin00be88f2019-01-03 17:50:52 -080049import com.android.systemui.doze.DozeLog;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080050import com.android.systemui.statusbar.ScrimView;
51import com.android.systemui.util.wakelock.WakeLock;
52import com.android.systemui.utils.os.FakeHandler;
53
Lucas Dupin4dbe5182019-03-07 18:20:11 -080054import org.junit.After;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080055import org.junit.Assert;
56import org.junit.Before;
57import org.junit.Test;
58import org.junit.runner.RunWith;
59
Lucas Dupin1c327432019-01-03 13:37:53 -080060import java.util.Collections;
Lucas Dupin78949b82018-04-03 18:54:39 -070061import java.util.HashSet;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080062import java.util.function.Consumer;
63
64@RunWith(AndroidTestingRunner.class)
65@TestableLooper.RunWithLooper
66@SmallTest
67public class ScrimControllerTest extends SysuiTestCase {
68
69 private SynchronousScrimController mScrimController;
70 private ScrimView mScrimBehind;
71 private ScrimView mScrimInFront;
Yohei Yukawa795f0102018-04-13 14:55:30 -070072 private ScrimState mScrimState;
shawnlin317db372018-04-09 19:49:48 +080073 private float mScrimBehindAlpha;
74 private GradientColors mScrimInFrontColor;
Lucas Dupin82aa1632017-12-13 00:13:57 -080075 private int mScrimVisibility;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080076 private DozeParameters mDozeParamenters;
77 private WakeLock mWakeLock;
78 private boolean mAlwaysOnEnabled;
Lucas Dupin82aa1632017-12-13 00:13:57 -080079 private AlarmManager mAlarmManager;
Lucas Dupin54fbfb32019-03-05 18:08:13 -080080 private TestableLooper mLooper;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080081
Yohei Yukawa795f0102018-04-13 14:55:30 -070082
Lucas Dupin9e3fa102017-11-08 17:16:55 -080083 @Before
84 public void setup() {
Lucas Dupin067136c2018-03-27 18:03:25 -070085 mScrimBehind = spy(new ScrimView(getContext()));
Lucas Dupin9e3fa102017-11-08 17:16:55 -080086 mScrimInFront = new ScrimView(getContext());
Lucas Dupin9e3fa102017-11-08 17:16:55 -080087 mWakeLock = mock(WakeLock.class);
Lucas Dupin82aa1632017-12-13 00:13:57 -080088 mAlarmManager = mock(AlarmManager.class);
Lucas Dupin9e3fa102017-11-08 17:16:55 -080089 mAlwaysOnEnabled = true;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080090 mDozeParamenters = mock(DozeParameters.class);
Lucas Dupin54fbfb32019-03-05 18:08:13 -080091 mLooper = TestableLooper.get(this);
Lucas Dupin9e3fa102017-11-08 17:16:55 -080092 when(mDozeParamenters.getAlwaysOn()).thenAnswer(invocation -> mAlwaysOnEnabled);
Lucas Dupin43d0d732017-11-16 11:23:49 -080093 when(mDozeParamenters.getDisplayNeedsBlanking()).thenReturn(true);
shawnlin317db372018-04-09 19:49:48 +080094 mScrimController = new SynchronousScrimController(mScrimBehind, mScrimInFront,
Yohei Yukawa795f0102018-04-13 14:55:30 -070095 (scrimState, scrimBehindAlpha, scrimInFrontColor) -> {
96 mScrimState = scrimState;
97 mScrimBehindAlpha = scrimBehindAlpha;
98 mScrimInFrontColor = scrimInFrontColor;
99 },
100 visible -> mScrimVisibility = visible, mDozeParamenters, mAlarmManager);
Lucas Dupinf8463ee2018-06-11 16:18:15 -0700101 mScrimController.setHasBackdrop(false);
TYM Tsaia71c8922019-01-07 15:57:53 +0800102 mScrimController.setWallpaperSupportsAmbientMode(false);
Lucas Dupin4dbe5182019-03-07 18:20:11 -0800103 mScrimController.transitionTo(ScrimState.KEYGUARD);
104 mScrimController.finishAnimationsImmediately();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800105 }
106
Lucas Dupin4dbe5182019-03-07 18:20:11 -0800107 @After
108 public void tearDown() {
109 mScrimController.finishAnimationsImmediately();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800110 }
111
112 @Test
113 public void transitionToKeyguard() {
114 mScrimController.transitionTo(ScrimState.KEYGUARD);
115 mScrimController.finishAnimationsImmediately();
116 // Front scrim should be transparent
117 // Back scrim should be visible without tint
Lucas Dupin82aa1632017-12-13 00:13:57 -0800118 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
Lucas Dupin1113fdf2019-03-07 17:32:00 -0800119 assertScrimTint(mScrimBehind, true /* tinted */);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800120 }
121
122 @Test
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700123 public void transitionToAod_withRegularWallpaper() {
124 mScrimController.transitionTo(ScrimState.AOD);
125 mScrimController.finishAnimationsImmediately();
126 // Front scrim should be transparent
127 // Back scrim should be visible with tint
Lucas Dupin82aa1632017-12-13 00:13:57 -0800128 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700129 assertScrimTint(mScrimBehind, true /* tinted */);
130 assertScrimTint(mScrimInFront, true /* tinted */);
131 }
132
133 @Test
134 public void transitionToAod_withAodWallpaper() {
135 mScrimController.setWallpaperSupportsAmbientMode(true);
136 mScrimController.transitionTo(ScrimState.AOD);
137 mScrimController.finishAnimationsImmediately();
138 // Front scrim should be transparent
139 // Back scrim should be transparent
Lucas Dupin82aa1632017-12-13 00:13:57 -0800140 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
141
Lucas Dupin00be88f2019-01-03 17:50:52 -0800142 // Pulsing notification should conserve AOD wallpaper.
143 mScrimController.setPulseReason(DozeLog.PULSE_REASON_NOTIFICATION);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800144 mScrimController.transitionTo(ScrimState.PULSING);
145 mScrimController.finishAnimationsImmediately();
Lucas Dupin00be88f2019-01-03 17:50:52 -0800146 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700147 }
148
149 @Test
150 public void transitionToAod_withAodWallpaperAndLockScreenWallpaper() {
Lucas Dupinf8463ee2018-06-11 16:18:15 -0700151 mScrimController.setHasBackdrop(true);
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700152 mScrimController.setWallpaperSupportsAmbientMode(true);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800153 mScrimController.transitionTo(ScrimState.AOD);
154 mScrimController.finishAnimationsImmediately();
155 // Front scrim should be transparent
156 // Back scrim should be visible with tint
Lucas Dupin82aa1632017-12-13 00:13:57 -0800157 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800158 assertScrimTint(mScrimBehind, true /* tinted */);
159 assertScrimTint(mScrimInFront, true /* tinted */);
160 }
161
162 @Test
Lucas Dupin9bee5822018-07-09 14:32:53 -0700163 public void setHasBackdrop_withAodWallpaperAndAlbumArt() {
164 mScrimController.setWallpaperSupportsAmbientMode(true);
165 mScrimController.transitionTo(ScrimState.AOD);
166 mScrimController.finishAnimationsImmediately();
167 mScrimController.setHasBackdrop(true);
168 mScrimController.finishAnimationsImmediately();
169 // Front scrim should be transparent
170 // Back scrim should be visible with tint
171 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
172 assertScrimTint(mScrimBehind, true /* tinted */);
173 assertScrimTint(mScrimInFront, true /* tinted */);
174 }
175
176 @Test
Michael Wrightcae88752018-04-16 23:13:54 +0100177 public void transitionToAod_withFrontAlphaUpdates() {
178 // Assert that setting the AOD front scrim alpha doesn't take effect in a non-AOD state.
179 mScrimController.transitionTo(ScrimState.KEYGUARD);
180 mScrimController.setAodFrontScrimAlpha(0.5f);
181 mScrimController.finishAnimationsImmediately();
182 // Front scrim should be transparent
183 // Back scrim should be visible without tint
184 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
185
186 // ... but that it does take effect once we enter the AOD state.
187 mScrimController.transitionTo(ScrimState.AOD);
188 mScrimController.finishAnimationsImmediately();
189 // Front scrim should be semi-transparent
190 // Back scrim should be visible
191 assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
192
193 // ... and that if we set it while we're in AOD, it does take immediate effect.
194 mScrimController.setAodFrontScrimAlpha(1f);
195 assertScrimVisibility(VISIBILITY_FULLY_OPAQUE, VISIBILITY_FULLY_OPAQUE);
196
197 // ... and make sure we recall the previous front scrim alpha even if we transition away
198 // for a bit.
199 mScrimController.transitionTo(ScrimState.UNLOCKED);
200 mScrimController.transitionTo(ScrimState.AOD);
201 mScrimController.finishAnimationsImmediately();
202 assertScrimVisibility(VISIBILITY_FULLY_OPAQUE, VISIBILITY_FULLY_OPAQUE);
203
Lucas Dupin69bda602018-05-18 17:24:52 -0700204 // ... and alpha updates should be completely ignored if always_on is off.
205 // Passing it forward would mess up the wake-up transition.
206 mAlwaysOnEnabled = false;
207 mScrimController.transitionTo(ScrimState.UNLOCKED);
208 mScrimController.transitionTo(ScrimState.AOD);
209 mScrimController.finishAnimationsImmediately();
210 mScrimController.setAodFrontScrimAlpha(0.3f);
211 Assert.assertEquals(ScrimState.AOD.getFrontAlpha(), mScrimInFront.getViewAlpha(), 0.001f);
212 Assert.assertNotEquals(0.3f, mScrimInFront.getViewAlpha(), 0.001f);
213
Michael Wrightcae88752018-04-16 23:13:54 +0100214 // Reset value since enums are static.
215 mScrimController.setAodFrontScrimAlpha(0f);
216 }
217
218 @Test
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800219 public void transitionToPulsing() {
Lucas Dupin82aa1632017-12-13 00:13:57 -0800220 // Pre-condition
221 // Need to go to AoD first because PULSING doesn't change
222 // the back scrim opacity - otherwise it would hide AoD wallpapers.
223 mScrimController.setWallpaperSupportsAmbientMode(false);
224 mScrimController.transitionTo(ScrimState.AOD);
225 mScrimController.finishAnimationsImmediately();
226 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
227
Lucas Dupin00be88f2019-01-03 17:50:52 -0800228 mScrimController.setPulseReason(DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800229 mScrimController.transitionTo(ScrimState.PULSING);
230 mScrimController.finishAnimationsImmediately();
231 // Front scrim should be transparent
Lucas Dupinde64ee02018-12-21 14:45:12 -0800232 // Back scrim should be semi-transparent so the user can see the wallpaper
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800233 // Pulse callback should have been invoked
Lucas Dupinde64ee02018-12-21 14:45:12 -0800234 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
Lucas Dupin3d36dd82019-01-02 14:38:35 -0800235 assertScrimTint(mScrimBehind, false /* tinted */);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800236 }
237
238 @Test
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800239 public void transitionToKeyguardBouncer() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800240 mScrimController.transitionTo(ScrimState.BOUNCER);
241 mScrimController.finishAnimationsImmediately();
242 // Front scrim should be transparent
243 // Back scrim should be visible without tint
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800244 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
245 assertScrimTint(mScrimBehind, false /* tinted */);
246 }
247
248 @Test
249 public void transitionToBouncer() {
Lucas Dupin05726cd2018-03-13 14:00:24 -0700250 mScrimController.transitionTo(ScrimState.BOUNCER_SCRIMMED);
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800251 mScrimController.finishAnimationsImmediately();
252 // Front scrim should be transparent
253 // Back scrim should be visible without tint
254 assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800255 assertScrimTint(mScrimBehind, false /* tinted */);
256 }
257
258 @Test
259 public void transitionToUnlocked() {
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800260 mScrimController.setPanelExpansion(0f);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800261 mScrimController.transitionTo(ScrimState.UNLOCKED);
262 mScrimController.finishAnimationsImmediately();
263 // Front scrim should be transparent
264 // Back scrim should be transparent
Lucas Dupin82aa1632017-12-13 00:13:57 -0800265 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800266 assertScrimTint(mScrimBehind, false /* tinted */);
267 assertScrimTint(mScrimInFront, false /* tinted */);
268
269 // Back scrim should be visible after start dragging
270 mScrimController.setPanelExpansion(0.5f);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800271 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800272 }
273
274 @Test
Mady Mellor0c333772018-11-06 18:05:54 -0800275 public void transitionToBubbleExpanded() {
276 mScrimController.transitionTo(ScrimState.BUBBLE_EXPANDED);
277 mScrimController.finishAnimationsImmediately();
278
279 // Front scrim should be transparent
280 Assert.assertEquals(ScrimController.VISIBILITY_FULLY_TRANSPARENT,
281 mScrimInFront.getViewAlpha(), 0.0f);
282 // Back scrim should be visible
283 Assert.assertEquals(ScrimController.GRADIENT_SCRIM_ALPHA_BUSY,
284 mScrimBehind.getViewAlpha(), 0.0f);
285 }
286
287 @Test
Yohei Yukawa795f0102018-04-13 14:55:30 -0700288 public void scrimStateCallback() {
289 mScrimController.transitionTo(ScrimState.UNLOCKED);
290 mScrimController.finishAnimationsImmediately();
291 Assert.assertEquals(mScrimState, ScrimState.UNLOCKED);
292
293 mScrimController.transitionTo(ScrimState.BOUNCER);
294 mScrimController.finishAnimationsImmediately();
295 Assert.assertEquals(mScrimState, ScrimState.BOUNCER);
296
297 mScrimController.transitionTo(ScrimState.BOUNCER_SCRIMMED);
298 mScrimController.finishAnimationsImmediately();
299 Assert.assertEquals(mScrimState, ScrimState.BOUNCER_SCRIMMED);
300 }
301
302 @Test
shawnlin317db372018-04-09 19:49:48 +0800303 public void panelExpansion() {
304 mScrimController.setPanelExpansion(0f);
305 mScrimController.setPanelExpansion(0.5f);
306 mScrimController.transitionTo(ScrimState.UNLOCKED);
307 mScrimController.finishAnimationsImmediately();
308
309 reset(mScrimBehind);
310 mScrimController.setPanelExpansion(0f);
311 mScrimController.setPanelExpansion(1.0f);
Lucas Dupin4dbe5182019-03-07 18:20:11 -0800312 mScrimController.finishAnimationsImmediately();
shawnlin317db372018-04-09 19:49:48 +0800313
314 Assert.assertEquals("Scrim alpha should change after setPanelExpansion",
315 mScrimBehindAlpha, mScrimBehind.getViewAlpha(), 0.01f);
316
317 mScrimController.setPanelExpansion(0f);
Lucas Dupin4dbe5182019-03-07 18:20:11 -0800318 mScrimController.finishAnimationsImmediately();
shawnlin317db372018-04-09 19:49:48 +0800319
320 Assert.assertEquals("Scrim alpha should change after setPanelExpansion",
321 mScrimBehindAlpha, mScrimBehind.getViewAlpha(), 0.01f);
322 }
323
324 @Test
Lucas Dupin67f02632018-03-12 11:08:31 -0700325 public void panelExpansionAffectsAlpha() {
326 mScrimController.setPanelExpansion(0f);
327 mScrimController.setPanelExpansion(0.5f);
328 mScrimController.transitionTo(ScrimState.UNLOCKED);
329 mScrimController.finishAnimationsImmediately();
330
331 final float scrimAlpha = mScrimBehind.getViewAlpha();
Lucas Dupin067136c2018-03-27 18:03:25 -0700332 reset(mScrimBehind);
Lucas Dupin67f02632018-03-12 11:08:31 -0700333 mScrimController.setExpansionAffectsAlpha(false);
334 mScrimController.setPanelExpansion(0.8f);
Lucas Dupin067136c2018-03-27 18:03:25 -0700335 verifyZeroInteractions(mScrimBehind);
Lucas Dupin67f02632018-03-12 11:08:31 -0700336 Assert.assertEquals("Scrim opacity shouldn't change when setExpansionAffectsAlpha "
337 + "is false", scrimAlpha, mScrimBehind.getViewAlpha(), 0.01f);
338
339 mScrimController.setExpansionAffectsAlpha(true);
340 mScrimController.setPanelExpansion(0.1f);
Lucas Dupin4dbe5182019-03-07 18:20:11 -0800341 mScrimController.finishAnimationsImmediately();
Lucas Dupin67f02632018-03-12 11:08:31 -0700342 Assert.assertNotEquals("Scrim opacity should change when setExpansionAffectsAlpha "
343 + "is true", scrimAlpha, mScrimBehind.getViewAlpha(), 0.01f);
344 }
345
346 @Test
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800347 public void transitionToUnlockedFromAod() {
348 // Simulate unlock with fingerprint
349 mScrimController.transitionTo(ScrimState.AOD);
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800350 mScrimController.setPanelExpansion(0f);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800351 mScrimController.finishAnimationsImmediately();
352 mScrimController.transitionTo(ScrimState.UNLOCKED);
353 // Immediately tinted after the transition starts
354 assertScrimTint(mScrimInFront, true /* tinted */);
355 assertScrimTint(mScrimBehind, true /* tinted */);
356 mScrimController.finishAnimationsImmediately();
357 // Front scrim should be transparent
358 // Back scrim should be transparent
359 // Neither scrims should be tinted anymore after the animation.
Lucas Dupin82aa1632017-12-13 00:13:57 -0800360 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800361 assertScrimTint(mScrimInFront, false /* tinted */);
362 assertScrimTint(mScrimBehind, false /* tinted */);
363 }
364
365 @Test
Lucas Dupinea0116e2018-04-05 10:09:29 -0700366 public void scrimBlanksBeforeLeavingAod() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800367 // Simulate unlock with fingerprint
368 mScrimController.transitionTo(ScrimState.AOD);
369 mScrimController.finishAnimationsImmediately();
370 mScrimController.transitionTo(ScrimState.UNLOCKED,
371 new ScrimController.Callback() {
372 @Override
373 public void onDisplayBlanked() {
374 // Front scrim should be black in the middle of the transition
375 Assert.assertTrue("Scrim should be visible during transition. Alpha: "
376 + mScrimInFront.getViewAlpha(), mScrimInFront.getViewAlpha() > 0);
377 assertScrimTint(mScrimInFront, true /* tinted */);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800378 Assert.assertSame("Scrim should be visible during transition.",
379 mScrimVisibility, VISIBILITY_FULLY_OPAQUE);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800380 }
381 });
382 mScrimController.finishAnimationsImmediately();
383 }
384
385 @Test
Lucas Dupineb840ea2018-06-01 00:28:58 -0700386 public void scrimBlanksWhenUnlockingFromPulse() {
387 boolean[] blanked = {false};
388 // Simulate unlock with fingerprint
389 mScrimController.transitionTo(ScrimState.PULSING);
390 mScrimController.finishAnimationsImmediately();
391 mScrimController.transitionTo(ScrimState.UNLOCKED,
392 new ScrimController.Callback() {
393 @Override
394 public void onDisplayBlanked() {
395 blanked[0] = true;
396 }
397 });
398 mScrimController.finishAnimationsImmediately();
399 Assert.assertTrue("Scrim should blank when unlocking from pulse.", blanked[0]);
400 }
401
402 @Test
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800403 public void testScrimCallback() {
404 int[] callOrder = {0, 0, 0};
405 int[] currentCall = {0};
406 mScrimController.transitionTo(ScrimState.AOD, new ScrimController.Callback() {
407 @Override
408 public void onStart() {
409 callOrder[0] = ++currentCall[0];
410 }
411
412 @Override
413 public void onDisplayBlanked() {
414 callOrder[1] = ++currentCall[0];
415 }
416
417 @Override
418 public void onFinished() {
419 callOrder[2] = ++currentCall[0];
420 }
421 });
422 mScrimController.finishAnimationsImmediately();
423 Assert.assertEquals("onStart called in wrong order", 1, callOrder[0]);
424 Assert.assertEquals("onDisplayBlanked called in wrong order", 2, callOrder[1]);
425 Assert.assertEquals("onFinished called in wrong order", 3, callOrder[2]);
426 }
427
428 @Test
429 public void testScrimCallbacksWithoutAmbientDisplay() {
430 mAlwaysOnEnabled = false;
431 testScrimCallback();
432 }
433
434 @Test
435 public void testScrimCallbackCancelled() {
436 boolean[] cancelledCalled = {false};
437 mScrimController.transitionTo(ScrimState.AOD, new ScrimController.Callback() {
438 @Override
439 public void onCancelled() {
440 cancelledCalled[0] = true;
441 }
442 });
443 mScrimController.transitionTo(ScrimState.PULSING);
444 Assert.assertTrue("onCancelled should have been called", cancelledCalled[0]);
445 }
446
447 @Test
Lucas Dupineea53b32017-12-18 13:47:14 -0800448 public void testHoldsWakeLock_whenAOD() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800449 mScrimController.transitionTo(ScrimState.AOD);
Lucas Dupinee4c9b72019-02-18 17:04:58 -0800450 verify(mWakeLock).acquire(anyString());
451 verify(mWakeLock, never()).release(anyString());
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800452 mScrimController.finishAnimationsImmediately();
Lucas Dupinee4c9b72019-02-18 17:04:58 -0800453 verify(mWakeLock).release(anyString());
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800454 }
455
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800456 @Test
Lucas Dupineea53b32017-12-18 13:47:14 -0800457 public void testDoesNotHoldWakeLock_whenUnlocking() {
458 mScrimController.transitionTo(ScrimState.UNLOCKED);
459 mScrimController.finishAnimationsImmediately();
460 verifyZeroInteractions(mWakeLock);
461 }
462
463 @Test
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800464 public void testCallbackInvokedOnSameStateTransition() {
465 mScrimController.transitionTo(ScrimState.UNLOCKED);
466 mScrimController.finishAnimationsImmediately();
467 ScrimController.Callback callback = mock(ScrimController.Callback.class);
468 mScrimController.transitionTo(ScrimState.UNLOCKED, callback);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800469 verify(callback).onFinished();
470 }
471
472 @Test
473 public void testHoldsAodWallpaperAnimationLock() {
474 // Pre-conditions
475 mScrimController.transitionTo(ScrimState.AOD);
476 mScrimController.finishAnimationsImmediately();
477 reset(mWakeLock);
478
479 mScrimController.onHideWallpaperTimeout();
Lucas Dupinee4c9b72019-02-18 17:04:58 -0800480 verify(mWakeLock).acquire(anyString());
481 verify(mWakeLock, never()).release(anyString());
Lucas Dupin82aa1632017-12-13 00:13:57 -0800482 mScrimController.finishAnimationsImmediately();
Lucas Dupinee4c9b72019-02-18 17:04:58 -0800483 verify(mWakeLock).release(anyString());
Lucas Dupin82aa1632017-12-13 00:13:57 -0800484 }
485
486 @Test
TYM Tsaia71c8922019-01-07 15:57:53 +0800487 public void testHoldsPulsingWallpaperAnimationLock() {
488 // Pre-conditions
Lucas Dupin00be88f2019-01-03 17:50:52 -0800489 mScrimController.setPulseReason(DozeLog.PULSE_REASON_NOTIFICATION);
490 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
Lucas Dupin00be88f2019-01-03 17:50:52 -0800511 public void testWillHidePulsingWallpaper_whenNotification() {
512 mScrimController.setWallpaperSupportsAmbientMode(false);
513 mScrimController.transitionTo(ScrimState.AOD);
514 mScrimController.finishAnimationsImmediately();
515 mScrimController.setPulseReason(DozeLog.PULSE_REASON_NOTIFICATION);
TYM Tsaia71c8922019-01-07 15:57:53 +0800516 mScrimController.transitionTo(ScrimState.PULSING);
Lucas Dupin00be88f2019-01-03 17:50:52 -0800517 mScrimController.finishAnimationsImmediately();
518 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
519 assertScrimTint(mScrimBehind, true);
520 }
521
522 @Test
523 public void testWillHidePulsingWallpaper_whenDocking() {
524 mScrimController.setWallpaperSupportsAmbientMode(false);
525 mScrimController.transitionTo(ScrimState.AOD);
526 mScrimController.finishAnimationsImmediately();
527 mScrimController.setPulseReason(DozeLog.PULSE_REASON_DOCKING);
528 mScrimController.transitionTo(ScrimState.PULSING);
529 mScrimController.finishAnimationsImmediately();
530 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
531 assertScrimTint(mScrimBehind, true);
TYM Tsaia71c8922019-01-07 15:57:53 +0800532 }
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 Dupin3daf3b02018-02-27 17:23:41 -0800563 @Test
Lucas Dupin38962d72018-03-14 12:41:39 -0700564 public void testScrimFocus() {
565 mScrimController.transitionTo(ScrimState.AOD);
566 Assert.assertFalse("Should not be focusable on AOD", mScrimBehind.isFocusable());
567 Assert.assertFalse("Should not be focusable on AOD", mScrimInFront.isFocusable());
568
569 mScrimController.transitionTo(ScrimState.KEYGUARD);
570 Assert.assertTrue("Should be focusable on keyguard", mScrimBehind.isFocusable());
571 Assert.assertTrue("Should be focusable on keyguard", mScrimInFront.isFocusable());
572 }
573
Lucas Dupind5107302018-03-19 15:30:29 -0700574 @Test
575 public void testHidesShowWhenLockedActivity() {
576 mScrimController.setWallpaperSupportsAmbientMode(true);
577 mScrimController.setKeyguardOccluded(true);
578 mScrimController.transitionTo(ScrimState.AOD);
579 mScrimController.finishAnimationsImmediately();
580 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
581
582 mScrimController.transitionTo(ScrimState.PULSING);
583 mScrimController.finishAnimationsImmediately();
584 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
585 }
586
Lucas Dupin78949b82018-04-03 18:54:39 -0700587 @Test
Lucas Dupin63d72172018-06-06 11:42:55 -0700588 public void testHidesShowWhenLockedActivity_whenAlreadyInAod() {
589 mScrimController.setWallpaperSupportsAmbientMode(true);
590 mScrimController.transitionTo(ScrimState.AOD);
591 mScrimController.finishAnimationsImmediately();
592 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
593
594 mScrimController.setKeyguardOccluded(true);
595 mScrimController.finishAnimationsImmediately();
596 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
597 }
598
599 @Test
Lucas Dupin78949b82018-04-03 18:54:39 -0700600 public void testEatsTouchEvent() {
601 HashSet<ScrimState> eatsTouches =
Lucas Dupin1c327432019-01-03 13:37:53 -0800602 new HashSet<>(Collections.singletonList(ScrimState.AOD));
Lucas Dupin78949b82018-04-03 18:54:39 -0700603 for (ScrimState state : ScrimState.values()) {
604 if (state == ScrimState.UNINITIALIZED) {
605 continue;
606 }
607 mScrimController.transitionTo(state);
608 mScrimController.finishAnimationsImmediately();
609 Assert.assertEquals("Should be clickable unless AOD or PULSING, was: " + state,
610 mScrimBehind.getViewAlpha() != 0 && !eatsTouches.contains(state),
611 mScrimBehind.isClickable());
612 }
613 }
614
Lucas Dupinea0116e2018-04-05 10:09:29 -0700615 @Test
616 public void testAnimatesTransitionToAod() {
617 when(mDozeParamenters.shouldControlScreenOff()).thenReturn(false);
618 ScrimState.AOD.prepare(ScrimState.KEYGUARD);
619 Assert.assertFalse("No animation when ColorFade kicks in",
620 ScrimState.AOD.getAnimateChange());
621
622 reset(mDozeParamenters);
623 when(mDozeParamenters.shouldControlScreenOff()).thenReturn(true);
624 ScrimState.AOD.prepare(ScrimState.KEYGUARD);
625 Assert.assertTrue("Animate scrims when ColorFade won't be triggered",
626 ScrimState.AOD.getAnimateChange());
627 }
628
Lucas Dupin373356b2018-04-07 10:50:25 -0700629 @Test
630 public void testViewsDontHaveFocusHighlight() {
631 Assert.assertFalse("Scrim shouldn't have focus highlight",
632 mScrimInFront.getDefaultFocusHighlightEnabled());
633 Assert.assertFalse("Scrim shouldn't have focus highlight",
634 mScrimBehind.getDefaultFocusHighlightEnabled());
635 }
636
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800637 private void assertScrimTint(ScrimView scrimView, boolean tinted) {
638 final boolean viewIsTinted = scrimView.getTint() != Color.TRANSPARENT;
639 final String name = scrimView == mScrimInFront ? "front" : "back";
640 Assert.assertEquals("Tint test failed at state " + mScrimController.getState()
641 +" with scrim: " + name + " and tint: " + Integer.toHexString(scrimView.getTint()),
642 tinted, viewIsTinted);
643 }
644
Lucas Dupin82aa1632017-12-13 00:13:57 -0800645 private void assertScrimVisibility(int inFront, int behind) {
646 boolean inFrontVisible = inFront != ScrimController.VISIBILITY_FULLY_TRANSPARENT;
647 boolean behindVisible = behind != ScrimController.VISIBILITY_FULLY_TRANSPARENT;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800648 Assert.assertEquals("Unexpected front scrim visibility. Alpha is "
Lucas Dupin82aa1632017-12-13 00:13:57 -0800649 + mScrimInFront.getViewAlpha(), inFrontVisible, mScrimInFront.getViewAlpha() > 0);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800650 Assert.assertEquals("Unexpected back scrim visibility. Alpha is "
Lucas Dupin82aa1632017-12-13 00:13:57 -0800651 + mScrimBehind.getViewAlpha(), behindVisible, mScrimBehind.getViewAlpha() > 0);
652
653 final int visibility;
654 if (inFront == VISIBILITY_FULLY_OPAQUE || behind == VISIBILITY_FULLY_OPAQUE) {
655 visibility = VISIBILITY_FULLY_OPAQUE;
656 } else if (inFront > VISIBILITY_FULLY_TRANSPARENT || behind > VISIBILITY_FULLY_TRANSPARENT) {
657 visibility = VISIBILITY_SEMI_TRANSPARENT;
658 } else {
659 visibility = VISIBILITY_FULLY_TRANSPARENT;
660 }
661 Assert.assertEquals("Invalid visibility.", visibility, mScrimVisibility);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800662 }
663
664 /**
665 * Special version of ScrimController where animations have 0 duration for test purposes.
666 */
667 private class SynchronousScrimController extends ScrimController {
668
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800669 private boolean mAnimationCancelled;
Lucas Dupin16cfe452018-02-08 13:14:50 -0800670 boolean mOnPreDrawCalled;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800671
shawnlin317db372018-04-09 19:49:48 +0800672 SynchronousScrimController(ScrimView scrimBehind, ScrimView scrimInFront,
Yohei Yukawa795f0102018-04-13 14:55:30 -0700673 TriConsumer<ScrimState, Float, GradientColors> scrimStateListener,
Lucas Dupin82aa1632017-12-13 00:13:57 -0800674 Consumer<Integer> scrimVisibleListener, DozeParameters dozeParameters,
675 AlarmManager alarmManager) {
Yohei Yukawa795f0102018-04-13 14:55:30 -0700676 super(scrimBehind, scrimInFront, scrimStateListener, scrimVisibleListener,
677 dozeParameters, alarmManager);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800678 }
679
Lucas Dupin16cfe452018-02-08 13:14:50 -0800680 @Override
681 public boolean onPreDraw() {
682 mOnPreDrawCalled = true;
683 return super.onPreDraw();
684 }
685
Lucas Dupin3503c5f2018-03-02 19:04:00 -0800686 void finishAnimationsImmediately() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800687 boolean[] animationFinished = {false};
688 setOnAnimationFinished(()-> animationFinished[0] = true);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800689 // Execute code that will trigger animations.
690 onPreDraw();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800691 // Force finish all animations.
Lucas Dupin54fbfb32019-03-05 18:08:13 -0800692 mLooper.processAllMessages();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800693 endAnimation(mScrimBehind, TAG_KEY_ANIM);
694 endAnimation(mScrimInFront, TAG_KEY_ANIM);
695
696 if (!animationFinished[0]) {
697 throw new IllegalStateException("Animation never finished");
698 }
699 }
700
Lucas Dupin3503c5f2018-03-02 19:04:00 -0800701 boolean wasAnimationJustCancelled() {
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800702 final boolean wasCancelled = mAnimationCancelled;
703 mAnimationCancelled = false;
704 return wasCancelled;
705 }
706
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800707 private void endAnimation(View scrimView, int tag) {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800708 Animator animator = (Animator) scrimView.getTag(tag);
709 if (animator != null) {
710 animator.end();
711 }
712 }
713
714 @Override
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800715 protected void cancelAnimator(ValueAnimator previousAnimator) {
716 super.cancelAnimator(previousAnimator);
717 mAnimationCancelled = true;
718 }
719
720 @Override
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800721 protected Handler getHandler() {
Lucas Dupin54fbfb32019-03-05 18:08:13 -0800722 return new FakeHandler(mLooper.getLooper());
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800723 }
724
725 @Override
726 protected WakeLock createWakeLock() {
727 return mWakeLock;
728 }
Lucas Dupin8c7cb022018-02-05 10:49:03 -0800729
730 /**
731 * Do not wait for a frame since we're in a test environment.
732 * @param callback What to execute.
733 */
734 @Override
Lucas Dupin0791d972018-03-26 13:32:16 -0700735 protected void doOnTheNextFrame(Runnable callback) {
736 callback.run();
Lucas Dupin8c7cb022018-02-05 10:49:03 -0800737 }
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800738 }
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800739}