blob: baaec458acce3b5e644bf79713e881a65f9d5315 [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
Lyn Hanbde48202019-05-29 19:18:29 -070019import static com.android.systemui.statusbar.phone.ScrimController.OPAQUE;
20import static com.android.systemui.statusbar.phone.ScrimController.SEMI_TRANSPARENT;
21import static com.android.systemui.statusbar.phone.ScrimController.TRANSPARENT;
Lucas Dupin82aa1632017-12-13 00:13:57 -080022
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;
Lyn Hanbde48202019-05-29 19:18:29 -070071 private ScrimView mScrimForBubble;
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());
Lyn Hanbde48202019-05-29 19:18:29 -070087 mScrimForBubble = new ScrimView(getContext());
Lucas Dupin9e3fa102017-11-08 17:16:55 -080088 mWakeLock = mock(WakeLock.class);
Lucas Dupin82aa1632017-12-13 00:13:57 -080089 mAlarmManager = mock(AlarmManager.class);
Lucas Dupin9e3fa102017-11-08 17:16:55 -080090 mAlwaysOnEnabled = true;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080091 mDozeParamenters = mock(DozeParameters.class);
Lucas Dupin54fbfb32019-03-05 18:08:13 -080092 mLooper = TestableLooper.get(this);
Lucas Dupin9e3fa102017-11-08 17:16:55 -080093 when(mDozeParamenters.getAlwaysOn()).thenAnswer(invocation -> mAlwaysOnEnabled);
Lucas Dupin43d0d732017-11-16 11:23:49 -080094 when(mDozeParamenters.getDisplayNeedsBlanking()).thenReturn(true);
shawnlin317db372018-04-09 19:49:48 +080095 mScrimController = new SynchronousScrimController(mScrimBehind, mScrimInFront,
Lyn Hanbde48202019-05-29 19:18:29 -070096 mScrimForBubble,
Yohei Yukawa795f0102018-04-13 14:55:30 -070097 (scrimState, scrimBehindAlpha, scrimInFrontColor) -> {
98 mScrimState = scrimState;
99 mScrimBehindAlpha = scrimBehindAlpha;
100 mScrimInFrontColor = scrimInFrontColor;
101 },
102 visible -> mScrimVisibility = visible, mDozeParamenters, mAlarmManager);
Lucas Dupinf8463ee2018-06-11 16:18:15 -0700103 mScrimController.setHasBackdrop(false);
TYM Tsaia71c8922019-01-07 15:57:53 +0800104 mScrimController.setWallpaperSupportsAmbientMode(false);
Lucas Dupin4dbe5182019-03-07 18:20:11 -0800105 mScrimController.transitionTo(ScrimState.KEYGUARD);
106 mScrimController.finishAnimationsImmediately();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800107 }
108
Lucas Dupin4dbe5182019-03-07 18:20:11 -0800109 @After
110 public void tearDown() {
111 mScrimController.finishAnimationsImmediately();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800112 }
113
114 @Test
115 public void transitionToKeyguard() {
116 mScrimController.transitionTo(ScrimState.KEYGUARD);
117 mScrimController.finishAnimationsImmediately();
Lyn Hanbde48202019-05-29 19:18:29 -0700118
119 assertScrimAlpha(TRANSPARENT /* front */,
120 SEMI_TRANSPARENT /* back */,
121 TRANSPARENT /* bubble */);
122
123 assertScrimTint(true /* front */,
124 true /* behind */,
125 false /* bubble */);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800126 }
127
128 @Test
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700129 public void transitionToAod_withRegularWallpaper() {
130 mScrimController.transitionTo(ScrimState.AOD);
131 mScrimController.finishAnimationsImmediately();
Lyn Hanbde48202019-05-29 19:18:29 -0700132
133 assertScrimAlpha(TRANSPARENT /* front */,
134 OPAQUE /* back */,
135 TRANSPARENT /* bubble */);
136
137 assertScrimTint(true /* front */,
138 true /* behind */,
139 false /* bubble */);
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700140 }
141
142 @Test
143 public void transitionToAod_withAodWallpaper() {
144 mScrimController.setWallpaperSupportsAmbientMode(true);
145 mScrimController.transitionTo(ScrimState.AOD);
146 mScrimController.finishAnimationsImmediately();
Lyn Hanbde48202019-05-29 19:18:29 -0700147
148 assertScrimAlpha(TRANSPARENT /* front */,
149 TRANSPARENT /* back */,
150 TRANSPARENT /* bubble */);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800151
Lucas Dupin00be88f2019-01-03 17:50:52 -0800152 // Pulsing notification should conserve AOD wallpaper.
Lucas Dupin82aa1632017-12-13 00:13:57 -0800153 mScrimController.transitionTo(ScrimState.PULSING);
154 mScrimController.finishAnimationsImmediately();
Lyn Hanbde48202019-05-29 19:18:29 -0700155
156 assertScrimAlpha(TRANSPARENT /* front */,
157 TRANSPARENT /* back */,
158 TRANSPARENT /* bubble */);
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700159 }
160
161 @Test
162 public void transitionToAod_withAodWallpaperAndLockScreenWallpaper() {
Lucas Dupinf8463ee2018-06-11 16:18:15 -0700163 mScrimController.setHasBackdrop(true);
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700164 mScrimController.setWallpaperSupportsAmbientMode(true);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800165 mScrimController.transitionTo(ScrimState.AOD);
166 mScrimController.finishAnimationsImmediately();
Lyn Hanbde48202019-05-29 19:18:29 -0700167
168 assertScrimAlpha(TRANSPARENT /* front */,
169 OPAQUE /* back */,
170 TRANSPARENT /* bubble */);
171
172 assertScrimTint(true /* front */,
173 true /* behind */,
174 false /* bubble */);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800175 }
176
177 @Test
Lucas Dupin9bee5822018-07-09 14:32:53 -0700178 public void setHasBackdrop_withAodWallpaperAndAlbumArt() {
179 mScrimController.setWallpaperSupportsAmbientMode(true);
180 mScrimController.transitionTo(ScrimState.AOD);
181 mScrimController.finishAnimationsImmediately();
182 mScrimController.setHasBackdrop(true);
183 mScrimController.finishAnimationsImmediately();
Lyn Hanbde48202019-05-29 19:18:29 -0700184
185 assertScrimAlpha(TRANSPARENT /* front */,
186 OPAQUE /* back */,
187 TRANSPARENT /* bubble */);
188
189 assertScrimTint(true /* front */,
190 true /* behind */,
191 false /* bubble */);
Lucas Dupin9bee5822018-07-09 14:32:53 -0700192 }
193
194 @Test
Michael Wrightcae88752018-04-16 23:13:54 +0100195 public void transitionToAod_withFrontAlphaUpdates() {
196 // Assert that setting the AOD front scrim alpha doesn't take effect in a non-AOD state.
197 mScrimController.transitionTo(ScrimState.KEYGUARD);
198 mScrimController.setAodFrontScrimAlpha(0.5f);
199 mScrimController.finishAnimationsImmediately();
Lyn Hanbde48202019-05-29 19:18:29 -0700200
201 assertScrimAlpha(TRANSPARENT /* front */,
202 SEMI_TRANSPARENT /* back */,
203 TRANSPARENT /* bubble */);
Michael Wrightcae88752018-04-16 23:13:54 +0100204
205 // ... but that it does take effect once we enter the AOD state.
206 mScrimController.transitionTo(ScrimState.AOD);
207 mScrimController.finishAnimationsImmediately();
Lyn Hanbde48202019-05-29 19:18:29 -0700208 assertScrimAlpha(SEMI_TRANSPARENT /* front */,
209 OPAQUE /* back */,
210 TRANSPARENT /* bubble */);
Michael Wrightcae88752018-04-16 23:13:54 +0100211
212 // ... and that if we set it while we're in AOD, it does take immediate effect.
213 mScrimController.setAodFrontScrimAlpha(1f);
Lyn Hanbde48202019-05-29 19:18:29 -0700214 assertScrimAlpha(OPAQUE /* front */,
215 OPAQUE /* back */,
216 TRANSPARENT /* bubble */);
Michael Wrightcae88752018-04-16 23:13:54 +0100217
218 // ... and make sure we recall the previous front scrim alpha even if we transition away
219 // for a bit.
220 mScrimController.transitionTo(ScrimState.UNLOCKED);
221 mScrimController.transitionTo(ScrimState.AOD);
222 mScrimController.finishAnimationsImmediately();
Lyn Hanbde48202019-05-29 19:18:29 -0700223 assertScrimAlpha(OPAQUE /* front */,
224 OPAQUE /* back */,
225 TRANSPARENT /* bubble */);
Michael Wrightcae88752018-04-16 23:13:54 +0100226
Lucas Dupin69bda602018-05-18 17:24:52 -0700227 // ... and alpha updates should be completely ignored if always_on is off.
228 // Passing it forward would mess up the wake-up transition.
229 mAlwaysOnEnabled = false;
230 mScrimController.transitionTo(ScrimState.UNLOCKED);
231 mScrimController.transitionTo(ScrimState.AOD);
232 mScrimController.finishAnimationsImmediately();
233 mScrimController.setAodFrontScrimAlpha(0.3f);
234 Assert.assertEquals(ScrimState.AOD.getFrontAlpha(), mScrimInFront.getViewAlpha(), 0.001f);
235 Assert.assertNotEquals(0.3f, mScrimInFront.getViewAlpha(), 0.001f);
236
Michael Wrightcae88752018-04-16 23:13:54 +0100237 // Reset value since enums are static.
238 mScrimController.setAodFrontScrimAlpha(0f);
239 }
240
241 @Test
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800242 public void transitionToPulsing() {
Lucas Dupin82aa1632017-12-13 00:13:57 -0800243 // Pre-condition
244 // Need to go to AoD first because PULSING doesn't change
245 // the back scrim opacity - otherwise it would hide AoD wallpapers.
246 mScrimController.setWallpaperSupportsAmbientMode(false);
247 mScrimController.transitionTo(ScrimState.AOD);
248 mScrimController.finishAnimationsImmediately();
Lyn Hanbde48202019-05-29 19:18:29 -0700249 assertScrimAlpha(TRANSPARENT /* front */,
250 OPAQUE /* back */,
251 TRANSPARENT /* bubble */);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800252
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800253 mScrimController.transitionTo(ScrimState.PULSING);
254 mScrimController.finishAnimationsImmediately();
Lucas Dupina7eacf92019-07-24 12:40:34 -0700255 // Front scrim should be transparent, but tinted
Lucas Dupinde64ee02018-12-21 14:45:12 -0800256 // Back scrim should be semi-transparent so the user can see the wallpaper
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800257 // Pulse callback should have been invoked
Lyn Hanbde48202019-05-29 19:18:29 -0700258 assertScrimAlpha(TRANSPARENT /* front */,
259 OPAQUE /* back */,
260 TRANSPARENT /* bubble */);
261
Mady Mellor4035ef52019-07-25 11:10:02 -0700262 assertScrimTint(true /* front */,
Lyn Hanbde48202019-05-29 19:18:29 -0700263 true /* behind */,
264 false /* bubble */);
Lucas Dupin5f00fa52019-03-27 22:46:53 -0700265
266 mScrimController.setWakeLockScreenSensorActive(true);
267 mScrimController.finishAnimationsImmediately();
Lyn Hanbde48202019-05-29 19:18:29 -0700268 assertScrimAlpha(TRANSPARENT /* front */,
269 SEMI_TRANSPARENT /* back */,
270 TRANSPARENT /* bubble */);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800271 }
272
273 @Test
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800274 public void transitionToKeyguardBouncer() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800275 mScrimController.transitionTo(ScrimState.BOUNCER);
276 mScrimController.finishAnimationsImmediately();
277 // Front scrim should be transparent
278 // Back scrim should be visible without tint
Lyn Hanbde48202019-05-29 19:18:29 -0700279 assertScrimAlpha(TRANSPARENT /* front */,
280 SEMI_TRANSPARENT /* back */,
281 TRANSPARENT /* bubble */);
282
283 assertScrimTint(false /* front */,
284 false /* behind */,
285 false /* bubble */);
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800286 }
287
288 @Test
289 public void transitionToBouncer() {
Lucas Dupin05726cd2018-03-13 14:00:24 -0700290 mScrimController.transitionTo(ScrimState.BOUNCER_SCRIMMED);
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800291 mScrimController.finishAnimationsImmediately();
292 // Front scrim should be transparent
293 // Back scrim should be visible without tint
Lyn Hanbde48202019-05-29 19:18:29 -0700294 assertScrimAlpha(SEMI_TRANSPARENT /* front */,
295 TRANSPARENT /* back */,
296 TRANSPARENT /* bubble */);
297 assertScrimTint(false /* front */,
298 false /* behind */,
299 false /* bubble */);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800300 }
301
302 @Test
303 public void transitionToUnlocked() {
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800304 mScrimController.setPanelExpansion(0f);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800305 mScrimController.transitionTo(ScrimState.UNLOCKED);
306 mScrimController.finishAnimationsImmediately();
Lyn Hanbde48202019-05-29 19:18:29 -0700307 assertScrimAlpha(TRANSPARENT /* front */,
308 TRANSPARENT /* back */,
309 TRANSPARENT /* bubble */);
310
311 assertScrimTint(false /* front */,
312 false /* behind */,
313 false /* bubble */);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800314
315 // Back scrim should be visible after start dragging
316 mScrimController.setPanelExpansion(0.5f);
Lyn Hanbde48202019-05-29 19:18:29 -0700317 assertScrimAlpha(TRANSPARENT /* front */,
318 SEMI_TRANSPARENT /* back */,
319 TRANSPARENT /* bubble */);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800320 }
321
322 @Test
Mady Mellor0c333772018-11-06 18:05:54 -0800323 public void transitionToBubbleExpanded() {
324 mScrimController.transitionTo(ScrimState.BUBBLE_EXPANDED);
325 mScrimController.finishAnimationsImmediately();
326
Lyn Hanbde48202019-05-29 19:18:29 -0700327 assertScrimTint(false /* front */,
328 false /* behind */,
329 false /* bubble */);
330
Mady Mellor0c333772018-11-06 18:05:54 -0800331 // Front scrim should be transparent
Lyn Hanbde48202019-05-29 19:18:29 -0700332 Assert.assertEquals(ScrimController.TRANSPARENT,
Mady Mellor0c333772018-11-06 18:05:54 -0800333 mScrimInFront.getViewAlpha(), 0.0f);
334 // Back scrim should be visible
335 Assert.assertEquals(ScrimController.GRADIENT_SCRIM_ALPHA_BUSY,
336 mScrimBehind.getViewAlpha(), 0.0f);
Lyn Hanbde48202019-05-29 19:18:29 -0700337 // Bubble scrim should be visible
338 Assert.assertEquals(ScrimController.GRADIENT_SCRIM_ALPHA_BUSY,
339 mScrimBehind.getViewAlpha(), 0.0f);
Mady Mellor0c333772018-11-06 18:05:54 -0800340 }
341
342 @Test
Yohei Yukawa795f0102018-04-13 14:55:30 -0700343 public void scrimStateCallback() {
344 mScrimController.transitionTo(ScrimState.UNLOCKED);
345 mScrimController.finishAnimationsImmediately();
346 Assert.assertEquals(mScrimState, ScrimState.UNLOCKED);
347
348 mScrimController.transitionTo(ScrimState.BOUNCER);
349 mScrimController.finishAnimationsImmediately();
350 Assert.assertEquals(mScrimState, ScrimState.BOUNCER);
351
352 mScrimController.transitionTo(ScrimState.BOUNCER_SCRIMMED);
353 mScrimController.finishAnimationsImmediately();
354 Assert.assertEquals(mScrimState, ScrimState.BOUNCER_SCRIMMED);
355 }
356
357 @Test
shawnlin317db372018-04-09 19:49:48 +0800358 public void panelExpansion() {
359 mScrimController.setPanelExpansion(0f);
360 mScrimController.setPanelExpansion(0.5f);
361 mScrimController.transitionTo(ScrimState.UNLOCKED);
362 mScrimController.finishAnimationsImmediately();
363
364 reset(mScrimBehind);
365 mScrimController.setPanelExpansion(0f);
366 mScrimController.setPanelExpansion(1.0f);
Lucas Dupin4dbe5182019-03-07 18:20:11 -0800367 mScrimController.finishAnimationsImmediately();
shawnlin317db372018-04-09 19:49:48 +0800368
369 Assert.assertEquals("Scrim alpha should change after setPanelExpansion",
370 mScrimBehindAlpha, mScrimBehind.getViewAlpha(), 0.01f);
371
372 mScrimController.setPanelExpansion(0f);
Lucas Dupin4dbe5182019-03-07 18:20:11 -0800373 mScrimController.finishAnimationsImmediately();
shawnlin317db372018-04-09 19:49:48 +0800374
375 Assert.assertEquals("Scrim alpha should change after setPanelExpansion",
376 mScrimBehindAlpha, mScrimBehind.getViewAlpha(), 0.01f);
377 }
378
379 @Test
Lucas Dupin67f02632018-03-12 11:08:31 -0700380 public void panelExpansionAffectsAlpha() {
381 mScrimController.setPanelExpansion(0f);
382 mScrimController.setPanelExpansion(0.5f);
383 mScrimController.transitionTo(ScrimState.UNLOCKED);
384 mScrimController.finishAnimationsImmediately();
385
386 final float scrimAlpha = mScrimBehind.getViewAlpha();
Lucas Dupin067136c2018-03-27 18:03:25 -0700387 reset(mScrimBehind);
Lucas Dupin67f02632018-03-12 11:08:31 -0700388 mScrimController.setExpansionAffectsAlpha(false);
389 mScrimController.setPanelExpansion(0.8f);
Lucas Dupin067136c2018-03-27 18:03:25 -0700390 verifyZeroInteractions(mScrimBehind);
Lucas Dupin67f02632018-03-12 11:08:31 -0700391 Assert.assertEquals("Scrim opacity shouldn't change when setExpansionAffectsAlpha "
392 + "is false", scrimAlpha, mScrimBehind.getViewAlpha(), 0.01f);
393
394 mScrimController.setExpansionAffectsAlpha(true);
395 mScrimController.setPanelExpansion(0.1f);
Lucas Dupin4dbe5182019-03-07 18:20:11 -0800396 mScrimController.finishAnimationsImmediately();
Lucas Dupin67f02632018-03-12 11:08:31 -0700397 Assert.assertNotEquals("Scrim opacity should change when setExpansionAffectsAlpha "
398 + "is true", scrimAlpha, mScrimBehind.getViewAlpha(), 0.01f);
399 }
400
401 @Test
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800402 public void transitionToUnlockedFromAod() {
403 // Simulate unlock with fingerprint
404 mScrimController.transitionTo(ScrimState.AOD);
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800405 mScrimController.setPanelExpansion(0f);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800406 mScrimController.finishAnimationsImmediately();
407 mScrimController.transitionTo(ScrimState.UNLOCKED);
Lyn Hanbde48202019-05-29 19:18:29 -0700408
409 // Immediately tinted black after the transition starts
410 assertScrimTint(true /* front */,
411 true /* behind */,
412 true /* bubble */);
413
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800414 mScrimController.finishAnimationsImmediately();
Lyn Hanbde48202019-05-29 19:18:29 -0700415
416 // All scrims should be transparent at the end of fade transition.
417 assertScrimAlpha(TRANSPARENT /* front */,
418 TRANSPARENT /* behind */,
419 TRANSPARENT /* bubble */);
420
421 assertScrimTint(false /* front */,
422 false /* behind */,
423 false /* bubble */);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800424 }
425
426 @Test
Lucas Dupinea0116e2018-04-05 10:09:29 -0700427 public void scrimBlanksBeforeLeavingAod() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800428 // Simulate unlock with fingerprint
429 mScrimController.transitionTo(ScrimState.AOD);
430 mScrimController.finishAnimationsImmediately();
431 mScrimController.transitionTo(ScrimState.UNLOCKED,
432 new ScrimController.Callback() {
433 @Override
434 public void onDisplayBlanked() {
435 // Front scrim should be black in the middle of the transition
436 Assert.assertTrue("Scrim should be visible during transition. Alpha: "
437 + mScrimInFront.getViewAlpha(), mScrimInFront.getViewAlpha() > 0);
Lyn Hanbde48202019-05-29 19:18:29 -0700438 assertScrimTint(true /* front */,
439 true /* behind */,
440 true /* bubble */);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800441 Assert.assertSame("Scrim should be visible during transition.",
Lyn Hanbde48202019-05-29 19:18:29 -0700442 mScrimVisibility, OPAQUE);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800443 }
444 });
445 mScrimController.finishAnimationsImmediately();
446 }
447
448 @Test
Lucas Dupineb840ea2018-06-01 00:28:58 -0700449 public void scrimBlanksWhenUnlockingFromPulse() {
450 boolean[] blanked = {false};
451 // Simulate unlock with fingerprint
452 mScrimController.transitionTo(ScrimState.PULSING);
453 mScrimController.finishAnimationsImmediately();
454 mScrimController.transitionTo(ScrimState.UNLOCKED,
455 new ScrimController.Callback() {
456 @Override
457 public void onDisplayBlanked() {
458 blanked[0] = true;
459 }
460 });
461 mScrimController.finishAnimationsImmediately();
462 Assert.assertTrue("Scrim should blank when unlocking from pulse.", blanked[0]);
463 }
464
465 @Test
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800466 public void testScrimCallback() {
467 int[] callOrder = {0, 0, 0};
468 int[] currentCall = {0};
469 mScrimController.transitionTo(ScrimState.AOD, new ScrimController.Callback() {
470 @Override
471 public void onStart() {
472 callOrder[0] = ++currentCall[0];
473 }
474
475 @Override
476 public void onDisplayBlanked() {
477 callOrder[1] = ++currentCall[0];
478 }
479
480 @Override
481 public void onFinished() {
482 callOrder[2] = ++currentCall[0];
483 }
484 });
485 mScrimController.finishAnimationsImmediately();
486 Assert.assertEquals("onStart called in wrong order", 1, callOrder[0]);
487 Assert.assertEquals("onDisplayBlanked called in wrong order", 2, callOrder[1]);
488 Assert.assertEquals("onFinished called in wrong order", 3, callOrder[2]);
489 }
490
491 @Test
492 public void testScrimCallbacksWithoutAmbientDisplay() {
493 mAlwaysOnEnabled = false;
494 testScrimCallback();
495 }
496
497 @Test
498 public void testScrimCallbackCancelled() {
499 boolean[] cancelledCalled = {false};
500 mScrimController.transitionTo(ScrimState.AOD, new ScrimController.Callback() {
501 @Override
502 public void onCancelled() {
503 cancelledCalled[0] = true;
504 }
505 });
506 mScrimController.transitionTo(ScrimState.PULSING);
507 Assert.assertTrue("onCancelled should have been called", cancelledCalled[0]);
508 }
509
510 @Test
Lucas Dupineea53b32017-12-18 13:47:14 -0800511 public void testHoldsWakeLock_whenAOD() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800512 mScrimController.transitionTo(ScrimState.AOD);
Lucas Dupinee4c9b72019-02-18 17:04:58 -0800513 verify(mWakeLock).acquire(anyString());
514 verify(mWakeLock, never()).release(anyString());
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800515 mScrimController.finishAnimationsImmediately();
Lucas Dupinee4c9b72019-02-18 17:04:58 -0800516 verify(mWakeLock).release(anyString());
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800517 }
518
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800519 @Test
Lucas Dupineea53b32017-12-18 13:47:14 -0800520 public void testDoesNotHoldWakeLock_whenUnlocking() {
521 mScrimController.transitionTo(ScrimState.UNLOCKED);
522 mScrimController.finishAnimationsImmediately();
523 verifyZeroInteractions(mWakeLock);
524 }
525
526 @Test
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800527 public void testCallbackInvokedOnSameStateTransition() {
528 mScrimController.transitionTo(ScrimState.UNLOCKED);
529 mScrimController.finishAnimationsImmediately();
530 ScrimController.Callback callback = mock(ScrimController.Callback.class);
531 mScrimController.transitionTo(ScrimState.UNLOCKED, callback);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800532 verify(callback).onFinished();
533 }
534
535 @Test
536 public void testHoldsAodWallpaperAnimationLock() {
537 // Pre-conditions
538 mScrimController.transitionTo(ScrimState.AOD);
539 mScrimController.finishAnimationsImmediately();
540 reset(mWakeLock);
541
542 mScrimController.onHideWallpaperTimeout();
Lucas Dupinee4c9b72019-02-18 17:04:58 -0800543 verify(mWakeLock).acquire(anyString());
544 verify(mWakeLock, never()).release(anyString());
Lucas Dupin82aa1632017-12-13 00:13:57 -0800545 mScrimController.finishAnimationsImmediately();
Lucas Dupinee4c9b72019-02-18 17:04:58 -0800546 verify(mWakeLock).release(anyString());
Lucas Dupin82aa1632017-12-13 00:13:57 -0800547 }
548
549 @Test
TYM Tsaia71c8922019-01-07 15:57:53 +0800550 public void testHoldsPulsingWallpaperAnimationLock() {
551 // Pre-conditions
Lucas Dupin00be88f2019-01-03 17:50:52 -0800552 mScrimController.transitionTo(ScrimState.PULSING);
TYM Tsaia71c8922019-01-07 15:57:53 +0800553 mScrimController.finishAnimationsImmediately();
554 reset(mWakeLock);
555
556 mScrimController.onHideWallpaperTimeout();
Lucas Dupinee4c9b72019-02-18 17:04:58 -0800557 verify(mWakeLock).acquire(anyString());
558 verify(mWakeLock, never()).release(anyString());
TYM Tsaia71c8922019-01-07 15:57:53 +0800559 mScrimController.finishAnimationsImmediately();
Lucas Dupinee4c9b72019-02-18 17:04:58 -0800560 verify(mWakeLock).release(anyString());
TYM Tsaia71c8922019-01-07 15:57:53 +0800561 }
562
563 @Test
Lucas Dupin16cfe452018-02-08 13:14:50 -0800564 public void testWillHideAodWallpaper() {
Lucas Dupin82aa1632017-12-13 00:13:57 -0800565 mScrimController.setWallpaperSupportsAmbientMode(true);
566 mScrimController.transitionTo(ScrimState.AOD);
567 verify(mAlarmManager).setExact(anyInt(), anyLong(), any(), any(), any());
568 mScrimController.transitionTo(ScrimState.KEYGUARD);
569 verify(mAlarmManager).cancel(any(AlarmManager.OnAlarmListener.class));
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800570 }
571
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800572 @Test
Jerry Changbde4c0c2019-06-13 16:58:41 +0800573 public void transitionToPulsing_withTimeoutWallpaperCallback_willHideWallpaper() {
574 mScrimController.setWallpaperSupportsAmbientMode(true);
575
576 mScrimController.transitionTo(ScrimState.PULSING, new ScrimController.Callback() {
577 @Override
578 public boolean shouldTimeoutWallpaper() {
579 return true;
580 }
581 });
582
583 verify(mAlarmManager).setExact(anyInt(), anyLong(), any(), any(), any());
584 }
585
586 @Test
587 public void transitionToPulsing_withDefaultCallback_wontHideWallpaper() {
588 mScrimController.setWallpaperSupportsAmbientMode(true);
589
590 mScrimController.transitionTo(ScrimState.PULSING, new ScrimController.Callback() {});
591
592 verify(mAlarmManager, never()).setExact(anyInt(), anyLong(), any(), any(), any());
593 }
594
595 @Test
596 public void transitionToPulsing_withoutCallback_wontHideWallpaper() {
597 mScrimController.setWallpaperSupportsAmbientMode(true);
598
599 mScrimController.transitionTo(ScrimState.PULSING);
600
601 verify(mAlarmManager, never()).setExact(anyInt(), anyLong(), any(), any(), any());
602 }
603
604 @Test
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800605 public void testConservesExpansionOpacityAfterTransition() {
606 mScrimController.transitionTo(ScrimState.UNLOCKED);
607 mScrimController.setPanelExpansion(0.5f);
608 mScrimController.finishAnimationsImmediately();
609
610 final float expandedAlpha = mScrimBehind.getViewAlpha();
611
612 mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR);
613 mScrimController.finishAnimationsImmediately();
614 mScrimController.transitionTo(ScrimState.UNLOCKED);
615 mScrimController.finishAnimationsImmediately();
616
617 Assert.assertEquals("Scrim expansion opacity wasn't conserved when transitioning back",
618 expandedAlpha, mScrimBehind.getViewAlpha(), 0.01f);
619 }
620
621 @Test
622 public void cancelsOldAnimationBeforeBlanking() {
623 mScrimController.transitionTo(ScrimState.AOD);
624 mScrimController.finishAnimationsImmediately();
625 // Consume whatever value we had before
626 mScrimController.wasAnimationJustCancelled();
627
628 mScrimController.transitionTo(ScrimState.KEYGUARD);
629 mScrimController.finishAnimationsImmediately();
630 Assert.assertTrue(mScrimController.wasAnimationJustCancelled());
631 }
632
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800633 @Test
Lucas Dupin38962d72018-03-14 12:41:39 -0700634 public void testScrimFocus() {
635 mScrimController.transitionTo(ScrimState.AOD);
636 Assert.assertFalse("Should not be focusable on AOD", mScrimBehind.isFocusable());
637 Assert.assertFalse("Should not be focusable on AOD", mScrimInFront.isFocusable());
638
639 mScrimController.transitionTo(ScrimState.KEYGUARD);
640 Assert.assertTrue("Should be focusable on keyguard", mScrimBehind.isFocusable());
641 Assert.assertTrue("Should be focusable on keyguard", mScrimInFront.isFocusable());
642 }
643
Lucas Dupind5107302018-03-19 15:30:29 -0700644 @Test
645 public void testHidesShowWhenLockedActivity() {
646 mScrimController.setWallpaperSupportsAmbientMode(true);
647 mScrimController.setKeyguardOccluded(true);
648 mScrimController.transitionTo(ScrimState.AOD);
649 mScrimController.finishAnimationsImmediately();
Lyn Hanbde48202019-05-29 19:18:29 -0700650 assertScrimAlpha(TRANSPARENT /* front */,
651 OPAQUE /* behind */,
652 TRANSPARENT /* bubble */);
Lucas Dupind5107302018-03-19 15:30:29 -0700653
654 mScrimController.transitionTo(ScrimState.PULSING);
655 mScrimController.finishAnimationsImmediately();
Lyn Hanbde48202019-05-29 19:18:29 -0700656 assertScrimAlpha(TRANSPARENT /* front */,
657 OPAQUE /* behind */,
658 TRANSPARENT /* bubble */);
Lucas Dupind5107302018-03-19 15:30:29 -0700659 }
660
Lucas Dupin78949b82018-04-03 18:54:39 -0700661 @Test
Lucas Dupin63d72172018-06-06 11:42:55 -0700662 public void testHidesShowWhenLockedActivity_whenAlreadyInAod() {
663 mScrimController.setWallpaperSupportsAmbientMode(true);
664 mScrimController.transitionTo(ScrimState.AOD);
665 mScrimController.finishAnimationsImmediately();
Lyn Hanbde48202019-05-29 19:18:29 -0700666 assertScrimAlpha(TRANSPARENT /* front */,
667 TRANSPARENT /* behind */,
668 TRANSPARENT /* bubble */);
Lucas Dupin63d72172018-06-06 11:42:55 -0700669
670 mScrimController.setKeyguardOccluded(true);
671 mScrimController.finishAnimationsImmediately();
Lyn Hanbde48202019-05-29 19:18:29 -0700672 assertScrimAlpha(TRANSPARENT /* front */,
673 OPAQUE /* behind */,
674 TRANSPARENT /* bubble */);
Lucas Dupin63d72172018-06-06 11:42:55 -0700675 }
676
677 @Test
Lucas Dupin78949b82018-04-03 18:54:39 -0700678 public void testEatsTouchEvent() {
679 HashSet<ScrimState> eatsTouches =
Lucas Dupin1c327432019-01-03 13:37:53 -0800680 new HashSet<>(Collections.singletonList(ScrimState.AOD));
Lucas Dupin78949b82018-04-03 18:54:39 -0700681 for (ScrimState state : ScrimState.values()) {
682 if (state == ScrimState.UNINITIALIZED) {
683 continue;
684 }
685 mScrimController.transitionTo(state);
686 mScrimController.finishAnimationsImmediately();
687 Assert.assertEquals("Should be clickable unless AOD or PULSING, was: " + state,
688 mScrimBehind.getViewAlpha() != 0 && !eatsTouches.contains(state),
689 mScrimBehind.isClickable());
690 }
691 }
692
Lucas Dupinea0116e2018-04-05 10:09:29 -0700693 @Test
694 public void testAnimatesTransitionToAod() {
695 when(mDozeParamenters.shouldControlScreenOff()).thenReturn(false);
696 ScrimState.AOD.prepare(ScrimState.KEYGUARD);
697 Assert.assertFalse("No animation when ColorFade kicks in",
698 ScrimState.AOD.getAnimateChange());
699
700 reset(mDozeParamenters);
701 when(mDozeParamenters.shouldControlScreenOff()).thenReturn(true);
702 ScrimState.AOD.prepare(ScrimState.KEYGUARD);
703 Assert.assertTrue("Animate scrims when ColorFade won't be triggered",
704 ScrimState.AOD.getAnimateChange());
705 }
706
Lucas Dupin373356b2018-04-07 10:50:25 -0700707 @Test
708 public void testViewsDontHaveFocusHighlight() {
709 Assert.assertFalse("Scrim shouldn't have focus highlight",
710 mScrimInFront.getDefaultFocusHighlightEnabled());
711 Assert.assertFalse("Scrim shouldn't have focus highlight",
712 mScrimBehind.getDefaultFocusHighlightEnabled());
Lyn Hanbde48202019-05-29 19:18:29 -0700713 Assert.assertFalse("Scrim shouldn't have focus highlight",
714 mScrimForBubble.getDefaultFocusHighlightEnabled());
Lucas Dupin373356b2018-04-07 10:50:25 -0700715 }
716
Lyn Hanbde48202019-05-29 19:18:29 -0700717 private void assertScrimTint(boolean front, boolean behind, boolean bubble) {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800718 Assert.assertEquals("Tint test failed at state " + mScrimController.getState()
Lyn Hanbde48202019-05-29 19:18:29 -0700719 + " with scrim: " + getScrimName(mScrimInFront) + " and tint: "
720 + Integer.toHexString(mScrimInFront.getTint()),
721 front, mScrimInFront.getTint() != Color.TRANSPARENT);
722
723 Assert.assertEquals("Tint test failed at state " + mScrimController.getState()
724 + " with scrim: " + getScrimName(mScrimBehind) + " and tint: "
725 + Integer.toHexString(mScrimBehind.getTint()),
726 behind, mScrimBehind.getTint() != Color.TRANSPARENT);
727
728 Assert.assertEquals("Tint test failed at state " + mScrimController.getState()
729 + " with scrim: " + getScrimName(mScrimForBubble) + " and tint: "
730 + Integer.toHexString(mScrimForBubble.getTint()),
731 bubble, mScrimForBubble.getTint() != Color.TRANSPARENT);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800732 }
733
Lyn Hanbde48202019-05-29 19:18:29 -0700734 private String getScrimName(ScrimView scrim) {
735 if (scrim == mScrimInFront) {
736 return "front";
737 } else if (scrim == mScrimBehind) {
738 return "back";
739 } else if (scrim == mScrimForBubble) {
740 return "bubble";
Lucas Dupin82aa1632017-12-13 00:13:57 -0800741 }
Lyn Hanbde48202019-05-29 19:18:29 -0700742 return "unknown_scrim";
743 }
744
745 private void assertScrimAlpha(int front, int behind, int bubble) {
746 // Check single scrim visibility.
747 Assert.assertEquals("Unexpected front scrim alpha: "
748 + mScrimInFront.getViewAlpha(),
749 front != TRANSPARENT /* expected */,
750 mScrimInFront.getViewAlpha() > TRANSPARENT /* actual */);
751
752 Assert.assertEquals("Unexpected back scrim alpha: "
753 + mScrimBehind.getViewAlpha(),
754 behind != TRANSPARENT /* expected */,
755 mScrimBehind.getViewAlpha() > TRANSPARENT /* actual */);
756
757 Assert.assertEquals(
758 "Unexpected bubble scrim alpha: "
759 + mScrimForBubble.getViewAlpha(), /* message */
760 bubble != TRANSPARENT /* expected */,
761 mScrimForBubble.getViewAlpha() > TRANSPARENT /* actual */);
762
763 // Check combined scrim visibility.
764 final int visibility;
765 if (front == OPAQUE || behind == OPAQUE || bubble == OPAQUE) {
766 visibility = OPAQUE;
767 } else if (front > TRANSPARENT || behind > TRANSPARENT || bubble > TRANSPARENT) {
768 visibility = SEMI_TRANSPARENT;
769 } else {
770 visibility = TRANSPARENT;
771 }
772 Assert.assertEquals("Invalid visibility.",
773 visibility /* expected */,
774 mScrimVisibility);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800775 }
776
777 /**
778 * Special version of ScrimController where animations have 0 duration for test purposes.
779 */
780 private class SynchronousScrimController extends ScrimController {
781
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800782 private boolean mAnimationCancelled;
Lucas Dupin16cfe452018-02-08 13:14:50 -0800783 boolean mOnPreDrawCalled;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800784
shawnlin317db372018-04-09 19:49:48 +0800785 SynchronousScrimController(ScrimView scrimBehind, ScrimView scrimInFront,
Lyn Hanbde48202019-05-29 19:18:29 -0700786 ScrimView scrimForBubble,
Yohei Yukawa795f0102018-04-13 14:55:30 -0700787 TriConsumer<ScrimState, Float, GradientColors> scrimStateListener,
Lucas Dupin82aa1632017-12-13 00:13:57 -0800788 Consumer<Integer> scrimVisibleListener, DozeParameters dozeParameters,
789 AlarmManager alarmManager) {
Lyn Hanbde48202019-05-29 19:18:29 -0700790 super(scrimBehind, scrimInFront, scrimForBubble, scrimStateListener,
791 scrimVisibleListener, dozeParameters, alarmManager);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800792 }
793
Lucas Dupin16cfe452018-02-08 13:14:50 -0800794 @Override
795 public boolean onPreDraw() {
796 mOnPreDrawCalled = true;
797 return super.onPreDraw();
798 }
799
Lucas Dupin3503c5f2018-03-02 19:04:00 -0800800 void finishAnimationsImmediately() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800801 boolean[] animationFinished = {false};
Lyn Hanbde48202019-05-29 19:18:29 -0700802 setOnAnimationFinished(() -> animationFinished[0] = true);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800803 // Execute code that will trigger animations.
804 onPreDraw();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800805 // Force finish all animations.
Lucas Dupin54fbfb32019-03-05 18:08:13 -0800806 mLooper.processAllMessages();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800807 endAnimation(mScrimBehind, TAG_KEY_ANIM);
808 endAnimation(mScrimInFront, TAG_KEY_ANIM);
Lyn Hanbde48202019-05-29 19:18:29 -0700809 endAnimation(mScrimForBubble, TAG_KEY_ANIM);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800810
811 if (!animationFinished[0]) {
812 throw new IllegalStateException("Animation never finished");
813 }
814 }
815
Lucas Dupin3503c5f2018-03-02 19:04:00 -0800816 boolean wasAnimationJustCancelled() {
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800817 final boolean wasCancelled = mAnimationCancelled;
818 mAnimationCancelled = false;
819 return wasCancelled;
820 }
821
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800822 private void endAnimation(View scrimView, int tag) {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800823 Animator animator = (Animator) scrimView.getTag(tag);
824 if (animator != null) {
825 animator.end();
826 }
827 }
828
829 @Override
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800830 protected void cancelAnimator(ValueAnimator previousAnimator) {
831 super.cancelAnimator(previousAnimator);
832 mAnimationCancelled = true;
833 }
834
835 @Override
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800836 protected Handler getHandler() {
Lucas Dupin54fbfb32019-03-05 18:08:13 -0800837 return new FakeHandler(mLooper.getLooper());
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800838 }
839
840 @Override
841 protected WakeLock createWakeLock() {
842 return mWakeLock;
843 }
Lucas Dupin8c7cb022018-02-05 10:49:03 -0800844
845 /**
846 * Do not wait for a frame since we're in a test environment.
Lyn Hanbde48202019-05-29 19:18:29 -0700847 *
Lucas Dupin8c7cb022018-02-05 10:49:03 -0800848 * @param callback What to execute.
849 */
850 @Override
Lucas Dupin0791d972018-03-26 13:32:16 -0700851 protected void doOnTheNextFrame(Runnable callback) {
852 callback.run();
Lucas Dupin8c7cb022018-02-05 10:49:03 -0800853 }
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800854 }
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800855}