1 /*
2  * Copyright (C) 2020 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 
17 package com.android.systemui.biometrics;
18 
19 import static org.junit.Assert.assertFalse;
20 import static org.junit.Assert.assertTrue;
21 import static org.mockito.ArgumentMatchers.any;
22 import static org.mockito.ArgumentMatchers.anyInt;
23 import static org.mockito.Mockito.atLeast;
24 import static org.mockito.Mockito.atLeastOnce;
25 import static org.mockito.Mockito.never;
26 import static org.mockito.Mockito.reset;
27 import static org.mockito.Mockito.verify;
28 import static org.mockito.Mockito.when;
29 
30 import android.testing.TestableLooper;
31 import android.view.MotionEvent;
32 
33 import androidx.test.ext.junit.runners.AndroidJUnit4;
34 import androidx.test.filters.SmallTest;
35 
36 import com.android.systemui.RoboPilotTest;
37 import com.android.systemui.shade.ShadeExpansionListener;
38 import com.android.systemui.statusbar.StatusBarState;
39 
40 import org.junit.Test;
41 import org.junit.runner.RunWith;
42 
43 @SmallTest
44 @RoboPilotTest
45 @RunWith(AndroidJUnit4.class)
46 
47 @TestableLooper.RunWithLooper(setAsMainLooper = true)
48 public class UdfpsKeyguardViewLegacyControllerTest extends
49         UdfpsKeyguardViewLegacyControllerBaseTest {
50     @Override
createUdfpsKeyguardViewController()51     public UdfpsKeyguardViewControllerLegacy createUdfpsKeyguardViewController() {
52         return createUdfpsKeyguardViewController(/* useModernBouncer */ false,
53                 /* useExpandedOverlay */ false);
54     }
55 
56     @Test
testShouldPauseAuth_bouncerShowing()57     public void testShouldPauseAuth_bouncerShowing() {
58         mController.onViewAttached();
59         captureStatusBarStateListeners();
60         sendStatusBarStateChanged(StatusBarState.KEYGUARD);
61 
62         when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(true);
63         when(mStatusBarKeyguardViewManager.primaryBouncerIsOrWillBeShowing()).thenReturn(true);
64         when(mView.getUnpausedAlpha()).thenReturn(0);
65         assertTrue(mController.shouldPauseAuth());
66     }
67 
68     @Test
testRegistersExpansionChangedListenerOnAttached()69     public void testRegistersExpansionChangedListenerOnAttached() {
70         mController.onViewAttached();
71         captureStatusBarExpansionListeners();
72     }
73 
74     @Test
testRegistersStatusBarStateListenersOnAttached()75     public void testRegistersStatusBarStateListenersOnAttached() {
76         mController.onViewAttached();
77         captureStatusBarStateListeners();
78     }
79 
80     @Test
testViewControllerQueriesSBStateOnAttached()81     public void testViewControllerQueriesSBStateOnAttached() {
82         mController.onViewAttached();
83         verify(mStatusBarStateController).getState();
84         verify(mStatusBarStateController).getDozeAmount();
85 
86         final float dozeAmount = .88f;
87         when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE_LOCKED);
88         when(mStatusBarStateController.getDozeAmount()).thenReturn(dozeAmount);
89         captureStatusBarStateListeners();
90 
91         mController.onViewAttached();
92         verify(mView, atLeast(1)).setPauseAuth(true);
93         verify(mView).onDozeAmountChanged(dozeAmount, dozeAmount,
94                 UdfpsKeyguardViewLegacy.ANIMATION_BETWEEN_AOD_AND_LOCKSCREEN);
95     }
96 
97     @Test
testListenersUnregisteredOnDetached()98     public void testListenersUnregisteredOnDetached() {
99         mController.onViewAttached();
100         captureStatusBarStateListeners();
101         captureStatusBarExpansionListeners();
102         captureKeyguardStateControllerCallback();
103         mController.onViewDetached();
104 
105         verify(mStatusBarStateController).removeCallback(mStatusBarStateListener);
106         for (ShadeExpansionListener listener : mExpansionListeners) {
107             verify(mShadeExpansionStateManager).removeExpansionListener(listener);
108         }
109         verify(mKeyguardStateController).removeCallback(mKeyguardStateControllerCallback);
110     }
111 
112     @Test
testDozeEventsSentToView()113     public void testDozeEventsSentToView() {
114         mController.onViewAttached();
115         captureStatusBarStateListeners();
116 
117         final float linear = .55f;
118         final float eased = .65f;
119         mStatusBarStateListener.onDozeAmountChanged(linear, eased);
120 
121         verify(mView).onDozeAmountChanged(linear, eased,
122                 UdfpsKeyguardViewLegacy.ANIMATION_BETWEEN_AOD_AND_LOCKSCREEN);
123     }
124 
125     @Test
testShouldPauseAuthUnpausedAlpha0()126     public void testShouldPauseAuthUnpausedAlpha0() {
127         mController.onViewAttached();
128         captureStatusBarStateListeners();
129 
130         when(mView.getUnpausedAlpha()).thenReturn(0);
131         sendStatusBarStateChanged(StatusBarState.KEYGUARD);
132 
133         assertTrue(mController.shouldPauseAuth());
134     }
135 
136     @Test
testFadeFromDialogSuggestedAlpha()137     public void testFadeFromDialogSuggestedAlpha() {
138         // GIVEN view is attached and status bar expansion is 1f
139         mController.onViewAttached();
140         captureStatusBarStateListeners();
141         captureStatusBarExpansionListeners();
142         updateStatusBarExpansion(1f, true);
143         reset(mView);
144 
145         // WHEN dialog suggested alpha is .6f
146         when(mView.getDialogSuggestedAlpha()).thenReturn(.6f);
147         sendStatusBarStateChanged(StatusBarState.KEYGUARD);
148 
149         // THEN alpha is updated based on dialog suggested alpha
150         verify(mView).setUnpausedAlpha((int) (.6f * 255));
151     }
152 
153     @Test
testShouldNotPauseAuthOnKeyguard()154     public void testShouldNotPauseAuthOnKeyguard() {
155         mController.onViewAttached();
156         captureStatusBarStateListeners();
157 
158         sendStatusBarStateChanged(StatusBarState.KEYGUARD);
159 
160         assertFalse(mController.shouldPauseAuth());
161     }
162 
163     @Test
onBiometricAuthenticated_pauseAuth()164     public void onBiometricAuthenticated_pauseAuth() {
165         // GIVEN view is attached and we're on the keyguard (see testShouldNotPauseAuthOnKeyguard)
166         mController.onViewAttached();
167         captureStatusBarStateListeners();
168         sendStatusBarStateChanged(StatusBarState.KEYGUARD);
169 
170         // WHEN biometric is authenticated
171         captureKeyguardStateControllerCallback();
172         when(mKeyguardUpdateMonitor.getUserUnlockedWithBiometric(anyInt())).thenReturn(true);
173         mKeyguardStateControllerCallback.onUnlockedChanged();
174 
175         // THEN pause auth
176         assertTrue(mController.shouldPauseAuth());
177     }
178 
179     @Test
testShouldPauseAuthIsLaunchTransitionFadingAway()180     public void testShouldPauseAuthIsLaunchTransitionFadingAway() {
181         // GIVEN view is attached and we're on the keyguard (see testShouldNotPauseAuthOnKeyguard)
182         mController.onViewAttached();
183         captureStatusBarStateListeners();
184         sendStatusBarStateChanged(StatusBarState.KEYGUARD);
185 
186         // WHEN isLaunchTransitionFadingAway=true
187         captureKeyguardStateControllerCallback();
188         when(mKeyguardStateController.isLaunchTransitionFadingAway()).thenReturn(true);
189         mKeyguardStateControllerCallback.onLaunchTransitionFadingAwayChanged();
190 
191         // THEN pause auth
192         assertTrue(mController.shouldPauseAuth());
193     }
194 
195     @Test
testShouldPauseAuthOnShadeLocked()196     public void testShouldPauseAuthOnShadeLocked() {
197         mController.onViewAttached();
198         captureStatusBarStateListeners();
199 
200         sendStatusBarStateChanged(StatusBarState.SHADE_LOCKED);
201 
202         assertTrue(mController.shouldPauseAuth());
203     }
204 
205     @Test
testShouldPauseAuthOnShade()206     public void testShouldPauseAuthOnShade() {
207         mController.onViewAttached();
208         captureStatusBarStateListeners();
209 
210         // WHEN not on keyguard yet (shade = home)
211         sendStatusBarStateChanged(StatusBarState.SHADE);
212 
213         // THEN pause auth
214         assertTrue(mController.shouldPauseAuth());
215     }
216 
217     @Test
testShouldPauseAuthAnimatingScreenOffFromShade()218     public void testShouldPauseAuthAnimatingScreenOffFromShade() {
219         mController.onViewAttached();
220         captureStatusBarStateListeners();
221 
222         // WHEN transitioning from home/shade => keyguard + animating screen off
223         mStatusBarStateListener.onStatePreChange(StatusBarState.SHADE, StatusBarState.KEYGUARD);
224         when(mKeyguardViewMediator.isAnimatingScreenOff()).thenReturn(true);
225 
226         // THEN pause auth
227         assertTrue(mController.shouldPauseAuth());
228     }
229 
230     @Test
testDoNotPauseAuthAnimatingScreenOffFromLS()231     public void testDoNotPauseAuthAnimatingScreenOffFromLS() {
232         mController.onViewAttached();
233         captureStatusBarStateListeners();
234 
235         // WHEN animating screen off transition from LS => AOD
236         sendStatusBarStateChanged(StatusBarState.KEYGUARD);
237         when(mKeyguardViewMediator.isAnimatingScreenOff()).thenReturn(true);
238 
239         // THEN don't pause auth
240         assertFalse(mController.shouldPauseAuth());
241     }
242 
243     @Test
testOverrideShouldPauseAuthOnShadeLocked()244     public void testOverrideShouldPauseAuthOnShadeLocked() {
245         mController.onViewAttached();
246         captureStatusBarStateListeners();
247 
248         sendStatusBarStateChanged(StatusBarState.SHADE_LOCKED);
249         assertTrue(mController.shouldPauseAuth());
250     }
251 
252     @Test
testFadeInWithStatusBarExpansion()253     public void testFadeInWithStatusBarExpansion() {
254         // GIVEN view is attached
255         mController.onViewAttached();
256         captureStatusBarExpansionListeners();
257         captureKeyguardStateControllerCallback();
258         reset(mView);
259 
260         // WHEN status bar expansion is 0
261         updateStatusBarExpansion(0, true);
262 
263         // THEN alpha is 0
264         verify(mView).setUnpausedAlpha(0);
265     }
266 
267     @Test
testTransitionToFullShadeProgress()268     public void testTransitionToFullShadeProgress() {
269         // GIVEN view is attached and status bar expansion is 1f
270         mController.onViewAttached();
271         captureStatusBarExpansionListeners();
272         updateStatusBarExpansion(1f, true);
273         reset(mView);
274         when(mView.getDialogSuggestedAlpha()).thenReturn(1f);
275 
276         // WHEN we're transitioning to the full shade
277         float transitionProgress = .6f;
278         mController.setTransitionToFullShadeProgress(transitionProgress);
279 
280         // THEN alpha is between 0 and 255
281         verify(mView).setUnpausedAlpha((int) ((1f - transitionProgress) * 255));
282     }
283 
284     @Test
testUpdatePanelExpansion_pauseAuth()285     public void testUpdatePanelExpansion_pauseAuth() {
286         // GIVEN view is attached + on the keyguard
287         mController.onViewAttached();
288         captureStatusBarStateListeners();
289         captureStatusBarExpansionListeners();
290         sendStatusBarStateChanged(StatusBarState.KEYGUARD);
291         reset(mView);
292 
293         // WHEN panelViewExpansion changes to hide
294         when(mView.getUnpausedAlpha()).thenReturn(0);
295         updateStatusBarExpansion(0f, false);
296 
297         // THEN pause auth is updated to PAUSE
298         verify(mView, atLeastOnce()).setPauseAuth(true);
299     }
300 
301     @Test
testUpdatePanelExpansion_unpauseAuth()302     public void testUpdatePanelExpansion_unpauseAuth() {
303         // GIVEN view is attached + on the keyguard + panel expansion is 0f
304         mController.onViewAttached();
305         captureStatusBarStateListeners();
306         captureStatusBarExpansionListeners();
307         sendStatusBarStateChanged(StatusBarState.KEYGUARD);
308         reset(mView);
309 
310         // WHEN panelViewExpansion changes to expanded
311         when(mView.getUnpausedAlpha()).thenReturn(255);
312         updateStatusBarExpansion(1f, true);
313 
314         // THEN pause auth is updated to NOT pause
315         verify(mView, atLeastOnce()).setPauseAuth(false);
316     }
317 
318     @Test
319     // TODO(b/259264861): Tracking Bug
testUdfpsExpandedOverlayOn()320     public void testUdfpsExpandedOverlayOn() {
321         // GIVEN view is attached and useExpandedOverlay is true
322         mController = createUdfpsKeyguardViewController(false, true);
323         mController.onViewAttached();
324         captureKeyGuardViewManagerCallback();
325 
326         // WHEN a touch is received
327         mKeyguardViewManagerCallback.onTouch(
328                 MotionEvent.obtain(0, 0, 0, 0, 0, 0));
329 
330         // THEN udfpsController onTouch is not called
331         assertTrue(mView.mUseExpandedOverlay);
332         verify(mUdfpsController, never()).onTouch(any());
333     }
334 
335     @Test
336     // TODO(b/259264861): Tracking Bug
testUdfpsExpandedOverlayOff()337     public void testUdfpsExpandedOverlayOff() {
338         // GIVEN view is attached and useExpandedOverlay is false
339         mController.onViewAttached();
340         captureKeyGuardViewManagerCallback();
341 
342         // WHEN a touch is received
343         mKeyguardViewManagerCallback.onTouch(
344                 MotionEvent.obtain(0, 0, 0, 0, 0, 0));
345 
346         // THEN udfpsController onTouch is called
347         assertFalse(mView.mUseExpandedOverlay);
348         verify(mUdfpsController).onTouch(any());
349     }
350 }
351