blob: 97ad47ec3f0ce50eba55e933d9079c12692d0bb7 [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;
Selim Cinek72cd9a72019-08-09 17:19:57 -070050import com.android.systemui.statusbar.policy.KeyguardMonitor;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080051import 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 },
Selim Cinek72cd9a72019-08-09 17:19:57 -0700100 visible -> mScrimVisibility = visible, mDozeParamenters, mAlarmManager,
101 mock(KeyguardMonitor.class));
Lucas Dupinf8463ee2018-06-11 16:18:15 -0700102 mScrimController.setHasBackdrop(false);
TYM Tsaia71c8922019-01-07 15:57:53 +0800103 mScrimController.setWallpaperSupportsAmbientMode(false);
Lucas Dupin4dbe5182019-03-07 18:20:11 -0800104 mScrimController.transitionTo(ScrimState.KEYGUARD);
105 mScrimController.finishAnimationsImmediately();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800106 }
107
Lucas Dupin4dbe5182019-03-07 18:20:11 -0800108 @After
109 public void tearDown() {
110 mScrimController.finishAnimationsImmediately();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800111 }
112
113 @Test
114 public void transitionToKeyguard() {
115 mScrimController.transitionTo(ScrimState.KEYGUARD);
116 mScrimController.finishAnimationsImmediately();
117 // Front scrim should be transparent
118 // Back scrim should be visible without tint
Lucas Dupin82aa1632017-12-13 00:13:57 -0800119 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
Lucas Dupin1113fdf2019-03-07 17:32:00 -0800120 assertScrimTint(mScrimBehind, true /* tinted */);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800121 }
122
123 @Test
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700124 public void transitionToAod_withRegularWallpaper() {
125 mScrimController.transitionTo(ScrimState.AOD);
126 mScrimController.finishAnimationsImmediately();
127 // Front scrim should be transparent
128 // Back scrim should be visible with tint
Lucas Dupin82aa1632017-12-13 00:13:57 -0800129 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700130 assertScrimTint(mScrimBehind, true /* tinted */);
131 assertScrimTint(mScrimInFront, true /* tinted */);
132 }
133
134 @Test
135 public void transitionToAod_withAodWallpaper() {
136 mScrimController.setWallpaperSupportsAmbientMode(true);
137 mScrimController.transitionTo(ScrimState.AOD);
138 mScrimController.finishAnimationsImmediately();
139 // Front scrim should be transparent
140 // Back scrim should be transparent
Lucas Dupin82aa1632017-12-13 00:13:57 -0800141 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
142
Lucas Dupin00be88f2019-01-03 17:50:52 -0800143 // Pulsing notification should conserve AOD wallpaper.
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 Dupin9e3fa102017-11-08 17:16:55 -0800228 mScrimController.transitionTo(ScrimState.PULSING);
229 mScrimController.finishAnimationsImmediately();
Lucas Dupina7eacf92019-07-24 12:40:34 -0700230 // Front scrim should be transparent, but tinted
Lucas Dupinde64ee02018-12-21 14:45:12 -0800231 // Back scrim should be semi-transparent so the user can see the wallpaper
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800232 // Pulse callback should have been invoked
Lucas Dupin5f00fa52019-03-27 22:46:53 -0700233 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
Lucas Dupin3113db62019-03-08 18:21:27 -0800234 assertScrimTint(mScrimBehind, true /* tinted */);
Lucas Dupina7eacf92019-07-24 12:40:34 -0700235 assertScrimTint(mScrimInFront, true /* tinted */);
Lucas Dupin5f00fa52019-03-27 22:46:53 -0700236
237 mScrimController.setWakeLockScreenSensorActive(true);
238 mScrimController.finishAnimationsImmediately();
239 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800240 }
241
242 @Test
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800243 public void transitionToKeyguardBouncer() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800244 mScrimController.transitionTo(ScrimState.BOUNCER);
245 mScrimController.finishAnimationsImmediately();
246 // Front scrim should be transparent
247 // Back scrim should be visible without tint
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800248 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
249 assertScrimTint(mScrimBehind, false /* tinted */);
250 }
251
252 @Test
253 public void transitionToBouncer() {
Lucas Dupin05726cd2018-03-13 14:00:24 -0700254 mScrimController.transitionTo(ScrimState.BOUNCER_SCRIMMED);
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800255 mScrimController.finishAnimationsImmediately();
256 // Front scrim should be transparent
257 // Back scrim should be visible without tint
258 assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800259 assertScrimTint(mScrimBehind, false /* tinted */);
260 }
261
262 @Test
263 public void transitionToUnlocked() {
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800264 mScrimController.setPanelExpansion(0f);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800265 mScrimController.transitionTo(ScrimState.UNLOCKED);
266 mScrimController.finishAnimationsImmediately();
267 // Front scrim should be transparent
268 // Back scrim should be transparent
Lucas Dupin82aa1632017-12-13 00:13:57 -0800269 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800270 assertScrimTint(mScrimBehind, false /* tinted */);
271 assertScrimTint(mScrimInFront, false /* tinted */);
272
273 // Back scrim should be visible after start dragging
274 mScrimController.setPanelExpansion(0.5f);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800275 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800276 }
277
278 @Test
Mady Mellor0c333772018-11-06 18:05:54 -0800279 public void transitionToBubbleExpanded() {
280 mScrimController.transitionTo(ScrimState.BUBBLE_EXPANDED);
281 mScrimController.finishAnimationsImmediately();
282
283 // Front scrim should be transparent
284 Assert.assertEquals(ScrimController.VISIBILITY_FULLY_TRANSPARENT,
285 mScrimInFront.getViewAlpha(), 0.0f);
286 // Back scrim should be visible
287 Assert.assertEquals(ScrimController.GRADIENT_SCRIM_ALPHA_BUSY,
288 mScrimBehind.getViewAlpha(), 0.0f);
289 }
290
291 @Test
Yohei Yukawa795f0102018-04-13 14:55:30 -0700292 public void scrimStateCallback() {
293 mScrimController.transitionTo(ScrimState.UNLOCKED);
294 mScrimController.finishAnimationsImmediately();
295 Assert.assertEquals(mScrimState, ScrimState.UNLOCKED);
296
297 mScrimController.transitionTo(ScrimState.BOUNCER);
298 mScrimController.finishAnimationsImmediately();
299 Assert.assertEquals(mScrimState, ScrimState.BOUNCER);
300
301 mScrimController.transitionTo(ScrimState.BOUNCER_SCRIMMED);
302 mScrimController.finishAnimationsImmediately();
303 Assert.assertEquals(mScrimState, ScrimState.BOUNCER_SCRIMMED);
304 }
305
306 @Test
shawnlin317db372018-04-09 19:49:48 +0800307 public void panelExpansion() {
308 mScrimController.setPanelExpansion(0f);
309 mScrimController.setPanelExpansion(0.5f);
310 mScrimController.transitionTo(ScrimState.UNLOCKED);
311 mScrimController.finishAnimationsImmediately();
312
313 reset(mScrimBehind);
314 mScrimController.setPanelExpansion(0f);
315 mScrimController.setPanelExpansion(1.0f);
Lucas Dupin4dbe5182019-03-07 18:20:11 -0800316 mScrimController.finishAnimationsImmediately();
shawnlin317db372018-04-09 19:49:48 +0800317
318 Assert.assertEquals("Scrim alpha should change after setPanelExpansion",
319 mScrimBehindAlpha, mScrimBehind.getViewAlpha(), 0.01f);
320
321 mScrimController.setPanelExpansion(0f);
Lucas Dupin4dbe5182019-03-07 18:20:11 -0800322 mScrimController.finishAnimationsImmediately();
shawnlin317db372018-04-09 19:49:48 +0800323
324 Assert.assertEquals("Scrim alpha should change after setPanelExpansion",
325 mScrimBehindAlpha, mScrimBehind.getViewAlpha(), 0.01f);
326 }
327
328 @Test
Lucas Dupin67f02632018-03-12 11:08:31 -0700329 public void panelExpansionAffectsAlpha() {
330 mScrimController.setPanelExpansion(0f);
331 mScrimController.setPanelExpansion(0.5f);
332 mScrimController.transitionTo(ScrimState.UNLOCKED);
333 mScrimController.finishAnimationsImmediately();
334
335 final float scrimAlpha = mScrimBehind.getViewAlpha();
Lucas Dupin067136c2018-03-27 18:03:25 -0700336 reset(mScrimBehind);
Lucas Dupin67f02632018-03-12 11:08:31 -0700337 mScrimController.setExpansionAffectsAlpha(false);
338 mScrimController.setPanelExpansion(0.8f);
Lucas Dupin067136c2018-03-27 18:03:25 -0700339 verifyZeroInteractions(mScrimBehind);
Lucas Dupin67f02632018-03-12 11:08:31 -0700340 Assert.assertEquals("Scrim opacity shouldn't change when setExpansionAffectsAlpha "
341 + "is false", scrimAlpha, mScrimBehind.getViewAlpha(), 0.01f);
342
343 mScrimController.setExpansionAffectsAlpha(true);
344 mScrimController.setPanelExpansion(0.1f);
Lucas Dupin4dbe5182019-03-07 18:20:11 -0800345 mScrimController.finishAnimationsImmediately();
Lucas Dupin67f02632018-03-12 11:08:31 -0700346 Assert.assertNotEquals("Scrim opacity should change when setExpansionAffectsAlpha "
347 + "is true", scrimAlpha, mScrimBehind.getViewAlpha(), 0.01f);
348 }
349
350 @Test
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800351 public void transitionToUnlockedFromAod() {
352 // Simulate unlock with fingerprint
353 mScrimController.transitionTo(ScrimState.AOD);
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800354 mScrimController.setPanelExpansion(0f);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800355 mScrimController.finishAnimationsImmediately();
356 mScrimController.transitionTo(ScrimState.UNLOCKED);
357 // Immediately tinted after the transition starts
358 assertScrimTint(mScrimInFront, true /* tinted */);
359 assertScrimTint(mScrimBehind, true /* tinted */);
360 mScrimController.finishAnimationsImmediately();
361 // Front scrim should be transparent
362 // Back scrim should be transparent
363 // Neither scrims should be tinted anymore after the animation.
Lucas Dupin82aa1632017-12-13 00:13:57 -0800364 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800365 assertScrimTint(mScrimInFront, false /* tinted */);
366 assertScrimTint(mScrimBehind, false /* tinted */);
367 }
368
369 @Test
Lucas Dupinea0116e2018-04-05 10:09:29 -0700370 public void scrimBlanksBeforeLeavingAod() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800371 // Simulate unlock with fingerprint
372 mScrimController.transitionTo(ScrimState.AOD);
373 mScrimController.finishAnimationsImmediately();
374 mScrimController.transitionTo(ScrimState.UNLOCKED,
375 new ScrimController.Callback() {
376 @Override
377 public void onDisplayBlanked() {
378 // Front scrim should be black in the middle of the transition
379 Assert.assertTrue("Scrim should be visible during transition. Alpha: "
380 + mScrimInFront.getViewAlpha(), mScrimInFront.getViewAlpha() > 0);
381 assertScrimTint(mScrimInFront, true /* tinted */);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800382 Assert.assertSame("Scrim should be visible during transition.",
383 mScrimVisibility, VISIBILITY_FULLY_OPAQUE);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800384 }
385 });
386 mScrimController.finishAnimationsImmediately();
387 }
388
389 @Test
Lucas Dupineb840ea2018-06-01 00:28:58 -0700390 public void scrimBlanksWhenUnlockingFromPulse() {
391 boolean[] blanked = {false};
392 // Simulate unlock with fingerprint
393 mScrimController.transitionTo(ScrimState.PULSING);
394 mScrimController.finishAnimationsImmediately();
395 mScrimController.transitionTo(ScrimState.UNLOCKED,
396 new ScrimController.Callback() {
397 @Override
398 public void onDisplayBlanked() {
399 blanked[0] = true;
400 }
401 });
402 mScrimController.finishAnimationsImmediately();
403 Assert.assertTrue("Scrim should blank when unlocking from pulse.", blanked[0]);
404 }
405
406 @Test
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800407 public void testScrimCallback() {
408 int[] callOrder = {0, 0, 0};
409 int[] currentCall = {0};
410 mScrimController.transitionTo(ScrimState.AOD, new ScrimController.Callback() {
411 @Override
412 public void onStart() {
413 callOrder[0] = ++currentCall[0];
414 }
415
416 @Override
417 public void onDisplayBlanked() {
418 callOrder[1] = ++currentCall[0];
419 }
420
421 @Override
422 public void onFinished() {
423 callOrder[2] = ++currentCall[0];
424 }
425 });
426 mScrimController.finishAnimationsImmediately();
427 Assert.assertEquals("onStart called in wrong order", 1, callOrder[0]);
428 Assert.assertEquals("onDisplayBlanked called in wrong order", 2, callOrder[1]);
429 Assert.assertEquals("onFinished called in wrong order", 3, callOrder[2]);
430 }
431
432 @Test
433 public void testScrimCallbacksWithoutAmbientDisplay() {
434 mAlwaysOnEnabled = false;
435 testScrimCallback();
436 }
437
438 @Test
439 public void testScrimCallbackCancelled() {
440 boolean[] cancelledCalled = {false};
441 mScrimController.transitionTo(ScrimState.AOD, new ScrimController.Callback() {
442 @Override
443 public void onCancelled() {
444 cancelledCalled[0] = true;
445 }
446 });
447 mScrimController.transitionTo(ScrimState.PULSING);
448 Assert.assertTrue("onCancelled should have been called", cancelledCalled[0]);
449 }
450
451 @Test
Lucas Dupineea53b32017-12-18 13:47:14 -0800452 public void testHoldsWakeLock_whenAOD() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800453 mScrimController.transitionTo(ScrimState.AOD);
Lucas Dupinee4c9b72019-02-18 17:04:58 -0800454 verify(mWakeLock).acquire(anyString());
455 verify(mWakeLock, never()).release(anyString());
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800456 mScrimController.finishAnimationsImmediately();
Lucas Dupinee4c9b72019-02-18 17:04:58 -0800457 verify(mWakeLock).release(anyString());
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800458 }
459
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800460 @Test
Lucas Dupineea53b32017-12-18 13:47:14 -0800461 public void testDoesNotHoldWakeLock_whenUnlocking() {
462 mScrimController.transitionTo(ScrimState.UNLOCKED);
463 mScrimController.finishAnimationsImmediately();
464 verifyZeroInteractions(mWakeLock);
465 }
466
467 @Test
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800468 public void testCallbackInvokedOnSameStateTransition() {
469 mScrimController.transitionTo(ScrimState.UNLOCKED);
470 mScrimController.finishAnimationsImmediately();
471 ScrimController.Callback callback = mock(ScrimController.Callback.class);
472 mScrimController.transitionTo(ScrimState.UNLOCKED, callback);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800473 verify(callback).onFinished();
474 }
475
476 @Test
477 public void testHoldsAodWallpaperAnimationLock() {
478 // Pre-conditions
479 mScrimController.transitionTo(ScrimState.AOD);
480 mScrimController.finishAnimationsImmediately();
481 reset(mWakeLock);
482
483 mScrimController.onHideWallpaperTimeout();
Lucas Dupinee4c9b72019-02-18 17:04:58 -0800484 verify(mWakeLock).acquire(anyString());
485 verify(mWakeLock, never()).release(anyString());
Lucas Dupin82aa1632017-12-13 00:13:57 -0800486 mScrimController.finishAnimationsImmediately();
Lucas Dupinee4c9b72019-02-18 17:04:58 -0800487 verify(mWakeLock).release(anyString());
Lucas Dupin82aa1632017-12-13 00:13:57 -0800488 }
489
490 @Test
TYM Tsaia71c8922019-01-07 15:57:53 +0800491 public void testHoldsPulsingWallpaperAnimationLock() {
492 // Pre-conditions
Lucas Dupin00be88f2019-01-03 17:50:52 -0800493 mScrimController.transitionTo(ScrimState.PULSING);
TYM Tsaia71c8922019-01-07 15:57:53 +0800494 mScrimController.finishAnimationsImmediately();
495 reset(mWakeLock);
496
497 mScrimController.onHideWallpaperTimeout();
Lucas Dupinee4c9b72019-02-18 17:04:58 -0800498 verify(mWakeLock).acquire(anyString());
499 verify(mWakeLock, never()).release(anyString());
TYM Tsaia71c8922019-01-07 15:57:53 +0800500 mScrimController.finishAnimationsImmediately();
Lucas Dupinee4c9b72019-02-18 17:04:58 -0800501 verify(mWakeLock).release(anyString());
TYM Tsaia71c8922019-01-07 15:57:53 +0800502 }
503
504 @Test
Lucas Dupin16cfe452018-02-08 13:14:50 -0800505 public void testWillHideAodWallpaper() {
Lucas Dupin82aa1632017-12-13 00:13:57 -0800506 mScrimController.setWallpaperSupportsAmbientMode(true);
507 mScrimController.transitionTo(ScrimState.AOD);
508 verify(mAlarmManager).setExact(anyInt(), anyLong(), any(), any(), any());
509 mScrimController.transitionTo(ScrimState.KEYGUARD);
510 verify(mAlarmManager).cancel(any(AlarmManager.OnAlarmListener.class));
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800511 }
512
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800513 @Test
Jerry Changbde4c0c2019-06-13 16:58:41 +0800514 public void transitionToPulsing_withTimeoutWallpaperCallback_willHideWallpaper() {
515 mScrimController.setWallpaperSupportsAmbientMode(true);
516
517 mScrimController.transitionTo(ScrimState.PULSING, new ScrimController.Callback() {
518 @Override
519 public boolean shouldTimeoutWallpaper() {
520 return true;
521 }
522 });
523
524 verify(mAlarmManager).setExact(anyInt(), anyLong(), any(), any(), any());
525 }
526
527 @Test
528 public void transitionToPulsing_withDefaultCallback_wontHideWallpaper() {
529 mScrimController.setWallpaperSupportsAmbientMode(true);
530
531 mScrimController.transitionTo(ScrimState.PULSING, new ScrimController.Callback() {});
532
533 verify(mAlarmManager, never()).setExact(anyInt(), anyLong(), any(), any(), any());
534 }
535
536 @Test
537 public void transitionToPulsing_withoutCallback_wontHideWallpaper() {
538 mScrimController.setWallpaperSupportsAmbientMode(true);
539
540 mScrimController.transitionTo(ScrimState.PULSING);
541
542 verify(mAlarmManager, never()).setExact(anyInt(), anyLong(), any(), any(), any());
543 }
544
545 @Test
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800546 public void testConservesExpansionOpacityAfterTransition() {
547 mScrimController.transitionTo(ScrimState.UNLOCKED);
548 mScrimController.setPanelExpansion(0.5f);
549 mScrimController.finishAnimationsImmediately();
550
551 final float expandedAlpha = mScrimBehind.getViewAlpha();
552
553 mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR);
554 mScrimController.finishAnimationsImmediately();
555 mScrimController.transitionTo(ScrimState.UNLOCKED);
556 mScrimController.finishAnimationsImmediately();
557
558 Assert.assertEquals("Scrim expansion opacity wasn't conserved when transitioning back",
559 expandedAlpha, mScrimBehind.getViewAlpha(), 0.01f);
560 }
561
562 @Test
563 public void cancelsOldAnimationBeforeBlanking() {
564 mScrimController.transitionTo(ScrimState.AOD);
565 mScrimController.finishAnimationsImmediately();
566 // Consume whatever value we had before
567 mScrimController.wasAnimationJustCancelled();
568
569 mScrimController.transitionTo(ScrimState.KEYGUARD);
570 mScrimController.finishAnimationsImmediately();
571 Assert.assertTrue(mScrimController.wasAnimationJustCancelled());
572 }
573
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800574 @Test
Lucas Dupin38962d72018-03-14 12:41:39 -0700575 public void testScrimFocus() {
576 mScrimController.transitionTo(ScrimState.AOD);
577 Assert.assertFalse("Should not be focusable on AOD", mScrimBehind.isFocusable());
578 Assert.assertFalse("Should not be focusable on AOD", mScrimInFront.isFocusable());
579
580 mScrimController.transitionTo(ScrimState.KEYGUARD);
581 Assert.assertTrue("Should be focusable on keyguard", mScrimBehind.isFocusable());
582 Assert.assertTrue("Should be focusable on keyguard", mScrimInFront.isFocusable());
583 }
584
Lucas Dupind5107302018-03-19 15:30:29 -0700585 @Test
586 public void testHidesShowWhenLockedActivity() {
587 mScrimController.setWallpaperSupportsAmbientMode(true);
588 mScrimController.setKeyguardOccluded(true);
589 mScrimController.transitionTo(ScrimState.AOD);
590 mScrimController.finishAnimationsImmediately();
591 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
592
593 mScrimController.transitionTo(ScrimState.PULSING);
594 mScrimController.finishAnimationsImmediately();
595 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
596 }
597
Lucas Dupin78949b82018-04-03 18:54:39 -0700598 @Test
Lucas Dupin63d72172018-06-06 11:42:55 -0700599 public void testHidesShowWhenLockedActivity_whenAlreadyInAod() {
600 mScrimController.setWallpaperSupportsAmbientMode(true);
601 mScrimController.transitionTo(ScrimState.AOD);
602 mScrimController.finishAnimationsImmediately();
603 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
604
605 mScrimController.setKeyguardOccluded(true);
606 mScrimController.finishAnimationsImmediately();
607 assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
608 }
609
610 @Test
Lucas Dupin78949b82018-04-03 18:54:39 -0700611 public void testEatsTouchEvent() {
612 HashSet<ScrimState> eatsTouches =
Lucas Dupin1c327432019-01-03 13:37:53 -0800613 new HashSet<>(Collections.singletonList(ScrimState.AOD));
Lucas Dupin78949b82018-04-03 18:54:39 -0700614 for (ScrimState state : ScrimState.values()) {
615 if (state == ScrimState.UNINITIALIZED) {
616 continue;
617 }
618 mScrimController.transitionTo(state);
619 mScrimController.finishAnimationsImmediately();
620 Assert.assertEquals("Should be clickable unless AOD or PULSING, was: " + state,
621 mScrimBehind.getViewAlpha() != 0 && !eatsTouches.contains(state),
622 mScrimBehind.isClickable());
623 }
624 }
625
Lucas Dupinea0116e2018-04-05 10:09:29 -0700626 @Test
627 public void testAnimatesTransitionToAod() {
628 when(mDozeParamenters.shouldControlScreenOff()).thenReturn(false);
629 ScrimState.AOD.prepare(ScrimState.KEYGUARD);
630 Assert.assertFalse("No animation when ColorFade kicks in",
631 ScrimState.AOD.getAnimateChange());
632
633 reset(mDozeParamenters);
634 when(mDozeParamenters.shouldControlScreenOff()).thenReturn(true);
635 ScrimState.AOD.prepare(ScrimState.KEYGUARD);
636 Assert.assertTrue("Animate scrims when ColorFade won't be triggered",
637 ScrimState.AOD.getAnimateChange());
638 }
639
Lucas Dupin373356b2018-04-07 10:50:25 -0700640 @Test
641 public void testViewsDontHaveFocusHighlight() {
642 Assert.assertFalse("Scrim shouldn't have focus highlight",
643 mScrimInFront.getDefaultFocusHighlightEnabled());
644 Assert.assertFalse("Scrim shouldn't have focus highlight",
645 mScrimBehind.getDefaultFocusHighlightEnabled());
646 }
647
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800648 private void assertScrimTint(ScrimView scrimView, boolean tinted) {
649 final boolean viewIsTinted = scrimView.getTint() != Color.TRANSPARENT;
650 final String name = scrimView == mScrimInFront ? "front" : "back";
651 Assert.assertEquals("Tint test failed at state " + mScrimController.getState()
652 +" with scrim: " + name + " and tint: " + Integer.toHexString(scrimView.getTint()),
653 tinted, viewIsTinted);
654 }
655
Lucas Dupin82aa1632017-12-13 00:13:57 -0800656 private void assertScrimVisibility(int inFront, int behind) {
657 boolean inFrontVisible = inFront != ScrimController.VISIBILITY_FULLY_TRANSPARENT;
658 boolean behindVisible = behind != ScrimController.VISIBILITY_FULLY_TRANSPARENT;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800659 Assert.assertEquals("Unexpected front scrim visibility. Alpha is "
Lucas Dupin82aa1632017-12-13 00:13:57 -0800660 + mScrimInFront.getViewAlpha(), inFrontVisible, mScrimInFront.getViewAlpha() > 0);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800661 Assert.assertEquals("Unexpected back scrim visibility. Alpha is "
Lucas Dupin82aa1632017-12-13 00:13:57 -0800662 + mScrimBehind.getViewAlpha(), behindVisible, mScrimBehind.getViewAlpha() > 0);
663
664 final int visibility;
665 if (inFront == VISIBILITY_FULLY_OPAQUE || behind == VISIBILITY_FULLY_OPAQUE) {
666 visibility = VISIBILITY_FULLY_OPAQUE;
667 } else if (inFront > VISIBILITY_FULLY_TRANSPARENT || behind > VISIBILITY_FULLY_TRANSPARENT) {
668 visibility = VISIBILITY_SEMI_TRANSPARENT;
669 } else {
670 visibility = VISIBILITY_FULLY_TRANSPARENT;
671 }
672 Assert.assertEquals("Invalid visibility.", visibility, mScrimVisibility);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800673 }
674
675 /**
676 * Special version of ScrimController where animations have 0 duration for test purposes.
677 */
678 private class SynchronousScrimController extends ScrimController {
679
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800680 private boolean mAnimationCancelled;
Lucas Dupin16cfe452018-02-08 13:14:50 -0800681 boolean mOnPreDrawCalled;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800682
shawnlin317db372018-04-09 19:49:48 +0800683 SynchronousScrimController(ScrimView scrimBehind, ScrimView scrimInFront,
Yohei Yukawa795f0102018-04-13 14:55:30 -0700684 TriConsumer<ScrimState, Float, GradientColors> scrimStateListener,
Lucas Dupin82aa1632017-12-13 00:13:57 -0800685 Consumer<Integer> scrimVisibleListener, DozeParameters dozeParameters,
Selim Cinek72cd9a72019-08-09 17:19:57 -0700686 AlarmManager alarmManager, KeyguardMonitor keyguardMonitor) {
Yohei Yukawa795f0102018-04-13 14:55:30 -0700687 super(scrimBehind, scrimInFront, scrimStateListener, scrimVisibleListener,
Selim Cinek72cd9a72019-08-09 17:19:57 -0700688 dozeParameters, alarmManager, keyguardMonitor);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800689 }
690
Lucas Dupin16cfe452018-02-08 13:14:50 -0800691 @Override
692 public boolean onPreDraw() {
693 mOnPreDrawCalled = true;
694 return super.onPreDraw();
695 }
696
Lucas Dupin3503c5f2018-03-02 19:04:00 -0800697 void finishAnimationsImmediately() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800698 boolean[] animationFinished = {false};
699 setOnAnimationFinished(()-> animationFinished[0] = true);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800700 // Execute code that will trigger animations.
701 onPreDraw();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800702 // Force finish all animations.
Lucas Dupin54fbfb32019-03-05 18:08:13 -0800703 mLooper.processAllMessages();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800704 endAnimation(mScrimBehind, TAG_KEY_ANIM);
705 endAnimation(mScrimInFront, TAG_KEY_ANIM);
706
707 if (!animationFinished[0]) {
708 throw new IllegalStateException("Animation never finished");
709 }
710 }
711
Lucas Dupin3503c5f2018-03-02 19:04:00 -0800712 boolean wasAnimationJustCancelled() {
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800713 final boolean wasCancelled = mAnimationCancelled;
714 mAnimationCancelled = false;
715 return wasCancelled;
716 }
717
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800718 private void endAnimation(View scrimView, int tag) {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800719 Animator animator = (Animator) scrimView.getTag(tag);
720 if (animator != null) {
721 animator.end();
722 }
723 }
724
725 @Override
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800726 protected void cancelAnimator(ValueAnimator previousAnimator) {
727 super.cancelAnimator(previousAnimator);
728 mAnimationCancelled = true;
729 }
730
731 @Override
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800732 protected Handler getHandler() {
Lucas Dupin54fbfb32019-03-05 18:08:13 -0800733 return new FakeHandler(mLooper.getLooper());
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800734 }
735
736 @Override
737 protected WakeLock createWakeLock() {
738 return mWakeLock;
739 }
Lucas Dupin8c7cb022018-02-05 10:49:03 -0800740
741 /**
742 * Do not wait for a frame since we're in a test environment.
743 * @param callback What to execute.
744 */
745 @Override
Lucas Dupin0791d972018-03-26 13:32:16 -0700746 protected void doOnTheNextFrame(Runnable callback) {
747 callback.run();
Lucas Dupin8c7cb022018-02-05 10:49:03 -0800748 }
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800749 }
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800750}