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