• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.keyguard;
18 
19 import static android.view.WindowInsets.Type.ime;
20 
21 import static com.android.keyguard.KeyguardSecurityContainer.MODE_DEFAULT;
22 import static com.android.keyguard.KeyguardSecurityContainer.MODE_ONE_HANDED;
23 
24 import static com.google.common.truth.Truth.assertThat;
25 
26 import static junit.framework.Assert.assertFalse;
27 import static junit.framework.Assert.assertTrue;
28 
29 import static org.mockito.ArgumentMatchers.any;
30 import static org.mockito.ArgumentMatchers.anyBoolean;
31 import static org.mockito.ArgumentMatchers.anyInt;
32 import static org.mockito.ArgumentMatchers.anyLong;
33 import static org.mockito.ArgumentMatchers.argThat;
34 import static org.mockito.ArgumentMatchers.eq;
35 import static org.mockito.Mockito.clearInvocations;
36 import static org.mockito.Mockito.mock;
37 import static org.mockito.Mockito.never;
38 import static org.mockito.Mockito.spy;
39 import static org.mockito.Mockito.verify;
40 import static org.mockito.Mockito.when;
41 
42 import android.content.res.Configuration;
43 import android.content.res.Resources;
44 import android.hardware.biometrics.BiometricOverlayConstants;
45 import android.media.AudioManager;
46 import android.telephony.TelephonyManager;
47 import android.testing.AndroidTestingRunner;
48 import android.testing.TestableLooper;
49 import android.testing.TestableResources;
50 import android.view.Gravity;
51 import android.view.LayoutInflater;
52 import android.view.MotionEvent;
53 import android.view.WindowInsetsController;
54 import android.widget.FrameLayout;
55 
56 import androidx.test.filters.SmallTest;
57 
58 import com.android.internal.logging.MetricsLogger;
59 import com.android.internal.logging.UiEventLogger;
60 import com.android.internal.widget.LockPatternUtils;
61 import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
62 import com.android.systemui.R;
63 import com.android.systemui.SysuiTestCase;
64 import com.android.systemui.biometrics.SideFpsController;
65 import com.android.systemui.biometrics.SideFpsUiRequestSource;
66 import com.android.systemui.classifier.FalsingA11yDelegate;
67 import com.android.systemui.classifier.FalsingCollector;
68 import com.android.systemui.flags.FeatureFlags;
69 import com.android.systemui.flags.Flags;
70 import com.android.systemui.log.SessionTracker;
71 import com.android.systemui.plugins.ActivityStarter;
72 import com.android.systemui.plugins.FalsingManager;
73 import com.android.systemui.statusbar.policy.ConfigurationController;
74 import com.android.systemui.statusbar.policy.KeyguardStateController;
75 import com.android.systemui.statusbar.policy.UserSwitcherController;
76 import com.android.systemui.util.settings.GlobalSettings;
77 
78 import org.junit.Before;
79 import org.junit.Rule;
80 import org.junit.Test;
81 import org.junit.runner.RunWith;
82 import org.mockito.ArgumentCaptor;
83 import org.mockito.ArgumentMatcher;
84 import org.mockito.Captor;
85 import org.mockito.Mock;
86 import org.mockito.junit.MockitoJUnit;
87 import org.mockito.junit.MockitoRule;
88 
89 import java.util.Optional;
90 
91 @SmallTest
92 @RunWith(AndroidTestingRunner.class)
93 @TestableLooper.RunWithLooper()
94 public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
95     private static final int TARGET_USER_ID = 100;
96     @Rule
97     public MockitoRule mRule = MockitoJUnit.rule();
98     @Mock
99     private KeyguardSecurityContainer mView;
100     @Mock
101     private AdminSecondaryLockScreenController.Factory mAdminSecondaryLockScreenControllerFactory;
102     @Mock
103     private AdminSecondaryLockScreenController mAdminSecondaryLockScreenController;
104     @Mock
105     private LockPatternUtils mLockPatternUtils;
106     @Mock
107     private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
108     @Mock
109     private KeyguardSecurityModel mKeyguardSecurityModel;
110     @Mock
111     private MetricsLogger mMetricsLogger;
112     @Mock
113     private UiEventLogger mUiEventLogger;
114     @Mock
115     private KeyguardStateController mKeyguardStateController;
116     @Mock
117     private KeyguardInputViewController mInputViewController;
118     @Mock
119     private WindowInsetsController mWindowInsetsController;
120     @Mock
121     private KeyguardSecurityViewFlipper mSecurityViewFlipper;
122     @Mock
123     private KeyguardSecurityViewFlipperController mKeyguardSecurityViewFlipperController;
124     @Mock
125     private KeyguardMessageAreaController.Factory mKeyguardMessageAreaControllerFactory;
126     @Mock
127     private KeyguardMessageAreaController mKeyguardMessageAreaController;
128     @Mock
129     private BouncerKeyguardMessageArea mKeyguardMessageArea;
130     @Mock
131     private ConfigurationController mConfigurationController;
132     @Mock
133     private EmergencyButtonController mEmergencyButtonController;
134     @Mock
135     private FalsingCollector mFalsingCollector;
136     @Mock
137     private FalsingManager mFalsingManager;
138     @Mock
139     private GlobalSettings mGlobalSettings;
140     @Mock
141     private FeatureFlags mFeatureFlags;
142     @Mock
143     private UserSwitcherController mUserSwitcherController;
144     @Mock
145     private SessionTracker mSessionTracker;
146     @Mock
147     private KeyguardViewController mKeyguardViewController;
148     @Mock
149     private SideFpsController mSideFpsController;
150     @Mock
151     private KeyguardPasswordViewController mKeyguardPasswordViewControllerMock;
152     @Mock
153     private FalsingA11yDelegate mFalsingA11yDelegate;
154     @Mock
155     private TelephonyManager mTelephonyManager;
156     @Mock
157     private ViewMediatorCallback mViewMediatorCallback;
158     @Mock
159     private AudioManager mAudioManager;
160 
161     @Captor
162     private ArgumentCaptor<KeyguardUpdateMonitorCallback> mKeyguardUpdateMonitorCallback;
163     @Captor
164     private ArgumentCaptor<KeyguardSecurityContainer.SwipeListener> mSwipeListenerArgumentCaptor;
165 
166     private KeyguardSecurityContainerController mKeyguardSecurityContainerController;
167     private KeyguardPasswordViewController mKeyguardPasswordViewController;
168     private KeyguardPasswordView mKeyguardPasswordView;
169     private TestableResources mTestableResources;
170 
171     @Before
setup()172     public void setup() {
173         mTestableResources = mContext.getOrCreateTestableResources();
174         mTestableResources.getResources().getConfiguration().orientation =
175                 Configuration.ORIENTATION_UNDEFINED;
176 
177         when(mView.getContext()).thenReturn(mContext);
178         when(mView.getResources()).thenReturn(mTestableResources.getResources());
179         FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(/* width=  */ 0, /* height= */
180                 0);
181         lp.gravity = 0;
182         when(mView.getLayoutParams()).thenReturn(lp);
183         when(mAdminSecondaryLockScreenControllerFactory.create(any(KeyguardSecurityCallback.class)))
184                 .thenReturn(mAdminSecondaryLockScreenController);
185         when(mSecurityViewFlipper.getWindowInsetsController()).thenReturn(mWindowInsetsController);
186         when(mKeyguardSecurityViewFlipperController.getSecurityView(any(SecurityMode.class),
187                 any(KeyguardSecurityCallback.class))).thenReturn(mInputViewController);
188         mKeyguardPasswordView = spy((KeyguardPasswordView) LayoutInflater.from(mContext).inflate(
189                 R.layout.keyguard_password_view, null));
190         when(mKeyguardPasswordView.getRootView()).thenReturn(mSecurityViewFlipper);
191         when(mKeyguardPasswordView.requireViewById(R.id.bouncer_message_area))
192                 .thenReturn(mKeyguardMessageArea);
193         when(mKeyguardMessageAreaControllerFactory.create(any(KeyguardMessageArea.class)))
194                 .thenReturn(mKeyguardMessageAreaController);
195         when(mKeyguardPasswordView.getWindowInsetsController()).thenReturn(mWindowInsetsController);
196         when(mKeyguardSecurityModel.getSecurityMode(anyInt())).thenReturn(SecurityMode.PIN);
197         when(mKeyguardStateController.canDismissLockScreen()).thenReturn(true);
198         mKeyguardPasswordViewController = new KeyguardPasswordViewController(
199                 (KeyguardPasswordView) mKeyguardPasswordView, mKeyguardUpdateMonitor,
200                 SecurityMode.Password, mLockPatternUtils, null,
201                 mKeyguardMessageAreaControllerFactory, null, null, mEmergencyButtonController,
202                 null, mock(Resources.class), null, mKeyguardViewController);
203 
204         mKeyguardSecurityContainerController = new KeyguardSecurityContainerController(
205                 mView, mAdminSecondaryLockScreenControllerFactory, mLockPatternUtils,
206                 mKeyguardUpdateMonitor, mKeyguardSecurityModel, mMetricsLogger, mUiEventLogger,
207                 mKeyguardStateController, mKeyguardSecurityViewFlipperController,
208                 mConfigurationController, mFalsingCollector, mFalsingManager,
209                 mUserSwitcherController, mFeatureFlags, mGlobalSettings,
210                 mSessionTracker, Optional.of(mSideFpsController), mFalsingA11yDelegate,
211                 mTelephonyManager, mViewMediatorCallback, mAudioManager);
212     }
213 
214     @Test
onInitConfiguresViewMode()215     public void onInitConfiguresViewMode() {
216         mKeyguardSecurityContainerController.onInit();
217         verify(mView).initMode(eq(MODE_DEFAULT), eq(mGlobalSettings), eq(mFalsingManager),
218                 eq(mUserSwitcherController),
219                 any(KeyguardSecurityContainer.UserSwitcherViewMode.UserSwitcherCallback.class),
220                 eq(mFalsingA11yDelegate));
221     }
222 
223     @Test
showSecurityScreen_canInflateAllModes()224     public void showSecurityScreen_canInflateAllModes() {
225         SecurityMode[] modes = SecurityMode.values();
226         for (SecurityMode mode : modes) {
227             when(mInputViewController.getSecurityMode()).thenReturn(mode);
228             mKeyguardSecurityContainerController.showSecurityScreen(mode);
229             if (mode == SecurityMode.Invalid) {
230                 verify(mKeyguardSecurityViewFlipperController, never()).getSecurityView(
231                         any(SecurityMode.class), any(KeyguardSecurityCallback.class));
232             } else {
233                 verify(mKeyguardSecurityViewFlipperController).getSecurityView(
234                         eq(mode), any(KeyguardSecurityCallback.class));
235             }
236         }
237     }
238 
239     @Test
startDisappearAnimation_animatesKeyboard()240     public void startDisappearAnimation_animatesKeyboard() {
241         when(mKeyguardSecurityModel.getSecurityMode(anyInt())).thenReturn(
242                 SecurityMode.Password);
243         when(mKeyguardSecurityViewFlipperController.getSecurityView(
244                 eq(SecurityMode.Password), any(KeyguardSecurityCallback.class)))
245                 .thenReturn((KeyguardInputViewController) mKeyguardPasswordViewController);
246         mKeyguardSecurityContainerController.showSecurityScreen(SecurityMode.Password);
247 
248         mKeyguardSecurityContainerController.startDisappearAnimation(null);
249         verify(mWindowInsetsController).controlWindowInsetsAnimation(
250                 eq(ime()), anyLong(), any(), any(), any());
251     }
252 
253     @Test
onResourcesUpdate_callsThroughOnRotationChange()254     public void onResourcesUpdate_callsThroughOnRotationChange() {
255         clearInvocations(mView);
256 
257         // Rotation is the same, shouldn't cause an update
258         mKeyguardSecurityContainerController.updateResources();
259         verify(mView, never()).initMode(eq(MODE_DEFAULT), eq(mGlobalSettings), eq(mFalsingManager),
260                 eq(mUserSwitcherController),
261                 any(KeyguardSecurityContainer.UserSwitcherViewMode.UserSwitcherCallback.class),
262                 eq(mFalsingA11yDelegate));
263 
264         // Update rotation. Should trigger update
265         mTestableResources.getResources().getConfiguration().orientation =
266                 Configuration.ORIENTATION_LANDSCAPE;
267 
268         mKeyguardSecurityContainerController.updateResources();
269         verify(mView).initMode(eq(MODE_DEFAULT), eq(mGlobalSettings), eq(mFalsingManager),
270                 eq(mUserSwitcherController),
271                 any(KeyguardSecurityContainer.UserSwitcherViewMode.UserSwitcherCallback.class),
272                 eq(mFalsingA11yDelegate));
273     }
274 
touchDown()275     private void touchDown() {
276         mKeyguardSecurityContainerController.mGlobalTouchListener.onTouchEvent(
277                 MotionEvent.obtain(
278                         /* downTime= */0,
279                         /* eventTime= */0,
280                         MotionEvent.ACTION_DOWN,
281                         /* x= */0,
282                         /* y= */0,
283                         /* metaState= */0));
284     }
285 
286     @Test
onInterceptTap_inhibitsFalsingInSidedSecurityMode()287     public void onInterceptTap_inhibitsFalsingInSidedSecurityMode() {
288 
289         when(mView.isTouchOnTheOtherSideOfSecurity(any())).thenReturn(false);
290         touchDown();
291         verify(mFalsingCollector, never()).avoidGesture();
292 
293         when(mView.isTouchOnTheOtherSideOfSecurity(any())).thenReturn(true);
294         touchDown();
295         verify(mFalsingCollector).avoidGesture();
296     }
297 
298     @Test
showSecurityScreen_oneHandedMode_flagDisabled_noOneHandedMode()299     public void showSecurityScreen_oneHandedMode_flagDisabled_noOneHandedMode() {
300         mTestableResources.addOverride(R.bool.can_use_one_handed_bouncer, false);
301         when(mKeyguardSecurityViewFlipperController.getSecurityView(
302                 eq(SecurityMode.Pattern), any(KeyguardSecurityCallback.class)))
303                 .thenReturn((KeyguardInputViewController) mKeyguardPasswordViewController);
304 
305         mKeyguardSecurityContainerController.showSecurityScreen(SecurityMode.Pattern);
306         verify(mView).initMode(eq(MODE_DEFAULT), eq(mGlobalSettings), eq(mFalsingManager),
307                 eq(mUserSwitcherController),
308                 any(KeyguardSecurityContainer.UserSwitcherViewMode.UserSwitcherCallback.class),
309                 eq(mFalsingA11yDelegate));
310     }
311 
312     @Test
showSecurityScreen_oneHandedMode_flagEnabled_oneHandedMode()313     public void showSecurityScreen_oneHandedMode_flagEnabled_oneHandedMode() {
314         mTestableResources.addOverride(R.bool.can_use_one_handed_bouncer, true);
315         when(mKeyguardSecurityViewFlipperController.getSecurityView(
316                 eq(SecurityMode.Pattern), any(KeyguardSecurityCallback.class)))
317                 .thenReturn((KeyguardInputViewController) mKeyguardPasswordViewController);
318 
319         mKeyguardSecurityContainerController.showSecurityScreen(SecurityMode.Pattern);
320         verify(mView).initMode(eq(MODE_ONE_HANDED), eq(mGlobalSettings), eq(mFalsingManager),
321                 eq(mUserSwitcherController),
322                 any(KeyguardSecurityContainer.UserSwitcherViewMode.UserSwitcherCallback.class),
323                 eq(mFalsingA11yDelegate));
324     }
325 
326     @Test
showSecurityScreen_twoHandedMode_flagEnabled_noOneHandedMode()327     public void showSecurityScreen_twoHandedMode_flagEnabled_noOneHandedMode() {
328         mTestableResources.addOverride(R.bool.can_use_one_handed_bouncer, true);
329         setupGetSecurityView();
330 
331         mKeyguardSecurityContainerController.showSecurityScreen(SecurityMode.Password);
332         verify(mView).initMode(eq(MODE_DEFAULT), eq(mGlobalSettings), eq(mFalsingManager),
333                 eq(mUserSwitcherController),
334                 any(KeyguardSecurityContainer.UserSwitcherViewMode.UserSwitcherCallback.class),
335                 eq(mFalsingA11yDelegate));
336     }
337 
338     @Test
addUserSwitcherCallback()339     public void addUserSwitcherCallback() {
340         ArgumentCaptor<KeyguardSecurityContainer.UserSwitcherViewMode.UserSwitcherCallback>
341                 captor = ArgumentCaptor.forClass(
342                 KeyguardSecurityContainer.UserSwitcherViewMode.UserSwitcherCallback.class);
343 
344         setupGetSecurityView();
345 
346         mKeyguardSecurityContainerController.showSecurityScreen(SecurityMode.Password);
347         verify(mView).initMode(anyInt(), any(GlobalSettings.class), any(FalsingManager.class),
348                 any(UserSwitcherController.class),
349                 captor.capture(),
350                 eq(mFalsingA11yDelegate));
351         captor.getValue().showUnlockToContinueMessage();
352         verify(mKeyguardPasswordViewControllerMock).showMessage(
353                 getContext().getString(R.string.keyguard_unlock_to_continue), null);
354     }
355 
356     @Test
addUserSwitchCallback()357     public void addUserSwitchCallback() {
358         mKeyguardSecurityContainerController.onViewAttached();
359         verify(mUserSwitcherController)
360                 .addUserSwitchCallback(any(UserSwitcherController.UserSwitchCallback.class));
361         mKeyguardSecurityContainerController.onViewDetached();
362         verify(mUserSwitcherController)
363                 .removeUserSwitchCallback(any(UserSwitcherController.UserSwitchCallback.class));
364     }
365 
366     @Test
onBouncerVisibilityChanged_resetsScale()367     public void onBouncerVisibilityChanged_resetsScale() {
368         mKeyguardSecurityContainerController.onBouncerVisibilityChanged(false);
369         verify(mView).resetScale();
370     }
371 
372     @Test
showNextSecurityScreenOrFinish_setsSecurityScreenToPinAfterSimPinUnlock()373     public void showNextSecurityScreenOrFinish_setsSecurityScreenToPinAfterSimPinUnlock() {
374         // GIVEN the current security method is SimPin
375         when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(false);
376         when(mKeyguardUpdateMonitor.getUserUnlockedWithBiometric(TARGET_USER_ID)).thenReturn(false);
377         mKeyguardSecurityContainerController.showSecurityScreen(SecurityMode.SimPin);
378 
379         // WHEN a request is made from the SimPin screens to show the next security method
380         when(mKeyguardSecurityModel.getSecurityMode(TARGET_USER_ID)).thenReturn(SecurityMode.PIN);
381         mKeyguardSecurityContainerController.showNextSecurityScreenOrFinish(
382                 /* authenticated= */true,
383                 TARGET_USER_ID,
384                 /* bypassSecondaryLockScreen= */true,
385                 SecurityMode.SimPin);
386 
387         // THEN the next security method of PIN is set, and the keyguard is not marked as done
388 
389         verify(mViewMediatorCallback, never()).keyguardDonePending(anyBoolean(), anyInt());
390         verify(mViewMediatorCallback, never()).keyguardDone(anyBoolean(), anyInt());
391         assertThat(mKeyguardSecurityContainerController.getCurrentSecurityMode())
392                 .isEqualTo(SecurityMode.PIN);
393     }
394 
395     @Test
showNextSecurityScreenOrFinish_ignoresCallWhenSecurityMethodHasChanged()396     public void showNextSecurityScreenOrFinish_ignoresCallWhenSecurityMethodHasChanged() {
397         //GIVEN current security mode has been set to PIN
398         mKeyguardSecurityContainerController.showSecurityScreen(SecurityMode.PIN);
399 
400         //WHEN a request comes from SimPin to dismiss the security screens
401         boolean keyguardDone = mKeyguardSecurityContainerController.showNextSecurityScreenOrFinish(
402                 /* authenticated= */true,
403                 TARGET_USER_ID,
404                 /* bypassSecondaryLockScreen= */true,
405                 SecurityMode.SimPin);
406 
407         //THEN no action has happened, which will not dismiss the security screens
408         assertThat(keyguardDone).isEqualTo(false);
409         verify(mKeyguardUpdateMonitor, never()).getUserHasTrust(anyInt());
410     }
411 
412     @Test
onSwipeUp_whenFaceDetectionIsNotRunning_initiatesFaceAuth()413     public void onSwipeUp_whenFaceDetectionIsNotRunning_initiatesFaceAuth() {
414         KeyguardSecurityContainer.SwipeListener registeredSwipeListener =
415                 getRegisteredSwipeListener();
416         when(mKeyguardUpdateMonitor.isFaceDetectionRunning()).thenReturn(false);
417         setupGetSecurityView();
418 
419         registeredSwipeListener.onSwipeUp();
420 
421         verify(mKeyguardUpdateMonitor).requestFaceAuth(
422                 FaceAuthApiRequestReason.SWIPE_UP_ON_BOUNCER);
423     }
424 
425     @Test
onSwipeUp_whenFaceDetectionIsRunning_doesNotInitiateFaceAuth()426     public void onSwipeUp_whenFaceDetectionIsRunning_doesNotInitiateFaceAuth() {
427         KeyguardSecurityContainer.SwipeListener registeredSwipeListener =
428                 getRegisteredSwipeListener();
429         when(mKeyguardUpdateMonitor.isFaceDetectionRunning()).thenReturn(true);
430 
431         registeredSwipeListener.onSwipeUp();
432 
433         verify(mKeyguardUpdateMonitor, never())
434                 .requestFaceAuth(FaceAuthApiRequestReason.SWIPE_UP_ON_BOUNCER);
435     }
436 
437     @Test
onSwipeUp_whenFaceDetectionIsTriggered_hidesBouncerMessage()438     public void onSwipeUp_whenFaceDetectionIsTriggered_hidesBouncerMessage() {
439         KeyguardSecurityContainer.SwipeListener registeredSwipeListener =
440                 getRegisteredSwipeListener();
441         when(mKeyguardUpdateMonitor.requestFaceAuth(FaceAuthApiRequestReason.SWIPE_UP_ON_BOUNCER))
442                 .thenReturn(true);
443         setupGetSecurityView();
444 
445         registeredSwipeListener.onSwipeUp();
446 
447         verify(mKeyguardPasswordViewControllerMock).showMessage(null, null);
448     }
449 
450     @Test
onSwipeUp_whenFaceDetectionIsNotTriggered_retainsBouncerMessage()451     public void onSwipeUp_whenFaceDetectionIsNotTriggered_retainsBouncerMessage() {
452         KeyguardSecurityContainer.SwipeListener registeredSwipeListener =
453                 getRegisteredSwipeListener();
454         when(mKeyguardUpdateMonitor.requestFaceAuth(FaceAuthApiRequestReason.SWIPE_UP_ON_BOUNCER))
455                 .thenReturn(false);
456         setupGetSecurityView();
457 
458         registeredSwipeListener.onSwipeUp();
459 
460         verify(mKeyguardPasswordViewControllerMock, never()).showMessage(null, null);
461     }
462 
463     @Test
onDensityOrFontScaleChanged()464     public void onDensityOrFontScaleChanged() {
465         ArgumentCaptor<ConfigurationController.ConfigurationListener>
466                 configurationListenerArgumentCaptor = ArgumentCaptor.forClass(
467                 ConfigurationController.ConfigurationListener.class);
468         mKeyguardSecurityContainerController.onViewAttached();
469         verify(mConfigurationController).addCallback(configurationListenerArgumentCaptor.capture());
470         clearInvocations(mKeyguardSecurityViewFlipperController);
471 
472         configurationListenerArgumentCaptor.getValue().onDensityOrFontScaleChanged();
473 
474         verify(mView).onDensityOrFontScaleChanged();
475         verify(mKeyguardSecurityViewFlipperController).clearViews();
476         verify(mKeyguardSecurityViewFlipperController).getSecurityView(eq(SecurityMode.PIN),
477                 any(KeyguardSecurityCallback.class));
478     }
479 
480     @Test
onThemeChanged()481     public void onThemeChanged() {
482         ArgumentCaptor<ConfigurationController.ConfigurationListener>
483                 configurationListenerArgumentCaptor = ArgumentCaptor.forClass(
484                 ConfigurationController.ConfigurationListener.class);
485         mKeyguardSecurityContainerController.onViewAttached();
486         verify(mConfigurationController).addCallback(configurationListenerArgumentCaptor.capture());
487         clearInvocations(mKeyguardSecurityViewFlipperController);
488 
489         configurationListenerArgumentCaptor.getValue().onThemeChanged();
490 
491         verify(mView).reloadColors();
492         verify(mKeyguardSecurityViewFlipperController).clearViews();
493         verify(mKeyguardSecurityViewFlipperController).getSecurityView(eq(SecurityMode.PIN),
494                 any(KeyguardSecurityCallback.class));
495     }
496 
497     @Test
onUiModeChanged()498     public void onUiModeChanged() {
499         ArgumentCaptor<ConfigurationController.ConfigurationListener>
500                 configurationListenerArgumentCaptor = ArgumentCaptor.forClass(
501                 ConfigurationController.ConfigurationListener.class);
502         mKeyguardSecurityContainerController.onViewAttached();
503         verify(mConfigurationController).addCallback(configurationListenerArgumentCaptor.capture());
504         clearInvocations(mKeyguardSecurityViewFlipperController);
505 
506         configurationListenerArgumentCaptor.getValue().onUiModeChanged();
507 
508         verify(mView).reloadColors();
509         verify(mKeyguardSecurityViewFlipperController).clearViews();
510         verify(mKeyguardSecurityViewFlipperController).getSecurityView(eq(SecurityMode.PIN),
511                 any(KeyguardSecurityCallback.class));
512     }
513 
514     @Test
testHasDismissActions()515     public void testHasDismissActions() {
516         assertFalse("Action not set yet", mKeyguardSecurityContainerController.hasDismissActions());
517         mKeyguardSecurityContainerController.setOnDismissAction(mock(
518                         ActivityStarter.OnDismissAction.class),
519                 null /* cancelAction */);
520         assertTrue("Action should exist", mKeyguardSecurityContainerController.hasDismissActions());
521     }
522 
523     @Test
testWillRunDismissFromKeyguardIsTrue()524     public void testWillRunDismissFromKeyguardIsTrue() {
525         ActivityStarter.OnDismissAction action = mock(ActivityStarter.OnDismissAction.class);
526         when(action.willRunAnimationOnKeyguard()).thenReturn(true);
527         mKeyguardSecurityContainerController.setOnDismissAction(action, null /* cancelAction */);
528 
529         mKeyguardSecurityContainerController.finish(false /* strongAuth */, 0 /* currentUser */);
530 
531         assertThat(mKeyguardSecurityContainerController.willRunDismissFromKeyguard()).isTrue();
532     }
533 
534     @Test
testWillRunDismissFromKeyguardIsFalse()535     public void testWillRunDismissFromKeyguardIsFalse() {
536         ActivityStarter.OnDismissAction action = mock(ActivityStarter.OnDismissAction.class);
537         when(action.willRunAnimationOnKeyguard()).thenReturn(false);
538         mKeyguardSecurityContainerController.setOnDismissAction(action, null /* cancelAction */);
539 
540         mKeyguardSecurityContainerController.finish(false /* strongAuth */, 0 /* currentUser */);
541 
542         assertThat(mKeyguardSecurityContainerController.willRunDismissFromKeyguard()).isFalse();
543     }
544 
545     @Test
testWillRunDismissFromKeyguardIsFalseWhenNoDismissActionSet()546     public void testWillRunDismissFromKeyguardIsFalseWhenNoDismissActionSet() {
547         mKeyguardSecurityContainerController.setOnDismissAction(null /* action */,
548                 null /* cancelAction */);
549 
550         mKeyguardSecurityContainerController.finish(false /* strongAuth */, 0 /* currentUser */);
551 
552         assertThat(mKeyguardSecurityContainerController.willRunDismissFromKeyguard()).isFalse();
553     }
554 
555     @Test
testSecurityCallbackFinish()556     public void testSecurityCallbackFinish() {
557         when(mKeyguardStateController.canDismissLockScreen()).thenReturn(true);
558         when(mKeyguardUpdateMonitor.isUserUnlocked(0)).thenReturn(true);
559         mKeyguardSecurityContainerController.finish(true, 0);
560         verify(mViewMediatorCallback).keyguardDone(anyBoolean(), anyInt());
561     }
562 
563     @Test
testSecurityCallbackFinish_cannotDismissLockScreenAndNotStrongAuth()564     public void testSecurityCallbackFinish_cannotDismissLockScreenAndNotStrongAuth() {
565         when(mFeatureFlags.isEnabled(Flags.PREVENT_BYPASS_KEYGUARD)).thenReturn(true);
566         when(mKeyguardStateController.canDismissLockScreen()).thenReturn(false);
567         mKeyguardSecurityContainerController.finish(false, 0);
568         verify(mViewMediatorCallback, never()).keyguardDone(anyBoolean(), anyInt());
569     }
570 
571     @Test
testOnStartingToHide()572     public void testOnStartingToHide() {
573         mKeyguardSecurityContainerController.onStartingToHide();
574         verify(mInputViewController).onStartingToHide();
575     }
576 
577     @Test
testGravityReappliedOnConfigurationChange()578     public void testGravityReappliedOnConfigurationChange() {
579         // Set initial gravity
580         mTestableResources.addOverride(R.integer.keyguard_host_view_gravity,
581                 Gravity.CENTER);
582         mTestableResources.addOverride(
583                 R.bool.can_use_one_handed_bouncer, false);
584 
585         // Kick off the initial pass...
586         mKeyguardSecurityContainerController.onInit();
587         verify(mView).setLayoutParams(any());
588         clearInvocations(mView);
589 
590         // Now simulate a config change
591         mTestableResources.addOverride(R.integer.keyguard_host_view_gravity,
592                 Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
593 
594         mKeyguardSecurityContainerController.updateResources();
595         verify(mView).setLayoutParams(any());
596     }
597 
598     @Test
testGravityUsesOneHandGravityWhenApplicable()599     public void testGravityUsesOneHandGravityWhenApplicable() {
600         mTestableResources.addOverride(
601                 R.integer.keyguard_host_view_gravity,
602                 Gravity.CENTER);
603         mTestableResources.addOverride(
604                 R.integer.keyguard_host_view_one_handed_gravity,
605                 Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
606 
607         // Start disabled.
608         mTestableResources.addOverride(
609                 R.bool.can_use_one_handed_bouncer, false);
610 
611         mKeyguardSecurityContainerController.onInit();
612         verify(mView).setLayoutParams(argThat(
613                 (ArgumentMatcher<FrameLayout.LayoutParams>) argument ->
614                         argument.gravity == Gravity.CENTER));
615         clearInvocations(mView);
616 
617         // And enable
618         mTestableResources.addOverride(
619                 R.bool.can_use_one_handed_bouncer, true);
620 
621         mKeyguardSecurityContainerController.updateResources();
622         verify(mView).setLayoutParams(argThat(
623                 (ArgumentMatcher<FrameLayout.LayoutParams>) argument ->
624                         argument.gravity == (Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM)));
625     }
626 
627     @Test
testUpdateKeyguardPositionDelegatesToSecurityContainer()628     public void testUpdateKeyguardPositionDelegatesToSecurityContainer() {
629         mKeyguardSecurityContainerController.updateKeyguardPosition(1.0f);
630         verify(mView).updatePositionByTouchX(1.0f);
631     }
632 
633 
634     @Test
testReinflateViewFlipper()635     public void testReinflateViewFlipper() {
636         mKeyguardSecurityContainerController.reinflateViewFlipper(() -> {});
637         verify(mKeyguardSecurityViewFlipperController).clearViews();
638         verify(mKeyguardSecurityViewFlipperController).getSecurityView(any(SecurityMode.class),
639                 any(KeyguardSecurityCallback.class));
640     }
641 
642     @Test
testReinflateViewFlipper_asyncBouncerFlagOn()643     public void testReinflateViewFlipper_asyncBouncerFlagOn() {
644         when(mFeatureFlags.isEnabled(Flags.ASYNC_INFLATE_BOUNCER)).thenReturn(true);
645         KeyguardSecurityViewFlipperController.OnViewInflatedListener onViewInflatedListener =
646                 () -> {
647                 };
648         mKeyguardSecurityContainerController.reinflateViewFlipper(onViewInflatedListener);
649         verify(mKeyguardSecurityViewFlipperController).clearViews();
650         verify(mKeyguardSecurityViewFlipperController).asynchronouslyInflateView(
651                 any(SecurityMode.class),
652                 any(KeyguardSecurityCallback.class), eq(onViewInflatedListener));
653     }
654 
655     @Test
testSideFpsControllerShow()656     public void testSideFpsControllerShow() {
657         mKeyguardSecurityContainerController.updateSideFpsVisibility(/* isVisible= */ true);
658         verify(mSideFpsController).show(
659                 SideFpsUiRequestSource.PRIMARY_BOUNCER,
660                 BiometricOverlayConstants.REASON_AUTH_KEYGUARD);
661     }
662 
663     @Test
testSideFpsControllerHide()664     public void testSideFpsControllerHide() {
665         mKeyguardSecurityContainerController.updateSideFpsVisibility(/* isVisible= */ false);
666         verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
667     }
668 
getRegisteredSwipeListener()669     private KeyguardSecurityContainer.SwipeListener getRegisteredSwipeListener() {
670         mKeyguardSecurityContainerController.onViewAttached();
671         verify(mView).setSwipeListener(mSwipeListenerArgumentCaptor.capture());
672         return mSwipeListenerArgumentCaptor.getValue();
673     }
674 
attachView()675     private void attachView() {
676         mKeyguardSecurityContainerController.onViewAttached();
677         verify(mKeyguardUpdateMonitor).registerCallback(mKeyguardUpdateMonitorCallback.capture());
678     }
679 
setupGetSecurityView()680     private void setupGetSecurityView() {
681         when(mKeyguardSecurityViewFlipperController.getSecurityView(
682                 any(), any(KeyguardSecurityCallback.class)))
683                 .thenReturn((KeyguardInputViewController) mKeyguardPasswordViewControllerMock);
684     }
685 }
686