1 /* 2 * Copyright (C) 2016 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.statusbar; 18 19 import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED; 20 import static android.content.pm.UserInfo.FLAG_MANAGED_PROFILE; 21 import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_TOO_DARK; 22 import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT; 23 import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_TIMEOUT; 24 25 import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_AVAILABLE; 26 import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_RECOGNIZED; 27 import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED; 28 import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_ALIGNMENT; 29 import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_BATTERY; 30 import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_BIOMETRIC_MESSAGE; 31 import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP; 32 import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_DISCLOSURE; 33 import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_LOGOUT; 34 import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_OWNER_INFO; 35 import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_PERSISTENT_UNLOCK_MESSAGE; 36 import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_TRANSIENT; 37 import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_TRUST; 38 import static com.android.systemui.keyguard.ScreenLifecycle.SCREEN_OFF; 39 import static com.android.systemui.keyguard.ScreenLifecycle.SCREEN_TURNING_ON; 40 41 import static com.google.common.truth.Truth.assertThat; 42 43 import static org.junit.Assert.assertFalse; 44 import static org.junit.Assert.assertTrue; 45 import static org.mockito.ArgumentMatchers.any; 46 import static org.mockito.ArgumentMatchers.anyBoolean; 47 import static org.mockito.ArgumentMatchers.anyInt; 48 import static org.mockito.ArgumentMatchers.anyObject; 49 import static org.mockito.ArgumentMatchers.anyString; 50 import static org.mockito.ArgumentMatchers.eq; 51 import static org.mockito.Mockito.clearInvocations; 52 import static org.mockito.Mockito.mock; 53 import static org.mockito.Mockito.never; 54 import static org.mockito.Mockito.reset; 55 import static org.mockito.Mockito.times; 56 import static org.mockito.Mockito.verify; 57 import static org.mockito.Mockito.verifyNoMoreInteractions; 58 import static org.mockito.Mockito.when; 59 60 import android.content.Intent; 61 import android.content.pm.UserInfo; 62 import android.graphics.Color; 63 import android.hardware.biometrics.BiometricFaceConstants; 64 import android.hardware.biometrics.BiometricFingerprintConstants; 65 import android.hardware.biometrics.BiometricSourceType; 66 import android.os.BatteryManager; 67 import android.os.RemoteException; 68 import android.testing.TestableLooper; 69 70 import androidx.test.ext.junit.runners.AndroidJUnit4; 71 import androidx.test.filters.FlakyTest; 72 import androidx.test.filters.SmallTest; 73 74 import com.android.keyguard.TrustGrantFlags; 75 import com.android.settingslib.fuelgauge.BatteryStatus; 76 import com.android.systemui.dock.DockManager; 77 import com.android.systemui.keyguard.KeyguardIndication; 78 import com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController; 79 import com.android.systemui.res.R; 80 81 import org.junit.Test; 82 import org.junit.runner.RunWith; 83 84 import java.text.NumberFormat; 85 import java.util.Collections; 86 import java.util.HashSet; 87 import java.util.List; 88 import java.util.Set; 89 90 @SmallTest 91 @RunWith(AndroidJUnit4.class) 92 @TestableLooper.RunWithLooper(setAsMainLooper = true) 93 public class KeyguardIndicationControllerTest extends KeyguardIndicationControllerBaseTest { 94 @Test afterFaceLockout_skipShowingFaceNotRecognized()95 public void afterFaceLockout_skipShowingFaceNotRecognized() { 96 createController(); 97 onFaceLockoutError("lockout"); 98 verifyIndicationShown(INDICATION_TYPE_BIOMETRIC_MESSAGE, "lockout"); 99 clearInvocations(mRotateTextViewController); 100 101 // WHEN face sends an onBiometricHelp BIOMETRIC_HELP_FACE_NOT_RECOGNIZED (face fail) 102 mKeyguardUpdateMonitorCallback.onBiometricHelp( 103 BIOMETRIC_HELP_FACE_NOT_RECOGNIZED, 104 "Face not recognized", 105 BiometricSourceType.FACE); 106 verifyNoMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE); // no updated message 107 } 108 109 @Test createController_setIndicationAreaAgain_destroysPreviousRotateTextViewController()110 public void createController_setIndicationAreaAgain_destroysPreviousRotateTextViewController() { 111 // GIVEN a controller with a mocked rotate text view controlller 112 final KeyguardIndicationRotateTextViewController mockedRotateTextViewController = 113 mock(KeyguardIndicationRotateTextViewController.class); 114 createController(); 115 mController.mRotateTextViewController = mockedRotateTextViewController; 116 117 // WHEN a new indication area is set 118 mController.setIndicationArea(mIndicationArea); 119 120 // THEN the previous rotateTextViewController is destroyed 121 verify(mockedRotateTextViewController).destroy(); 122 } 123 124 @Test createController_addsAlignmentListener()125 public void createController_addsAlignmentListener() { 126 createController(); 127 128 verify(mDockManager).addAlignmentStateListener( 129 any(DockManager.AlignmentStateListener.class)); 130 } 131 132 @Test onAlignmentStateChanged_showsSlowChargingIndication()133 public void onAlignmentStateChanged_showsSlowChargingIndication() { 134 createController(); 135 verify(mDockManager).addAlignmentStateListener(mAlignmentListener.capture()); 136 mController.setVisible(true); 137 138 mAlignmentListener.getValue().onAlignmentStateChanged(DockManager.ALIGN_STATE_POOR); 139 mTestableLooper.processAllMessages(); 140 141 verifyIndicationMessage(INDICATION_TYPE_ALIGNMENT, 142 mContext.getResources().getString(R.string.dock_alignment_slow_charging)); 143 assertThat(mKeyguardIndicationCaptor.getValue().getTextColor().getDefaultColor()) 144 .isEqualTo(mContext.getColor(R.color.misalignment_text_color)); 145 } 146 147 @Test onAlignmentStateChanged_showsNotChargingIndication()148 public void onAlignmentStateChanged_showsNotChargingIndication() { 149 createController(); 150 verify(mDockManager).addAlignmentStateListener(mAlignmentListener.capture()); 151 mController.setVisible(true); 152 153 mAlignmentListener.getValue().onAlignmentStateChanged(DockManager.ALIGN_STATE_TERRIBLE); 154 mTestableLooper.processAllMessages(); 155 156 verifyIndicationMessage(INDICATION_TYPE_ALIGNMENT, 157 mContext.getResources().getString(R.string.dock_alignment_not_charging)); 158 assertThat(mKeyguardIndicationCaptor.getValue().getTextColor().getDefaultColor()) 159 .isEqualTo(mContext.getColor(R.color.misalignment_text_color)); 160 } 161 162 @FlakyTest(bugId = 279944472) 163 @Test onAlignmentStateChanged_whileDozing_showsSlowChargingIndication()164 public void onAlignmentStateChanged_whileDozing_showsSlowChargingIndication() { 165 createController(); 166 verify(mDockManager).addAlignmentStateListener(mAlignmentListener.capture()); 167 mController.setVisible(true); 168 mStatusBarStateListener.onDozingChanged(true); 169 170 mAlignmentListener.getValue().onAlignmentStateChanged(DockManager.ALIGN_STATE_POOR); 171 mTestableLooper.processAllMessages(); 172 173 assertThat(mTextView.getText()).isEqualTo( 174 mContext.getResources().getString(R.string.dock_alignment_slow_charging)); 175 assertThat(mTextView.getCurrentTextColor()).isEqualTo( 176 mContext.getColor(R.color.misalignment_text_color)); 177 } 178 179 @Test onAlignmentStateChanged_whileDozing_showsNotChargingIndication()180 public void onAlignmentStateChanged_whileDozing_showsNotChargingIndication() { 181 createController(); 182 verify(mDockManager).addAlignmentStateListener(mAlignmentListener.capture()); 183 mController.setVisible(true); 184 mStatusBarStateListener.onDozingChanged(true); 185 186 mAlignmentListener.getValue().onAlignmentStateChanged(DockManager.ALIGN_STATE_TERRIBLE); 187 mTestableLooper.processAllMessages(); 188 189 assertThat(mTextView.getText()).isEqualTo( 190 mContext.getResources().getString(R.string.dock_alignment_not_charging)); 191 assertThat(mTextView.getCurrentTextColor()).isEqualTo( 192 mContext.getColor(R.color.misalignment_text_color)); 193 } 194 195 @Test disclosure_unmanaged()196 public void disclosure_unmanaged() { 197 createController(); 198 mController.setVisible(true); 199 when(mKeyguardStateController.isShowing()).thenReturn(true); 200 when(mDevicePolicyManager.isDeviceManaged()).thenReturn(false); 201 when(mDevicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile()).thenReturn(false); 202 reset(mRotateTextViewController); 203 204 sendUpdateDisclosureBroadcast(); 205 mExecutor.runAllReady(); 206 207 verifyHideIndication(INDICATION_TYPE_DISCLOSURE); 208 } 209 210 @Test disclosure_deviceOwner_noOrganizationName()211 public void disclosure_deviceOwner_noOrganizationName() { 212 createController(); 213 when(mKeyguardStateController.isShowing()).thenReturn(true); 214 when(mDevicePolicyManager.isDeviceManaged()).thenReturn(true); 215 when(mDevicePolicyManager.getDeviceOwnerOrganizationName()).thenReturn(null); 216 sendUpdateDisclosureBroadcast(); 217 mController.setVisible(true); 218 mExecutor.runAllReady(); 219 220 verifyIndicationMessage(INDICATION_TYPE_DISCLOSURE, mDisclosureGeneric); 221 } 222 223 @Test disclosure_orgOwnedDeviceWithManagedProfile_noOrganizationName()224 public void disclosure_orgOwnedDeviceWithManagedProfile_noOrganizationName() { 225 createController(); 226 mController.setVisible(true); 227 when(mKeyguardStateController.isShowing()).thenReturn(true); 228 when(mDevicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile()).thenReturn(true); 229 when(mUserManager.getProfiles(anyInt())).thenReturn(Collections.singletonList( 230 new UserInfo(10, /* name */ null, /* flags */ FLAG_MANAGED_PROFILE))); 231 when(mDevicePolicyManager.getOrganizationNameForUser(eq(10))).thenReturn(null); 232 sendUpdateDisclosureBroadcast(); 233 mExecutor.runAllReady(); 234 235 verifyIndicationMessage(INDICATION_TYPE_DISCLOSURE, mDisclosureGeneric); 236 } 237 238 @Test disclosure_deviceOwner_withOrganizationName()239 public void disclosure_deviceOwner_withOrganizationName() { 240 createController(); 241 mController.setVisible(true); 242 when(mKeyguardStateController.isShowing()).thenReturn(true); 243 when(mDevicePolicyManager.isDeviceManaged()).thenReturn(true); 244 when(mDevicePolicyManager.getDeviceOwnerOrganizationName()).thenReturn(ORGANIZATION_NAME); 245 sendUpdateDisclosureBroadcast(); 246 mExecutor.runAllReady(); 247 248 verifyIndicationMessage(INDICATION_TYPE_DISCLOSURE, mDisclosureWithOrganization); 249 } 250 251 @Test disclosure_orgOwnedDeviceWithManagedProfile_withOrganizationName()252 public void disclosure_orgOwnedDeviceWithManagedProfile_withOrganizationName() { 253 createController(); 254 mController.setVisible(true); 255 when(mKeyguardStateController.isShowing()).thenReturn(true); 256 when(mDevicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile()).thenReturn(true); 257 when(mUserManager.getProfiles(anyInt())).thenReturn(Collections.singletonList( 258 new UserInfo(10, /* name */ null, FLAG_MANAGED_PROFILE))); 259 when(mDevicePolicyManager.getOrganizationNameForUser(eq(10))).thenReturn(ORGANIZATION_NAME); 260 sendUpdateDisclosureBroadcast(); 261 mExecutor.runAllReady(); 262 263 verifyIndicationMessage(INDICATION_TYPE_DISCLOSURE, mDisclosureWithOrganization); 264 } 265 266 @Test disclosure_updateOnTheFly()267 public void disclosure_updateOnTheFly() { 268 when(mKeyguardStateController.isShowing()).thenReturn(true); 269 when(mDevicePolicyManager.isDeviceManaged()).thenReturn(false); 270 createController(); 271 mController.setVisible(true); 272 273 when(mDevicePolicyManager.isDeviceManaged()).thenReturn(true); 274 when(mDevicePolicyManager.getDeviceOwnerOrganizationName()).thenReturn(null); 275 sendUpdateDisclosureBroadcast(); 276 mExecutor.runAllReady(); 277 278 verifyIndicationMessage(INDICATION_TYPE_DISCLOSURE, mDisclosureGeneric); 279 reset(mRotateTextViewController); 280 281 when(mDevicePolicyManager.isDeviceManaged()).thenReturn(true); 282 when(mDevicePolicyManager.getDeviceOwnerOrganizationName()).thenReturn(ORGANIZATION_NAME); 283 sendUpdateDisclosureBroadcast(); 284 mExecutor.runAllReady(); 285 286 verifyIndicationMessage(INDICATION_TYPE_DISCLOSURE, mDisclosureWithOrganization); 287 reset(mRotateTextViewController); 288 289 when(mDevicePolicyManager.isDeviceManaged()).thenReturn(false); 290 sendUpdateDisclosureBroadcast(); 291 mExecutor.runAllReady(); 292 293 verifyHideIndication(INDICATION_TYPE_DISCLOSURE); 294 } 295 296 @Test disclosure_deviceOwner_financedDeviceWithOrganizationName()297 public void disclosure_deviceOwner_financedDeviceWithOrganizationName() { 298 createController(); 299 mController.setVisible(true); 300 when(mKeyguardStateController.isShowing()).thenReturn(true); 301 when(mDevicePolicyManager.isDeviceManaged()).thenReturn(true); 302 when(mDevicePolicyManager.getDeviceOwnerOrganizationName()).thenReturn(ORGANIZATION_NAME); 303 when(mDevicePolicyManager.isFinancedDevice()).thenReturn(true); 304 // TODO(b/259908270): remove 305 when(mDevicePolicyManager.getDeviceOwnerType(DEVICE_OWNER_COMPONENT)) 306 .thenReturn(DEVICE_OWNER_TYPE_FINANCED); 307 sendUpdateDisclosureBroadcast(); 308 mExecutor.runAllReady(); 309 mController.setVisible(true); 310 311 verifyIndicationMessage(INDICATION_TYPE_DISCLOSURE, mFinancedDisclosureWithOrganization); 312 } 313 314 @Test transientIndication_holdsWakeLock_whenDozing()315 public void transientIndication_holdsWakeLock_whenDozing() { 316 // GIVEN animations are enabled and text is visible 317 mTextView.setAnimationsEnabled(true); 318 createController(); 319 mController.setVisible(true); 320 321 // WHEN transient text is shown 322 mStatusBarStateListener.onDozingChanged(true); 323 mController.showTransientIndication(TEST_STRING_RES); 324 325 // THEN wake lock is held while the animation is running 326 assertTrue("WakeLock expected: HELD, was: RELEASED", mWakeLock.isHeld()); 327 } 328 329 @Test transientIndication_releasesWakeLock_whenDozing()330 public void transientIndication_releasesWakeLock_whenDozing() { 331 // GIVEN animations aren't enabled 332 mTextView.setAnimationsEnabled(false); 333 createController(); 334 mController.setVisible(true); 335 336 // WHEN we show the transient indication 337 mStatusBarStateListener.onDozingChanged(true); 338 mController.showTransientIndication(TEST_STRING_RES); 339 340 // THEN wake lock is RELEASED, not held 341 assertFalse("WakeLock expected: RELEASED, was: HELD", mWakeLock.isHeld()); 342 } 343 344 @Test transientIndication_visibleWhenDozing()345 public void transientIndication_visibleWhenDozing() { 346 createController(); 347 mController.setVisible(true); 348 349 mStatusBarStateListener.onDozingChanged(true); 350 mController.showTransientIndication(TEST_STRING_RES); 351 352 assertThat(mTextView.getText()).isEqualTo( 353 mContext.getResources().getString(TEST_STRING_RES)); 354 assertThat(mTextView.getCurrentTextColor()).isEqualTo(Color.WHITE); 355 assertThat(mTextView.getAlpha()).isEqualTo(1f); 356 } 357 358 @Test transientIndication_visibleWhenDozing_unlessSwipeUp_fromHelp()359 public void transientIndication_visibleWhenDozing_unlessSwipeUp_fromHelp() { 360 createController(); 361 String message = "A message"; 362 363 mController.setVisible(true); 364 mController.getKeyguardCallback().onBiometricHelp( 365 BIOMETRIC_HELP_FACE_NOT_RECOGNIZED, message, 366 BiometricSourceType.FACE); 367 verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE, message); 368 reset(mRotateTextViewController); 369 mStatusBarStateListener.onDozingChanged(true); 370 371 assertThat(mTextView.getText()).isNotEqualTo(message); 372 } 373 374 @Test transientIndication_visibleWhenWokenUp()375 public void transientIndication_visibleWhenWokenUp() { 376 createController(); 377 when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(false); 378 final String message = "helpMsg"; 379 380 // GIVEN screen is off 381 when(mScreenLifecycle.getScreenState()).thenReturn(SCREEN_OFF); 382 383 // WHEN fingeprint help message received 384 mController.setVisible(true); 385 mController.getKeyguardCallback().onBiometricHelp(BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED, 386 message, BiometricSourceType.FINGERPRINT); 387 388 // THEN message isn't shown right away 389 verifyNoMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE); 390 391 // WHEN the screen turns on 392 mScreenObserver.onScreenTurnedOn(); 393 mTestableLooper.processAllMessages(); 394 395 // THEN the message is shown 396 verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE, message); 397 } 398 399 @Test onBiometricHelp_coEx_faceFailure()400 public void onBiometricHelp_coEx_faceFailure() { 401 createController(); 402 403 // GIVEN unlocking with fingerprint is possible and allowed 404 fingerprintUnlockIsPossibleAndAllowed(); 405 406 String message = "A message"; 407 mController.setVisible(true); 408 409 // WHEN there's a face not recognized message 410 mController.getKeyguardCallback().onBiometricHelp( 411 BIOMETRIC_HELP_FACE_NOT_RECOGNIZED, 412 message, 413 BiometricSourceType.FACE); 414 415 // THEN show sequential messages such as: 'face not recognized' and 416 // 'try fingerprint instead' 417 verifyIndicationMessage( 418 INDICATION_TYPE_BIOMETRIC_MESSAGE, 419 mContext.getString(R.string.keyguard_face_failed)); 420 verifyIndicationMessage( 421 INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP, 422 mContext.getString(R.string.keyguard_suggest_fingerprint)); 423 } 424 425 @Test onBiometricHelp_coEx_faceUnavailable()426 public void onBiometricHelp_coEx_faceUnavailable() { 427 createController(); 428 429 // GIVEN unlocking with fingerprint is possible and allowed 430 fingerprintUnlockIsPossibleAndAllowed(); 431 432 String message = "A message"; 433 mController.setVisible(true); 434 435 // WHEN there's a face unavailable message 436 mController.getKeyguardCallback().onBiometricHelp( 437 BIOMETRIC_HELP_FACE_NOT_AVAILABLE, 438 message, 439 BiometricSourceType.FACE); 440 441 // THEN show sequential messages such as: 'face unlock unavailable' and 442 // 'try fingerprint instead' 443 verifyIndicationMessage( 444 INDICATION_TYPE_BIOMETRIC_MESSAGE, 445 message); 446 verifyIndicationMessage( 447 INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP, 448 mContext.getString(R.string.keyguard_suggest_fingerprint)); 449 } 450 451 452 @Test onBiometricHelp_coEx_faceUnavailable_fpNotAllowed()453 public void onBiometricHelp_coEx_faceUnavailable_fpNotAllowed() { 454 createController(); 455 456 // GIVEN unlocking with fingerprint is possible but not allowed 457 setupFingerprintUnlockPossible(true); 458 when(mKeyguardUpdateMonitor.isUnlockingWithFingerprintAllowed()) 459 .thenReturn(false); 460 461 String message = "A message"; 462 mController.setVisible(true); 463 464 // WHEN there's a face unavailable message 465 mController.getKeyguardCallback().onBiometricHelp( 466 BIOMETRIC_HELP_FACE_NOT_AVAILABLE, 467 message, 468 BiometricSourceType.FACE); 469 470 // THEN show sequential messages such as: 'face unlock unavailable' and 471 // 'try fingerprint instead' 472 verifyIndicationMessage( 473 INDICATION_TYPE_BIOMETRIC_MESSAGE, 474 message); 475 verifyIndicationMessage( 476 INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP, 477 mContext.getString(R.string.keyguard_unlock)); 478 } 479 480 @Test onBiometricHelp_coEx_fpFailure_faceAlreadyUnlocked()481 public void onBiometricHelp_coEx_fpFailure_faceAlreadyUnlocked() { 482 createController(); 483 484 // GIVEN face has already unlocked the device 485 when(mKeyguardUpdateMonitor.isCurrentUserUnlockedWithFace()).thenReturn(true); 486 487 String message = "A message"; 488 mController.setVisible(true); 489 490 // WHEN there's a fingerprint not recognized message 491 mController.getKeyguardCallback().onBiometricHelp( 492 BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED, 493 message, 494 BiometricSourceType.FINGERPRINT); 495 496 // THEN show sequential messages such as: 'Unlocked by face' and 497 // 'Swipe up to open' 498 verifyIndicationMessage( 499 INDICATION_TYPE_BIOMETRIC_MESSAGE, 500 mContext.getString(R.string.keyguard_face_successful_unlock)); 501 verifyIndicationMessage( 502 INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP, 503 mContext.getString(R.string.keyguard_unlock)); 504 } 505 506 @Test onBiometricHelp_coEx_fpFailure_trustAgentAlreadyUnlocked()507 public void onBiometricHelp_coEx_fpFailure_trustAgentAlreadyUnlocked() { 508 createController(); 509 510 // GIVEN trust agent has already unlocked the device 511 when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(true); 512 513 String message = "A message"; 514 mController.setVisible(true); 515 516 // WHEN there's a fingerprint not recognized message 517 mController.getKeyguardCallback().onBiometricHelp( 518 BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED, 519 message, 520 BiometricSourceType.FINGERPRINT); 521 522 // THEN show sequential messages such as: 'Kept unlocked by TrustAgent' and 523 // 'Swipe up to open' 524 verifyIndicationMessage( 525 INDICATION_TYPE_BIOMETRIC_MESSAGE, 526 mContext.getString(R.string.keyguard_indication_trust_unlocked)); 527 verifyIndicationMessage( 528 INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP, 529 mContext.getString(R.string.keyguard_unlock)); 530 } 531 532 @Test onBiometricHelp_coEx_fpFailure_trustAgentUnlocked_emptyTrustGrantedMessage()533 public void onBiometricHelp_coEx_fpFailure_trustAgentUnlocked_emptyTrustGrantedMessage() { 534 createController(); 535 536 // GIVEN trust agent has already unlocked the device & trust granted message is empty 537 when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(true); 538 mController.showTrustGrantedMessage(false, ""); 539 540 String message = "A message"; 541 mController.setVisible(true); 542 543 // WHEN there's a fingerprint not recognized message 544 mController.getKeyguardCallback().onBiometricHelp( 545 BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED, 546 message, 547 BiometricSourceType.FINGERPRINT); 548 549 // THEN show action to unlock (ie: 'Swipe up to open') 550 verifyNoMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE); 551 verifyIndicationMessage( 552 INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP, 553 mContext.getString(R.string.keyguard_unlock)); 554 } 555 556 @Test transientIndication_visibleWhenDozing_unlessSwipeUp_fromError()557 public void transientIndication_visibleWhenDozing_unlessSwipeUp_fromError() { 558 createController(); 559 String message = mContext.getString(R.string.keyguard_unlock); 560 561 mController.setVisible(true); 562 mController.getKeyguardCallback().onBiometricError(FACE_ERROR_TIMEOUT, 563 "A message", BiometricSourceType.FACE); 564 565 verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE, message); 566 mStatusBarStateListener.onDozingChanged(true); 567 568 assertThat(mTextView.getText()).isNotEqualTo(message); 569 } 570 571 @Test transientIndication_visibleWhenDozing_ignoresFingerprintErrorMsg()572 public void transientIndication_visibleWhenDozing_ignoresFingerprintErrorMsg() { 573 createController(); 574 mController.setVisible(true); 575 reset(mRotateTextViewController); 576 577 // WHEN a fingerprint error user cancelled message is received 578 mController.getKeyguardCallback().onBiometricError( 579 BiometricFingerprintConstants.FINGERPRINT_ERROR_USER_CANCELED, "foo", 580 BiometricSourceType.FINGERPRINT); 581 582 // THEN no message is shown 583 verifyNoMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE); 584 verifyNoMessage(INDICATION_TYPE_TRANSIENT); 585 } 586 587 @Test transientIndication_swipeUpToRetry()588 public void transientIndication_swipeUpToRetry() { 589 createController(); 590 String message = mContext.getString(R.string.keyguard_retry); 591 when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(true); 592 when(mKeyguardUpdateMonitor.isFaceEnabledAndEnrolled()).thenReturn(true); 593 when(mKeyguardUpdateMonitor.getIsFaceAuthenticated()).thenReturn(false); 594 595 mController.setVisible(true); 596 mController.getKeyguardCallback().onBiometricError(FACE_ERROR_TIMEOUT, 597 "A message", BiometricSourceType.FACE); 598 599 verify(mStatusBarKeyguardViewManager).setKeyguardMessage(eq(message), any(), any()); 600 } 601 602 @Test transientIndication_swipeUpToRetry_faceAuthenticated()603 public void transientIndication_swipeUpToRetry_faceAuthenticated() { 604 createController(); 605 String message = mContext.getString(R.string.keyguard_retry); 606 when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(true); 607 when(mKeyguardUpdateMonitor.getIsFaceAuthenticated()).thenReturn(true); 608 when(mKeyguardUpdateMonitor.isFaceEnabledAndEnrolled()).thenReturn(true); 609 610 mController.setVisible(true); 611 mController.getKeyguardCallback().onBiometricError(FACE_ERROR_TIMEOUT, 612 "A message", BiometricSourceType.FACE); 613 614 verify(mStatusBarKeyguardViewManager, never()).setKeyguardMessage( 615 eq(message), any(), any()); 616 } 617 618 @Test faceErrorTimeout_whenFingerprintEnrolled_doesNotShowMessage()619 public void faceErrorTimeout_whenFingerprintEnrolled_doesNotShowMessage() { 620 createController(); 621 fingerprintUnlockIsPossibleAndAllowed(); 622 String message = "A message"; 623 624 mController.setVisible(true); 625 mController.getKeyguardCallback().onBiometricError( 626 FACE_ERROR_TIMEOUT, message, BiometricSourceType.FACE); 627 verifyNoMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE); 628 } 629 630 @Test sendFaceHelpMessages_fingerprintEnrolled()631 public void sendFaceHelpMessages_fingerprintEnrolled() { 632 createController(); 633 mController.mCoExAcquisitionMsgIdsToShowCallback.accept( 634 Set.of( 635 BiometricFaceConstants.FACE_ACQUIRED_MOUTH_COVERING_DETECTED, 636 BiometricFaceConstants.FACE_ACQUIRED_DARK_GLASSES_DETECTED 637 ) 638 ); 639 640 // GIVEN unlocking with fingerprint is possible and allowed 641 fingerprintUnlockIsPossibleAndAllowed(); 642 643 // WHEN help messages received that are allowed to show 644 final String helpString = "helpString"; 645 final int[] msgIds = new int[]{ 646 BiometricFaceConstants.FACE_ACQUIRED_MOUTH_COVERING_DETECTED, 647 BiometricFaceConstants.FACE_ACQUIRED_DARK_GLASSES_DETECTED 648 }; 649 Set<CharSequence> messages = new HashSet<>(); 650 for (int msgId : msgIds) { 651 final String message = helpString + msgId; 652 messages.add(message); 653 mKeyguardUpdateMonitorCallback.onBiometricHelp( 654 msgId, message, BiometricSourceType.FACE); 655 } 656 657 // THEN FACE_ACQUIRED_MOUTH_COVERING_DETECTED and DARK_GLASSES help messages shown 658 verifyIndicationMessages(INDICATION_TYPE_BIOMETRIC_MESSAGE, 659 messages); 660 } 661 662 @Test doNotSendMostFaceHelpMessages_fingerprintEnrolled()663 public void doNotSendMostFaceHelpMessages_fingerprintEnrolled() { 664 createController(); 665 666 // GIVEN unlocking with fingerprint is possible and allowed 667 fingerprintUnlockIsPossibleAndAllowed(); 668 669 // WHEN help messages received that aren't supposed to show 670 final String helpString = "helpString"; 671 final int[] msgIds = new int[]{ 672 BiometricFaceConstants.FACE_ACQUIRED_FACE_OBSCURED, 673 BiometricFaceConstants.FACE_ACQUIRED_TOO_RIGHT, 674 BiometricFaceConstants.FACE_ACQUIRED_TOO_LEFT, 675 BiometricFaceConstants.FACE_ACQUIRED_TOO_HIGH, 676 BiometricFaceConstants.FACE_ACQUIRED_TOO_LOW, 677 BiometricFaceConstants.FACE_ACQUIRED_TOO_BRIGHT 678 }; 679 for (int msgId : msgIds) { 680 mKeyguardUpdateMonitorCallback.onBiometricHelp( 681 msgId, helpString + msgId, BiometricSourceType.FACE); 682 } 683 684 // THEN no messages shown 685 verifyNoMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE); 686 } 687 688 @Test sendAllFaceHelpMessages_fingerprintNotEnrolled()689 public void sendAllFaceHelpMessages_fingerprintNotEnrolled() { 690 createController(); 691 692 // GIVEN fingerprint NOT possible 693 fingerprintUnlockIsNotPossible(); 694 695 // WHEN help messages received 696 final Set<CharSequence> helpStrings = new HashSet<>(); 697 final String helpString = "helpString"; 698 final int[] msgIds = new int[]{ 699 BiometricFaceConstants.FACE_ACQUIRED_FACE_OBSCURED, 700 BiometricFaceConstants.FACE_ACQUIRED_DARK_GLASSES_DETECTED, 701 BiometricFaceConstants.FACE_ACQUIRED_TOO_RIGHT, 702 BiometricFaceConstants.FACE_ACQUIRED_TOO_LEFT, 703 BiometricFaceConstants.FACE_ACQUIRED_TOO_HIGH, 704 BiometricFaceConstants.FACE_ACQUIRED_TOO_LOW, 705 BiometricFaceConstants.FACE_ACQUIRED_TOO_BRIGHT 706 }; 707 for (int msgId : msgIds) { 708 final String numberedHelpString = helpString + msgId; 709 mKeyguardUpdateMonitorCallback.onBiometricHelp( 710 msgId, numberedHelpString, BiometricSourceType.FACE); 711 helpStrings.add(numberedHelpString); 712 } 713 714 // THEN message shown for each call 715 verifyIndicationMessages(INDICATION_TYPE_BIOMETRIC_MESSAGE, helpStrings); 716 } 717 718 @Test sendTooDarkFaceHelpMessages_onTimeout_noFpEnrolled()719 public void sendTooDarkFaceHelpMessages_onTimeout_noFpEnrolled() { 720 createController(); 721 722 // GIVEN fingerprint not possible 723 fingerprintUnlockIsNotPossible(); 724 725 // WHEN help message received and deferred message is valid 726 final String helpString = "helpMsg"; 727 when(mFaceHelpMessageDeferral.getDeferredMessage()).thenReturn(helpString); 728 when(mFaceHelpMessageDeferral.shouldDefer(FACE_ACQUIRED_TOO_DARK)).thenReturn(true); 729 mKeyguardUpdateMonitorCallback.onBiometricHelp( 730 BiometricFaceConstants.FACE_ACQUIRED_TOO_DARK, 731 helpString, 732 BiometricSourceType.FACE 733 ); 734 735 // THEN help message not shown yet 736 verifyNoMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE); 737 738 // WHEN face timeout error received 739 mKeyguardUpdateMonitorCallback.onBiometricError(FACE_ERROR_TIMEOUT, "face timeout", 740 BiometricSourceType.FACE); 741 742 // THEN the low light message shows with suggestion to swipe up to unlock 743 verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE, helpString); 744 verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP, 745 mContext.getString(R.string.keyguard_unlock)); 746 } 747 748 @Test sendTooDarkFaceHelpMessages_onTimeout_fingerprintEnrolled()749 public void sendTooDarkFaceHelpMessages_onTimeout_fingerprintEnrolled() { 750 createController(); 751 752 // GIVEN unlocking with fingerprint is possible and allowed 753 fingerprintUnlockIsPossibleAndAllowed(); 754 755 // WHEN help message received and deferredMessage is valid 756 final String helpString = "helpMsg"; 757 when(mFaceHelpMessageDeferral.getDeferredMessage()).thenReturn(helpString); 758 when(mFaceHelpMessageDeferral.shouldDefer(FACE_ACQUIRED_TOO_DARK)).thenReturn(true); 759 mKeyguardUpdateMonitorCallback.onBiometricHelp( 760 BiometricFaceConstants.FACE_ACQUIRED_TOO_DARK, 761 helpString, 762 BiometricSourceType.FACE 763 ); 764 765 // THEN help message not shown yet 766 verifyNoMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE); 767 768 // WHEN face timeout error received 769 mKeyguardUpdateMonitorCallback.onBiometricError(FACE_ERROR_TIMEOUT, "face timeout", 770 BiometricSourceType.FACE); 771 772 // THEN the low light message shows and suggests trying fingerprint 773 verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE, helpString); 774 verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP, 775 mContext.getString(R.string.keyguard_suggest_fingerprint)); 776 } 777 778 @Test onRefreshBatteryInfo_computesChargingTime()779 public void onRefreshBatteryInfo_computesChargingTime() throws RemoteException { 780 createController(); 781 BatteryStatus status = new BatteryStatus(BatteryManager.BATTERY_STATUS_CHARGING, 782 80 /* level */, BatteryManager.BATTERY_PLUGGED_WIRELESS, 100 /* health */, 783 0 /* maxChargingWattage */, true /* present */); 784 785 mController.getKeyguardCallback().onRefreshBatteryInfo(status); 786 verify(mIBatteryStats).computeChargeTimeRemaining(); 787 } 788 789 @Test onRefreshBatteryInfo_computesChargingTime_onlyWhenCharging()790 public void onRefreshBatteryInfo_computesChargingTime_onlyWhenCharging() 791 throws RemoteException { 792 createController(); 793 BatteryStatus status = new BatteryStatus(BatteryManager.BATTERY_STATUS_CHARGING, 794 80 /* level */, 0 /* plugged */, 100 /* health */, 795 0 /* maxChargingWattage */, true /* present */); 796 797 mController.getKeyguardCallback().onRefreshBatteryInfo(status); 798 verify(mIBatteryStats, never()).computeChargeTimeRemaining(); 799 } 800 801 /** 802 * Regression test. 803 * We should not make calls to the system_process when updating the doze state. 804 */ 805 @Test setDozing_noIBatteryCalls()806 public void setDozing_noIBatteryCalls() throws RemoteException { 807 createController(); 808 mController.setVisible(true); 809 mStatusBarStateListener.onDozingChanged(true); 810 mStatusBarStateListener.onDozingChanged(false); 811 verify(mIBatteryStats, never()).computeChargeTimeRemaining(); 812 } 813 814 @Test registersKeyguardStateCallback()815 public void registersKeyguardStateCallback() { 816 createController(); 817 verify(mKeyguardStateController).addCallback(any()); 818 } 819 820 @Test unlockMethodCache_listenerUpdatesPluggedIndication()821 public void unlockMethodCache_listenerUpdatesPluggedIndication() { 822 createController(); 823 when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(true); 824 mController.setPowerPluggedIn(true); 825 mController.setVisible(true); 826 827 verifyIndicationMessage( 828 INDICATION_TYPE_TRUST, 829 mContext.getString(R.string.keyguard_indication_trust_unlocked)); 830 } 831 832 @Test onRefreshBatteryInfo_chargingWithLongLife_presentChargingLimited()833 public void onRefreshBatteryInfo_chargingWithLongLife_presentChargingLimited() { 834 createController(); 835 BatteryStatus status = new BatteryStatus(BatteryManager.BATTERY_STATUS_CHARGING, 836 80 /* level */, BatteryManager.BATTERY_PLUGGED_AC, 837 BatteryManager.CHARGING_POLICY_ADAPTIVE_LONGLIFE, 0 /* maxChargingWattage */, 838 true /* present */); 839 840 mController.getKeyguardCallback().onRefreshBatteryInfo(status); 841 mController.setVisible(true); 842 843 verifyIndicationMessage( 844 INDICATION_TYPE_BATTERY, 845 mContext.getString( 846 R.string.keyguard_plugged_in_charging_limited, 847 NumberFormat.getPercentInstance().format(80 / 100f))); 848 } 849 850 @Test onRefreshBatteryInfo_fullChargedWithLongLife_presentChargingLimited()851 public void onRefreshBatteryInfo_fullChargedWithLongLife_presentChargingLimited() { 852 createController(); 853 BatteryStatus status = new BatteryStatus(BatteryManager.BATTERY_STATUS_CHARGING, 854 100 /* level */, BatteryManager.BATTERY_PLUGGED_AC, 855 BatteryManager.CHARGING_POLICY_ADAPTIVE_LONGLIFE, 0 /* maxChargingWattage */, 856 true /* present */); 857 858 mController.getKeyguardCallback().onRefreshBatteryInfo(status); 859 mController.setVisible(true); 860 861 verifyIndicationMessage( 862 INDICATION_TYPE_BATTERY, 863 mContext.getString( 864 R.string.keyguard_plugged_in_charging_limited, 865 NumberFormat.getPercentInstance().format(100 / 100f))); 866 } 867 868 @Test onRefreshBatteryInfo_fullChargedWithoutLongLife_presentCharged()869 public void onRefreshBatteryInfo_fullChargedWithoutLongLife_presentCharged() { 870 createController(); 871 BatteryStatus status = new BatteryStatus(BatteryManager.BATTERY_STATUS_CHARGING, 872 100 /* level */, BatteryManager.BATTERY_PLUGGED_AC, 873 BatteryManager.CHARGING_POLICY_DEFAULT, 0 /* maxChargingWattage */, 874 true /* present */); 875 876 mController.getKeyguardCallback().onRefreshBatteryInfo(status); 877 mController.setVisible(true); 878 879 verifyIndicationMessage( 880 INDICATION_TYPE_BATTERY, 881 mContext.getString(R.string.keyguard_charged)); 882 } 883 884 @Test onRefreshBatteryInfo_dozing_dischargingWithLongLife_presentBatteryPercentage()885 public void onRefreshBatteryInfo_dozing_dischargingWithLongLife_presentBatteryPercentage() { 886 createController(); 887 mController.setVisible(true); 888 BatteryStatus status = new BatteryStatus(BatteryManager.BATTERY_STATUS_DISCHARGING, 889 90 /* level */, 0 /* plugged */, BatteryManager.CHARGING_POLICY_ADAPTIVE_LONGLIFE, 890 0 /* maxChargingWattage */, true /* present */); 891 892 mController.getKeyguardCallback().onRefreshBatteryInfo(status); 893 mStatusBarStateListener.onDozingChanged(true); 894 895 String percentage = NumberFormat.getPercentInstance().format(90 / 100f); 896 assertThat(mTextView.getText()).isEqualTo(percentage); 897 } 898 899 @Test onRequireUnlockForNfc_showsRequireUnlockForNfcIndication()900 public void onRequireUnlockForNfc_showsRequireUnlockForNfcIndication() { 901 createController(); 902 mController.setVisible(true); 903 String message = mContext.getString(R.string.require_unlock_for_nfc); 904 mController.getKeyguardCallback().onRequireUnlockForNfc(); 905 906 verifyTransientMessage(message); 907 } 908 909 @Test testEmptyOwnerInfoHidesIndicationArea()910 public void testEmptyOwnerInfoHidesIndicationArea() { 911 createController(); 912 913 // GIVEN the owner info is set to an empty string & keyguard is showing 914 when(mKeyguardStateController.isShowing()).thenReturn(true); 915 when(mLockPatternUtils.getDeviceOwnerInfo()).thenReturn(""); 916 917 // WHEN asked to update the indication area 918 mController.setVisible(true); 919 mExecutor.runAllReady(); 920 921 // THEN the owner info should be hidden 922 verifyHideIndication(INDICATION_TYPE_OWNER_INFO); 923 } 924 925 @Test testOnKeyguardShowingChanged_notShowing_resetsMessages()926 public void testOnKeyguardShowingChanged_notShowing_resetsMessages() { 927 createController(); 928 929 // GIVEN keyguard isn't showing 930 when(mKeyguardStateController.isShowing()).thenReturn(false); 931 932 // WHEN keyguard showing changed called 933 mKeyguardStateControllerCallback.onKeyguardShowingChanged(); 934 935 // THEN messages are reset 936 verify(mRotateTextViewController).clearMessages(); 937 assertThat(mTextView.getText()).isEqualTo(""); 938 } 939 940 @Test testOnKeyguardShowingChanged_showing_updatesPersistentMessages()941 public void testOnKeyguardShowingChanged_showing_updatesPersistentMessages() { 942 createController(); 943 mController.setVisible(true); 944 mExecutor.runAllReady(); 945 reset(mRotateTextViewController); 946 947 // GIVEN keyguard is showing and not dozing 948 when(mKeyguardStateController.isShowing()).thenReturn(true); 949 mController.setVisible(true); 950 mExecutor.runAllReady(); 951 reset(mRotateTextViewController); 952 953 // WHEN keyguard showing changed called 954 mKeyguardStateControllerCallback.onKeyguardShowingChanged(); 955 mExecutor.runAllReady(); 956 957 // THEN persistent messages are updated (in this case, most messages are hidden since 958 // no info is provided) - verify that this happens 959 verify(mRotateTextViewController).hideIndication(INDICATION_TYPE_DISCLOSURE); 960 verify(mRotateTextViewController).hideIndication(INDICATION_TYPE_OWNER_INFO); 961 verify(mRotateTextViewController).hideIndication(INDICATION_TYPE_BATTERY); 962 verify(mRotateTextViewController).hideIndication(INDICATION_TYPE_TRUST); 963 verify(mRotateTextViewController).hideIndication(INDICATION_TYPE_ALIGNMENT); 964 verify(mRotateTextViewController).hideIndication(INDICATION_TYPE_LOGOUT); 965 } 966 967 @Test onTrustGrantedMessageDoesNotShowUntilTrustGranted()968 public void onTrustGrantedMessageDoesNotShowUntilTrustGranted() { 969 createController(); 970 mController.setVisible(true); 971 reset(mRotateTextViewController); 972 973 // GIVEN a trust granted message but trust isn't granted 974 final String trustGrantedMsg = "testing trust granted message"; 975 mController.getKeyguardCallback().onTrustGrantedForCurrentUser( 976 false, false, new TrustGrantFlags(0), trustGrantedMsg); 977 978 verifyHideIndication(INDICATION_TYPE_TRUST); 979 980 // WHEN trust is granted 981 when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(true); 982 mKeyguardUpdateMonitorCallback.onTrustChanged(getCurrentUser()); 983 984 // THEN verify the trust granted message shows 985 verifyIndicationMessage( 986 INDICATION_TYPE_TRUST, 987 trustGrantedMsg); 988 } 989 990 @Test onTrustGrantedMessageShowsOnTrustGranted()991 public void onTrustGrantedMessageShowsOnTrustGranted() { 992 createController(); 993 mController.setVisible(true); 994 995 // GIVEN trust is granted 996 when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(true); 997 998 // WHEN the showTrustGranted method is called 999 final String trustGrantedMsg = "testing trust granted message"; 1000 mController.getKeyguardCallback().onTrustGrantedForCurrentUser( 1001 false, false, new TrustGrantFlags(0), trustGrantedMsg); 1002 1003 // THEN verify the trust granted message shows 1004 verifyIndicationMessage( 1005 INDICATION_TYPE_TRUST, 1006 trustGrantedMsg); 1007 } 1008 1009 @Test onTrustGrantedMessage_nullMessage_showsDefaultMessage()1010 public void onTrustGrantedMessage_nullMessage_showsDefaultMessage() { 1011 createController(); 1012 mController.setVisible(true); 1013 1014 // GIVEN trust is granted 1015 when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(true); 1016 1017 // WHEN the showTrustGranted method is called with a null message 1018 mController.getKeyguardCallback().onTrustGrantedForCurrentUser( 1019 false, false, new TrustGrantFlags(0), null); 1020 1021 // THEN verify the default trust granted message shows 1022 verifyIndicationMessage( 1023 INDICATION_TYPE_TRUST, 1024 getContext().getString(R.string.keyguard_indication_trust_unlocked)); 1025 } 1026 1027 @Test onTrustGrantedMessage_emptyString_showsNoMessage()1028 public void onTrustGrantedMessage_emptyString_showsNoMessage() { 1029 createController(); 1030 mController.setVisible(true); 1031 1032 // GIVEN trust is granted 1033 when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(true); 1034 1035 // WHEN the showTrustGranted method is called with an EMPTY string 1036 mController.getKeyguardCallback().onTrustGrantedForCurrentUser( 1037 false, false, new TrustGrantFlags(0), ""); 1038 1039 // THEN verify NO trust message is shown 1040 verifyNoMessage(INDICATION_TYPE_TRUST); 1041 } 1042 1043 @Test coEx_faceSuccess_showsPressToOpen()1044 public void coEx_faceSuccess_showsPressToOpen() { 1045 // GIVEN bouncer isn't showing, can skip bouncer, udfps is supported, no a11y enabled 1046 when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(false); 1047 when(mKeyguardUpdateMonitor.getUserCanSkipBouncer(getCurrentUser())) 1048 .thenReturn(true); 1049 when(mKeyguardUpdateMonitor.isUdfpsSupported()).thenReturn(true); 1050 when(mAccessibilityManager.isEnabled()).thenReturn(false); 1051 when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(false); 1052 createController(); 1053 mController.setVisible(true); 1054 1055 // WHEN face auth succeeds 1056 when(mKeyguardUpdateMonitor.getIsFaceAuthenticated()).thenReturn(true); 1057 mController.getKeyguardCallback().onBiometricAuthenticated(0, 1058 BiometricSourceType.FACE, false); 1059 1060 // THEN 'face unlocked' then 'press unlock icon to open' message show 1061 String unlockedByFace = mContext.getString(R.string.keyguard_face_successful_unlock); 1062 verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE, unlockedByFace); 1063 String pressToOpen = mContext.getString(R.string.keyguard_unlock_press); 1064 verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP, pressToOpen); 1065 } 1066 1067 @Test coEx_faceSuccess_touchExplorationEnabled_showsFaceUnlockedSwipeToOpen()1068 public void coEx_faceSuccess_touchExplorationEnabled_showsFaceUnlockedSwipeToOpen() { 1069 // GIVEN bouncer isn't showing, can skip bouncer, udfps is supported, a11y enabled 1070 when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(false); 1071 when(mKeyguardUpdateMonitor.getUserCanSkipBouncer(getCurrentUser())) 1072 .thenReturn(true); 1073 when(mKeyguardUpdateMonitor.isUdfpsSupported()).thenReturn(true); 1074 when(mAccessibilityManager.isEnabled()).thenReturn(true); 1075 when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(true); 1076 createController(); 1077 mController.setVisible(true); 1078 1079 // WHEN face authenticated 1080 when(mKeyguardUpdateMonitor.getIsFaceAuthenticated()).thenReturn(true); 1081 mController.getKeyguardCallback().onBiometricAuthenticated(0, 1082 BiometricSourceType.FACE, false); 1083 1084 // THEN show 'face unlocked' and 'swipe up to open' messages 1085 String unlockedByFace = mContext.getString(R.string.keyguard_face_successful_unlock); 1086 verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE, unlockedByFace); 1087 String swipeUpToOpen = mContext.getString(R.string.keyguard_unlock); 1088 verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP, swipeUpToOpen); 1089 } 1090 1091 @Test coEx_faceSuccess_a11yEnabled_showsFaceUnlockedSwipeToOpen()1092 public void coEx_faceSuccess_a11yEnabled_showsFaceUnlockedSwipeToOpen() { 1093 // GIVEN bouncer isn't showing, can skip bouncer, udfps is supported, a11y is enabled 1094 when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(false); 1095 when(mKeyguardUpdateMonitor.getUserCanSkipBouncer(getCurrentUser())) 1096 .thenReturn(true); 1097 when(mKeyguardUpdateMonitor.isUdfpsSupported()).thenReturn(true); 1098 when(mAccessibilityManager.isEnabled()).thenReturn(true); 1099 createController(); 1100 mController.setVisible(true); 1101 1102 // WHEN face auth is successful 1103 when(mKeyguardUpdateMonitor.getIsFaceAuthenticated()).thenReturn(true); 1104 mController.getKeyguardCallback().onBiometricAuthenticated(0, 1105 BiometricSourceType.FACE, false); 1106 1107 // THEN show 'face unlocked' and 'swipe up to open' messages 1108 String unlockedByFace = mContext.getString(R.string.keyguard_face_successful_unlock); 1109 verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE, unlockedByFace); 1110 String swipeUpToOpen = mContext.getString(R.string.keyguard_unlock); 1111 verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP, swipeUpToOpen); 1112 } 1113 1114 @Test faceOnly_faceSuccess_showsFaceUnlockedSwipeToOpen()1115 public void faceOnly_faceSuccess_showsFaceUnlockedSwipeToOpen() { 1116 // GIVEN bouncer isn't showing, can skip bouncer, no udfps supported 1117 when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(false); 1118 when(mKeyguardUpdateMonitor.getUserCanSkipBouncer(getCurrentUser())) 1119 .thenReturn(true); 1120 when(mKeyguardUpdateMonitor.isUdfpsSupported()).thenReturn(false); 1121 createController(); 1122 mController.setVisible(true); 1123 1124 // WHEN face auth is successful 1125 when(mKeyguardUpdateMonitor.getIsFaceAuthenticated()).thenReturn(true); 1126 mController.getKeyguardCallback().onBiometricAuthenticated(0, 1127 BiometricSourceType.FACE, false); 1128 1129 // THEN show 'face unlocked' and 'swipe up to open' messages 1130 String unlockedByFace = mContext.getString(R.string.keyguard_face_successful_unlock); 1131 verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE, unlockedByFace); 1132 String swipeUpToOpen = mContext.getString(R.string.keyguard_unlock); 1133 verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP, swipeUpToOpen); 1134 } 1135 1136 @Test udfpsOnly_a11yEnabled_showsSwipeToOpen()1137 public void udfpsOnly_a11yEnabled_showsSwipeToOpen() { 1138 // GIVEN bouncer isn't showing, can skip bouncer, udfps is supported, a11y is enabled 1139 when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(false); 1140 when(mKeyguardUpdateMonitor.getUserCanSkipBouncer(getCurrentUser())) 1141 .thenReturn(true); 1142 when(mKeyguardUpdateMonitor.isUdfpsSupported()).thenReturn(true); 1143 when(mAccessibilityManager.isEnabled()).thenReturn(true); 1144 when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(true); 1145 createController(); 1146 mController.setVisible(true); 1147 1148 // WHEN showActionToUnlock 1149 mController.showActionToUnlock(); 1150 1151 // THEN show 'swipe up to open' message 1152 String swipeToOpen = mContext.getString(R.string.keyguard_unlock); 1153 verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE, swipeToOpen); 1154 } 1155 1156 @Test udfpsOnly_showsPressToOpen()1157 public void udfpsOnly_showsPressToOpen() { 1158 // GIVEN bouncer isn't showing, udfps is supported, a11y is NOT enabled, can skip bouncer 1159 when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(false); 1160 when(mKeyguardUpdateMonitor.getUserCanSkipBouncer(getCurrentUser())) 1161 .thenReturn(true); 1162 when(mKeyguardUpdateMonitor.isUdfpsSupported()).thenReturn(true); 1163 when(mAccessibilityManager.isEnabled()).thenReturn(false); 1164 when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(false); 1165 createController(); 1166 mController.setVisible(true); 1167 1168 // WHEN showActionToUnlock 1169 mController.showActionToUnlock(); 1170 1171 // THEN show 'press unlock icon to open' message 1172 String pressToOpen = mContext.getString(R.string.keyguard_unlock_press); 1173 verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE, pressToOpen); 1174 } 1175 1176 @Test canSkipBouncer_noSecurity_showSwipeToUnlockHint()1177 public void canSkipBouncer_noSecurity_showSwipeToUnlockHint() { 1178 // GIVEN bouncer isn't showing, can skip bouncer, no security (udfps isn't supported, 1179 // face wasn't authenticated) 1180 when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(false); 1181 when(mKeyguardUpdateMonitor.getUserCanSkipBouncer(getCurrentUser())) 1182 .thenReturn(true); 1183 when(mKeyguardUpdateMonitor.isUdfpsSupported()).thenReturn(false); 1184 createController(); 1185 mController.setVisible(true); 1186 1187 // WHEN showActionToUnlock 1188 mController.showActionToUnlock(); 1189 1190 // THEN show 'swipe up to open' message 1191 String swipeToOpen = mContext.getString(R.string.keyguard_unlock); 1192 verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE, swipeToOpen); 1193 } 1194 1195 @Test cannotSkipBouncer_showSwipeToUnlockHint()1196 public void cannotSkipBouncer_showSwipeToUnlockHint() { 1197 // GIVEN bouncer isn't showing and cannot skip bouncer 1198 when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(false); 1199 when(mKeyguardUpdateMonitor.getUserCanSkipBouncer(getCurrentUser())) 1200 .thenReturn(false); 1201 createController(); 1202 mController.setVisible(true); 1203 1204 // WHEN showActionToUnlock 1205 mController.showActionToUnlock(); 1206 1207 // THEN show 'swipe up to open' message 1208 String swipeToOpen = mContext.getString(R.string.keyguard_unlock); 1209 verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE, swipeToOpen); 1210 } 1211 1212 @Test faceOnAcquired_processFrame()1213 public void faceOnAcquired_processFrame() { 1214 createController(); 1215 1216 // WHEN face sends an acquired message 1217 final int acquireInfo = 1; 1218 mKeyguardUpdateMonitorCallback.onBiometricAcquired(BiometricSourceType.FACE, acquireInfo); 1219 1220 // THEN face help message deferral should process the acquired frame 1221 verify(mFaceHelpMessageDeferral).processFrame(acquireInfo); 1222 } 1223 1224 @Test fingerprintOnAcquired_noProcessFrame()1225 public void fingerprintOnAcquired_noProcessFrame() { 1226 createController(); 1227 1228 // WHEN fingerprint sends an acquired message 1229 mKeyguardUpdateMonitorCallback.onBiometricAcquired(BiometricSourceType.FINGERPRINT, 1); 1230 1231 // THEN face help message deferral should NOT process any acquired frames 1232 verify(mFaceHelpMessageDeferral, never()).processFrame(anyInt()); 1233 } 1234 1235 @Test onBiometricHelp_fingerprint_faceHelpMessageDeferralDoesNothing()1236 public void onBiometricHelp_fingerprint_faceHelpMessageDeferralDoesNothing() { 1237 createController(); 1238 1239 // WHEN fingerprint sends an onBiometricHelp 1240 mKeyguardUpdateMonitorCallback.onBiometricHelp( 1241 1, 1242 "placeholder", 1243 BiometricSourceType.FINGERPRINT); 1244 1245 // THEN face help message deferral is NOT: reset, updated, or checked for shouldDefer 1246 verify(mFaceHelpMessageDeferral, never()).reset(); 1247 verify(mFaceHelpMessageDeferral, never()).updateMessage(anyInt(), anyString()); 1248 verify(mFaceHelpMessageDeferral, never()).shouldDefer(anyInt()); 1249 } 1250 1251 @Test onBiometricFailed_resetFaceHelpMessageDeferral()1252 public void onBiometricFailed_resetFaceHelpMessageDeferral() { 1253 createController(); 1254 1255 // WHEN face sends an onBiometricAuthFailed 1256 mKeyguardUpdateMonitorCallback.onBiometricAuthFailed(BiometricSourceType.FACE); 1257 1258 // THEN face help message deferral is reset 1259 verify(mFaceHelpMessageDeferral).reset(); 1260 } 1261 1262 @Test onBiometricError_resetFaceHelpMessageDeferral()1263 public void onBiometricError_resetFaceHelpMessageDeferral() { 1264 createController(); 1265 1266 // WHEN face has an error 1267 mKeyguardUpdateMonitorCallback.onBiometricError(4, "string", 1268 BiometricSourceType.FACE); 1269 1270 // THEN face help message deferral is reset 1271 verify(mFaceHelpMessageDeferral).reset(); 1272 } 1273 1274 @Test onBiometricHelp_faceAcquiredInfo_faceHelpMessageDeferral()1275 public void onBiometricHelp_faceAcquiredInfo_faceHelpMessageDeferral() { 1276 createController(); 1277 1278 // WHEN face sends an onBiometricHelp BIOMETRIC_HELP_FACE_NOT_RECOGNIZED 1279 final int msgId = 1; 1280 final String helpString = "test"; 1281 mKeyguardUpdateMonitorCallback.onBiometricHelp( 1282 msgId, 1283 "test", 1284 BiometricSourceType.FACE); 1285 1286 // THEN face help message deferral is NOT reset and message IS updated 1287 verify(mFaceHelpMessageDeferral, never()).reset(); 1288 verify(mFaceHelpMessageDeferral).updateMessage(msgId, helpString); 1289 } 1290 1291 1292 @Test onBiometricError_faceLockedOutFirstTime_showsThePassedInMessage()1293 public void onBiometricError_faceLockedOutFirstTime_showsThePassedInMessage() { 1294 createController(); 1295 onFaceLockoutError("first lockout"); 1296 1297 verifyIndicationShown(INDICATION_TYPE_BIOMETRIC_MESSAGE, "first lockout"); 1298 } 1299 1300 @Test onBiometricError_faceLockedOutFirstTimeAndFpAllowed_showsTheFpFollowupMessage()1301 public void onBiometricError_faceLockedOutFirstTimeAndFpAllowed_showsTheFpFollowupMessage() { 1302 createController(); 1303 fingerprintUnlockIsPossibleAndAllowed(); 1304 onFaceLockoutError("first lockout"); 1305 1306 verifyIndicationShown(INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP, 1307 mContext.getString(R.string.keyguard_suggest_fingerprint)); 1308 } 1309 1310 @Test onBiometricError_faceLockedOutFirstTimeAndFpNotAllowed_showsDefaultFollowup()1311 public void onBiometricError_faceLockedOutFirstTimeAndFpNotAllowed_showsDefaultFollowup() { 1312 createController(); 1313 fingerprintUnlockIsNotPossible(); 1314 onFaceLockoutError("first lockout"); 1315 1316 verifyIndicationShown(INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP, 1317 mContext.getString(R.string.keyguard_unlock)); 1318 } 1319 1320 @Test onBiometricError_faceLockedOutSecondTimeInSession_showsUnavailableMessage()1321 public void onBiometricError_faceLockedOutSecondTimeInSession_showsUnavailableMessage() { 1322 createController(); 1323 onFaceLockoutError("first lockout"); 1324 clearInvocations(mRotateTextViewController); 1325 1326 onFaceLockoutError("second lockout"); 1327 1328 verifyIndicationShown(INDICATION_TYPE_BIOMETRIC_MESSAGE, 1329 mContext.getString(R.string.keyguard_face_unlock_unavailable)); 1330 } 1331 1332 @Test onBiometricError_faceLockedOutSecondTimeOnBouncer_showsUnavailableMessage()1333 public void onBiometricError_faceLockedOutSecondTimeOnBouncer_showsUnavailableMessage() { 1334 createController(); 1335 onFaceLockoutError("first lockout"); 1336 clearInvocations(mRotateTextViewController); 1337 when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(true); 1338 1339 onFaceLockoutError("second lockout"); 1340 1341 verify(mStatusBarKeyguardViewManager) 1342 .setKeyguardMessage( 1343 eq(mContext.getString(R.string.keyguard_face_unlock_unavailable)), 1344 any(), 1345 any() 1346 ); 1347 } 1348 1349 @Test onBiometricError_faceLockedOutSecondTimeButUdfpsActive_showsNoMessage()1350 public void onBiometricError_faceLockedOutSecondTimeButUdfpsActive_showsNoMessage() { 1351 createController(); 1352 onFaceLockoutError("first lockout"); 1353 clearInvocations(mRotateTextViewController); 1354 1355 when(mAuthController.isUdfpsFingerDown()).thenReturn(true); 1356 onFaceLockoutError("second lockout"); 1357 1358 verifyNoMoreInteractions(mRotateTextViewController); 1359 } 1360 1361 @Test onBiometricError_faceLockedOutAgainAndFpAllowed_showsTheFpFollowupMessage()1362 public void onBiometricError_faceLockedOutAgainAndFpAllowed_showsTheFpFollowupMessage() { 1363 createController(); 1364 fingerprintUnlockIsPossibleAndAllowed(); 1365 onFaceLockoutError("first lockout"); 1366 clearInvocations(mRotateTextViewController); 1367 1368 onFaceLockoutError("second lockout"); 1369 1370 verifyIndicationShown(INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP, 1371 mContext.getString(R.string.keyguard_suggest_fingerprint)); 1372 } 1373 1374 @Test onBiometricError_faceLockedOutAgainAndFpNotAllowed_showsDefaultFollowup()1375 public void onBiometricError_faceLockedOutAgainAndFpNotAllowed_showsDefaultFollowup() { 1376 createController(); 1377 fingerprintUnlockIsNotPossible(); 1378 onFaceLockoutError("first lockout"); 1379 clearInvocations(mRotateTextViewController); 1380 1381 onFaceLockoutError("second lockout"); 1382 1383 verifyIndicationShown(INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP, 1384 mContext.getString(R.string.keyguard_unlock)); 1385 } 1386 1387 @Test onBiometricError_whenFaceLockoutReset_onLockOutError_showsPassedInMessage()1388 public void onBiometricError_whenFaceLockoutReset_onLockOutError_showsPassedInMessage() { 1389 createController(); 1390 onFaceLockoutError("first lockout"); 1391 clearInvocations(mRotateTextViewController); 1392 when(mKeyguardUpdateMonitor.isFaceLockedOut()).thenReturn(false); 1393 mKeyguardUpdateMonitorCallback.onLockedOutStateChanged(BiometricSourceType.FACE); 1394 1395 onFaceLockoutError("second lockout"); 1396 1397 verifyIndicationShown(INDICATION_TYPE_BIOMETRIC_MESSAGE, "second lockout"); 1398 } 1399 1400 @Test onFpLockoutStateChanged_whenFpIsLockedOut_showsPersistentMessage()1401 public void onFpLockoutStateChanged_whenFpIsLockedOut_showsPersistentMessage() { 1402 createController(); 1403 mController.setVisible(true); 1404 when(mKeyguardUpdateMonitor.isFingerprintLockedOut()).thenReturn(true); 1405 1406 mKeyguardUpdateMonitorCallback.onLockedOutStateChanged(BiometricSourceType.FINGERPRINT); 1407 1408 verifyIndicationShown(INDICATION_TYPE_PERSISTENT_UNLOCK_MESSAGE, 1409 mContext.getString(R.string.keyguard_unlock)); 1410 } 1411 1412 @Test onFpLockoutStateChanged_whenFpIsNotLockedOut_showsPersistentMessage()1413 public void onFpLockoutStateChanged_whenFpIsNotLockedOut_showsPersistentMessage() { 1414 createController(); 1415 mController.setVisible(true); 1416 clearInvocations(mRotateTextViewController); 1417 when(mKeyguardUpdateMonitor.isFingerprintLockedOut()).thenReturn(false); 1418 1419 mKeyguardUpdateMonitorCallback.onLockedOutStateChanged(BiometricSourceType.FINGERPRINT); 1420 1421 verifyHideIndication(INDICATION_TYPE_PERSISTENT_UNLOCK_MESSAGE); 1422 } 1423 1424 @Test onVisibilityChange_showsPersistentMessage_ifFpIsLockedOut()1425 public void onVisibilityChange_showsPersistentMessage_ifFpIsLockedOut() { 1426 createController(); 1427 mController.setVisible(false); 1428 when(mKeyguardUpdateMonitor.isFingerprintLockedOut()).thenReturn(true); 1429 mKeyguardUpdateMonitorCallback.onLockedOutStateChanged(BiometricSourceType.FINGERPRINT); 1430 clearInvocations(mRotateTextViewController); 1431 1432 mController.setVisible(true); 1433 1434 verifyIndicationShown(INDICATION_TYPE_PERSISTENT_UNLOCK_MESSAGE, 1435 mContext.getString(R.string.keyguard_unlock)); 1436 } 1437 1438 @Test onBiometricError_whenFaceIsLocked_onMultipleLockOutErrors_showUnavailableMessage()1439 public void onBiometricError_whenFaceIsLocked_onMultipleLockOutErrors_showUnavailableMessage() { 1440 createController(); 1441 onFaceLockoutError("first lockout"); 1442 clearInvocations(mRotateTextViewController); 1443 when(mKeyguardUpdateMonitor.isFaceLockedOut()).thenReturn(true); 1444 mKeyguardUpdateMonitorCallback.onLockedOutStateChanged(BiometricSourceType.FACE); 1445 1446 onFaceLockoutError("second lockout"); 1447 1448 verifyIndicationShown(INDICATION_TYPE_BIOMETRIC_MESSAGE, 1449 mContext.getString(R.string.keyguard_face_unlock_unavailable)); 1450 } 1451 1452 @Test onBiometricError_screenIsTurningOn_faceLockedOutFpIsNotAvailable_showsMessage()1453 public void onBiometricError_screenIsTurningOn_faceLockedOutFpIsNotAvailable_showsMessage() { 1454 createController(); 1455 screenIsTurningOn(); 1456 fingerprintUnlockIsNotPossible(); 1457 1458 onFaceLockoutError("lockout error"); 1459 verifyNoMoreInteractions(mRotateTextViewController); 1460 1461 mScreenObserver.onScreenTurnedOn(); 1462 1463 verifyIndicationShown(INDICATION_TYPE_BIOMETRIC_MESSAGE, 1464 "lockout error"); 1465 verifyIndicationShown(INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP, 1466 mContext.getString(R.string.keyguard_unlock)); 1467 } 1468 1469 @Test onBiometricError_screenIsTurningOn_faceLockedOutFpIsAvailable_showsMessage()1470 public void onBiometricError_screenIsTurningOn_faceLockedOutFpIsAvailable_showsMessage() { 1471 createController(); 1472 screenIsTurningOn(); 1473 fingerprintUnlockIsPossibleAndAllowed(); 1474 1475 onFaceLockoutError("lockout error"); 1476 verifyNoMoreInteractions(mRotateTextViewController); 1477 1478 mScreenObserver.onScreenTurnedOn(); 1479 1480 verifyIndicationShown(INDICATION_TYPE_BIOMETRIC_MESSAGE, 1481 "lockout error"); 1482 verifyIndicationShown(INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP, 1483 mContext.getString(R.string.keyguard_suggest_fingerprint)); 1484 } 1485 1486 @Test faceErrorMessageDroppedBecauseFingerprintMessageShowing()1487 public void faceErrorMessageDroppedBecauseFingerprintMessageShowing() { 1488 createController(); 1489 mController.setVisible(true); 1490 mController.getKeyguardCallback().onBiometricHelp(BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED, 1491 "fp not recognized", BiometricSourceType.FINGERPRINT); 1492 clearInvocations(mRotateTextViewController); 1493 1494 onFaceLockoutError("lockout"); 1495 verifyNoMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE); 1496 } 1497 1498 @Test faceUnlockedMessageShowsEvenWhenFingerprintMessageShowing()1499 public void faceUnlockedMessageShowsEvenWhenFingerprintMessageShowing() { 1500 createController(); 1501 mController.setVisible(true); 1502 mController.getKeyguardCallback().onBiometricHelp(BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED, 1503 "fp not recognized", BiometricSourceType.FINGERPRINT); 1504 clearInvocations(mRotateTextViewController); 1505 1506 when(mKeyguardUpdateMonitor.getIsFaceAuthenticated()).thenReturn(true); 1507 when(mKeyguardUpdateMonitor.getUserCanSkipBouncer(getCurrentUser())) 1508 .thenReturn(true); 1509 mController.getKeyguardCallback().onBiometricAuthenticated(0, 1510 BiometricSourceType.FACE, false); 1511 verifyIndicationMessage( 1512 INDICATION_TYPE_BIOMETRIC_MESSAGE, 1513 mContext.getString(R.string.keyguard_face_successful_unlock)); 1514 } 1515 1516 @Test trustGrantedMessageShowsEvenWhenFingerprintMessageShowing()1517 public void trustGrantedMessageShowsEvenWhenFingerprintMessageShowing() { 1518 createController(); 1519 mController.setVisible(true); 1520 mController.getKeyguardCallback().onBiometricHelp(BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED, 1521 "fp not recognized", BiometricSourceType.FINGERPRINT); 1522 clearInvocations(mRotateTextViewController); 1523 1524 // GIVEN trust is granted 1525 when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(true); 1526 1527 // WHEN the showTrustGranted method is called 1528 final String trustGrantedMsg = "testing trust granted message after fp message"; 1529 mController.getKeyguardCallback().onTrustGrantedForCurrentUser( 1530 false, false, new TrustGrantFlags(0), trustGrantedMsg); 1531 1532 // THEN verify the trust granted message shows 1533 verifyIndicationMessage( 1534 INDICATION_TYPE_TRUST, 1535 trustGrantedMsg); 1536 } 1537 screenIsTurningOn()1538 private void screenIsTurningOn() { 1539 when(mScreenLifecycle.getScreenState()).thenReturn(SCREEN_TURNING_ON); 1540 } 1541 sendUpdateDisclosureBroadcast()1542 private void sendUpdateDisclosureBroadcast() { 1543 mBroadcastReceiver.onReceive(mContext, new Intent()); 1544 } 1545 verifyIndicationMessages(int type, Set<CharSequence> messages)1546 private void verifyIndicationMessages(int type, Set<CharSequence> messages) { 1547 verify(mRotateTextViewController, times(messages.size())).updateIndication(eq(type), 1548 mKeyguardIndicationCaptor.capture(), anyBoolean()); 1549 List<KeyguardIndication> kis = mKeyguardIndicationCaptor.getAllValues(); 1550 1551 for (KeyguardIndication ki : kis) { 1552 final CharSequence msg = ki.getMessage(); 1553 assertTrue(messages.contains(msg)); // check message is shown 1554 messages.remove(msg); 1555 } 1556 assertThat(messages.size()).isEqualTo(0); // check that all messages accounted for (removed) 1557 } 1558 verifyIndicationMessage(int type, String message)1559 private void verifyIndicationMessage(int type, String message) { 1560 verify(mRotateTextViewController).updateIndication(eq(type), 1561 mKeyguardIndicationCaptor.capture(), anyBoolean()); 1562 assertThat(mKeyguardIndicationCaptor.getValue().getMessage()) 1563 .isEqualTo(message); 1564 } 1565 verifyHideIndication(int type)1566 private void verifyHideIndication(int type) { 1567 if (type == INDICATION_TYPE_TRANSIENT) { 1568 verify(mRotateTextViewController).hideTransient(); 1569 verify(mRotateTextViewController, never()).showTransient(anyString()); 1570 } else { 1571 verify(mRotateTextViewController).hideIndication(type); 1572 verify(mRotateTextViewController, never()).updateIndication(eq(type), 1573 anyObject(), anyBoolean()); 1574 } 1575 } 1576 verifyTransientMessage(String message)1577 private void verifyTransientMessage(String message) { 1578 verify(mRotateTextViewController).showTransient(eq(message)); 1579 } 1580 fingerprintUnlockIsNotPossible()1581 private void fingerprintUnlockIsNotPossible() { 1582 setupFingerprintUnlockPossible(false); 1583 } 1584 fingerprintUnlockIsPossibleAndAllowed()1585 private void fingerprintUnlockIsPossibleAndAllowed() { 1586 setupFingerprintUnlockPossible(true); 1587 when(mKeyguardUpdateMonitor.isUnlockingWithFingerprintAllowed()).thenReturn(true); 1588 } 1589 setupFingerprintUnlockPossible(boolean possible)1590 private void setupFingerprintUnlockPossible(boolean possible) { 1591 when(mKeyguardUpdateMonitor 1592 .isUnlockWithFingerprintPossible(getCurrentUser())) 1593 .thenReturn(possible); 1594 } 1595 getCurrentUser()1596 private int getCurrentUser() { 1597 return mCurrentUserId; 1598 } 1599 onFaceLockoutError(String errMsg)1600 private void onFaceLockoutError(String errMsg) { 1601 mKeyguardUpdateMonitorCallback.onBiometricError(FACE_ERROR_LOCKOUT_PERMANENT, 1602 errMsg, 1603 BiometricSourceType.FACE); 1604 } 1605 } 1606