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