Loading packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +16 −4 Original line number Diff line number Diff line Loading @@ -1311,7 +1311,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } public boolean getUserHasTrust(int userId) { return !isTrustDisabled() && mUserHasTrust.get(userId); return !isTrustDisabled() && mUserHasTrust.get(userId) && isUnlockingWithTrustAgentAllowed(); } /** Loading @@ -1319,12 +1320,19 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab */ public boolean getUserUnlockedWithBiometric(int userId) { BiometricAuthenticated fingerprint = mUserFingerprintAuthenticated.get(userId); BiometricAuthenticated face = mUserFaceAuthenticated.get(userId); boolean fingerprintAllowed = fingerprint != null && fingerprint.mAuthenticated && isUnlockingWithBiometricAllowed(fingerprint.mIsStrongBiometric); boolean faceAllowed = face != null && face.mAuthenticated return fingerprintAllowed || getUserUnlockedWithFace(userId); } /** * Returns whether the user is unlocked with face. */ public boolean getUserUnlockedWithFace(int userId) { BiometricAuthenticated face = mUserFaceAuthenticated.get(userId); return face != null && face.mAuthenticated && isUnlockingWithBiometricAllowed(face.mIsStrongBiometric); return fingerprintAllowed || faceAllowed; } /** Loading Loading @@ -1399,6 +1407,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab return mUserTrustIsUsuallyManaged.get(userId); } private boolean isUnlockingWithTrustAgentAllowed() { return isUnlockingWithBiometricAllowed(true); } public boolean isUnlockingWithBiometricAllowed(boolean isStrongBiometric) { // StrongAuthTracker#isUnlockingWithBiometricAllowed includes // STRONG_AUTH_REQUIRED_AFTER_LOCKOUT which is the same as mFingerprintLockedOutPermanent; Loading packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java +39 −18 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import static android.view.View.GONE; import static android.view.View.VISIBLE; import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_RECOGNIZED; import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED; import static com.android.keyguard.KeyguardUpdateMonitor.getCurrentUser; import static com.android.systemui.DejankUtils.whitelistIpcs; import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.IMPORTANT_MSG_MIN_DURATION; Loading Loading @@ -539,6 +540,10 @@ public class KeyguardIndicationController { .build(), true ); } else { mRotateTextViewController.hideIndication( INDICATION_TYPE_BIOMETRIC_MESSAGE); } if (!TextUtils.isEmpty(mBiometricMessageFollowUp)) { mRotateTextViewController.updateIndication( INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP, Loading @@ -553,10 +558,6 @@ public class KeyguardIndicationController { mRotateTextViewController.hideIndication( INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP); } } else { mRotateTextViewController.hideIndication(INDICATION_TYPE_BIOMETRIC_MESSAGE); mRotateTextViewController.hideIndication(INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP); } } private void updateTransient() { Loading Loading @@ -784,7 +785,8 @@ public class KeyguardIndicationController { */ private void showBiometricMessage(CharSequence biometricMessage, @Nullable CharSequence biometricMessageFollowUp) { if (TextUtils.equals(biometricMessage, mBiometricMessage)) { if (TextUtils.equals(biometricMessage, mBiometricMessage) && TextUtils.equals(biometricMessageFollowUp, mBiometricMessageFollowUp)) { return; } Loading @@ -793,7 +795,8 @@ public class KeyguardIndicationController { mHandler.removeMessages(MSG_SHOW_ACTION_TO_UNLOCK); hideBiometricMessageDelayed( mBiometricMessageFollowUp != null !TextUtils.isEmpty(mBiometricMessage) && !TextUtils.isEmpty(mBiometricMessageFollowUp) ? IMPORTANT_MSG_MIN_DURATION * 2 : DEFAULT_HIDE_DELAY_MS ); Loading Loading @@ -1091,6 +1094,8 @@ public class KeyguardIndicationController { && msgId != BIOMETRIC_HELP_FACE_NOT_RECOGNIZED; final boolean faceAuthFailed = biometricSourceType == FACE && msgId == BIOMETRIC_HELP_FACE_NOT_RECOGNIZED; // ran through matcher & failed final boolean fpAuthFailed = biometricSourceType == FINGERPRINT && msgId == BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED; // ran matcher & failed final boolean isUnlockWithFingerprintPossible = canUnlockWithFingerprint(); final boolean isCoExFaceAcquisitionMessage = faceAuthSoftError && isUnlockWithFingerprintPossible; Loading @@ -1113,6 +1118,22 @@ public class KeyguardIndicationController { mContext.getString(R.string.keyguard_face_failed), mContext.getString(R.string.keyguard_suggest_fingerprint) ); } else if (fpAuthFailed && mKeyguardUpdateMonitor.getUserUnlockedWithFace(getCurrentUser())) { // face had already previously unlocked the device, so instead of showing a // fingerprint error, tell them they have already unlocked with face auth // and how to enter their device showBiometricMessage( mContext.getString(R.string.keyguard_face_successful_unlock), mContext.getString(R.string.keyguard_unlock) ); } else if (fpAuthFailed && mKeyguardUpdateMonitor.getUserHasTrust( KeyguardUpdateMonitor.getCurrentUser())) { showBiometricMessage( getTrustGrantedIndication(), mContext.getString(R.string.keyguard_unlock) ); } else { showBiometricMessage(helpString); } Loading packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java +5 −0 Original line number Diff line number Diff line Loading @@ -437,6 +437,11 @@ public class KeyguardStateControllerImpl implements KeyguardStateController, Dum update(false /* updateAlways */); } @Override public void onLockedOutStateChanged(BiometricSourceType biometricSourceType) { update(false /* updateAlways */); } @Override public void onKeyguardVisibilityChanged(boolean visible) { update(false /* updateAlways */); Loading packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +25 −1 Original line number Diff line number Diff line Loading @@ -685,11 +685,35 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { // WHEN fingerprint is locked out fingerprintErrorLockedOut(); // THEN unlocking with fingeprint is not allowed // THEN unlocking with fingerprint is not allowed Assert.assertFalse(mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed( BiometricSourceType.FINGERPRINT)); } @Test public void trustAgentHasTrust() { // WHEN user has trust mKeyguardUpdateMonitor.onTrustChanged(true, true, getCurrentUser(), 0, null); // THEN user is considered as "having trust" and bouncer can be skipped Assert.assertTrue(mKeyguardUpdateMonitor.getUserHasTrust(getCurrentUser())); Assert.assertTrue(mKeyguardUpdateMonitor.getUserCanSkipBouncer(getCurrentUser())); } @Test public void trustAgentHasTrust_fingerprintLockout() { // GIVEN user has trust mKeyguardUpdateMonitor.onTrustChanged(true, true, getCurrentUser(), 0, null); Assert.assertTrue(mKeyguardUpdateMonitor.getUserHasTrust(getCurrentUser())); // WHEN fingerprint is locked out fingerprintErrorLockedOut(); // THEN user is NOT considered as "having trust" and bouncer cannot be skipped Assert.assertFalse(mKeyguardUpdateMonitor.getUserHasTrust(getCurrentUser())); Assert.assertFalse(mKeyguardUpdateMonitor.getUserCanSkipBouncer(getCurrentUser())); } @Test public void testTriesToAuthenticate_whenBouncer() { setKeyguardBouncerVisibility(true); Loading packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java +76 −0 Original line number Diff line number Diff line Loading @@ -619,6 +619,82 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { mContext.getString(R.string.keyguard_suggest_fingerprint)); } @Test public void onBiometricHelp_coEx_fpFailure_faceAlreadyUnlocked() { createController(); // GIVEN face has already unlocked the device when(mKeyguardUpdateMonitor.getUserUnlockedWithFace(anyInt())).thenReturn(true); String message = "A message"; mController.setVisible(true); // WHEN there's a fingerprint not recognized message mController.getKeyguardCallback().onBiometricHelp( BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED, message, BiometricSourceType.FINGERPRINT); // THEN show sequential messages such as: 'Unlocked by face' and // 'Swipe up to open' verifyIndicationMessage( INDICATION_TYPE_BIOMETRIC_MESSAGE, mContext.getString(R.string.keyguard_face_successful_unlock)); verifyIndicationMessage( INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP, mContext.getString(R.string.keyguard_unlock)); } @Test public void onBiometricHelp_coEx_fpFailure_trustAgentAlreadyUnlocked() { createController(); // GIVEN trust agent has already unlocked the device when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(true); String message = "A message"; mController.setVisible(true); // WHEN there's a fingerprint not recognized message mController.getKeyguardCallback().onBiometricHelp( BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED, message, BiometricSourceType.FINGERPRINT); // THEN show sequential messages such as: 'Kept unlocked by TrustAgent' and // 'Swipe up to open' verifyIndicationMessage( INDICATION_TYPE_BIOMETRIC_MESSAGE, mContext.getString(R.string.keyguard_indication_trust_unlocked)); verifyIndicationMessage( INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP, mContext.getString(R.string.keyguard_unlock)); } @Test public void onBiometricHelp_coEx_fpFailure_trustAgentUnlocked_emptyTrustGrantedMessage() { createController(); // GIVEN trust agent has already unlocked the device & trust granted message is empty when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(true); mController.showTrustGrantedMessage(false, ""); String message = "A message"; mController.setVisible(true); // WHEN there's a fingerprint not recognized message mController.getKeyguardCallback().onBiometricHelp( BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED, message, BiometricSourceType.FINGERPRINT); // THEN show action to unlock (ie: 'Swipe up to open') verifyNoMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE); verifyIndicationMessage( INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP, mContext.getString(R.string.keyguard_unlock)); } @Test public void transientIndication_visibleWhenDozing_unlessSwipeUp_fromError() { createController(); Loading Loading
packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +16 −4 Original line number Diff line number Diff line Loading @@ -1311,7 +1311,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } public boolean getUserHasTrust(int userId) { return !isTrustDisabled() && mUserHasTrust.get(userId); return !isTrustDisabled() && mUserHasTrust.get(userId) && isUnlockingWithTrustAgentAllowed(); } /** Loading @@ -1319,12 +1320,19 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab */ public boolean getUserUnlockedWithBiometric(int userId) { BiometricAuthenticated fingerprint = mUserFingerprintAuthenticated.get(userId); BiometricAuthenticated face = mUserFaceAuthenticated.get(userId); boolean fingerprintAllowed = fingerprint != null && fingerprint.mAuthenticated && isUnlockingWithBiometricAllowed(fingerprint.mIsStrongBiometric); boolean faceAllowed = face != null && face.mAuthenticated return fingerprintAllowed || getUserUnlockedWithFace(userId); } /** * Returns whether the user is unlocked with face. */ public boolean getUserUnlockedWithFace(int userId) { BiometricAuthenticated face = mUserFaceAuthenticated.get(userId); return face != null && face.mAuthenticated && isUnlockingWithBiometricAllowed(face.mIsStrongBiometric); return fingerprintAllowed || faceAllowed; } /** Loading Loading @@ -1399,6 +1407,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab return mUserTrustIsUsuallyManaged.get(userId); } private boolean isUnlockingWithTrustAgentAllowed() { return isUnlockingWithBiometricAllowed(true); } public boolean isUnlockingWithBiometricAllowed(boolean isStrongBiometric) { // StrongAuthTracker#isUnlockingWithBiometricAllowed includes // STRONG_AUTH_REQUIRED_AFTER_LOCKOUT which is the same as mFingerprintLockedOutPermanent; Loading
packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java +39 −18 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import static android.view.View.GONE; import static android.view.View.VISIBLE; import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_RECOGNIZED; import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED; import static com.android.keyguard.KeyguardUpdateMonitor.getCurrentUser; import static com.android.systemui.DejankUtils.whitelistIpcs; import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.IMPORTANT_MSG_MIN_DURATION; Loading Loading @@ -539,6 +540,10 @@ public class KeyguardIndicationController { .build(), true ); } else { mRotateTextViewController.hideIndication( INDICATION_TYPE_BIOMETRIC_MESSAGE); } if (!TextUtils.isEmpty(mBiometricMessageFollowUp)) { mRotateTextViewController.updateIndication( INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP, Loading @@ -553,10 +558,6 @@ public class KeyguardIndicationController { mRotateTextViewController.hideIndication( INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP); } } else { mRotateTextViewController.hideIndication(INDICATION_TYPE_BIOMETRIC_MESSAGE); mRotateTextViewController.hideIndication(INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP); } } private void updateTransient() { Loading Loading @@ -784,7 +785,8 @@ public class KeyguardIndicationController { */ private void showBiometricMessage(CharSequence biometricMessage, @Nullable CharSequence biometricMessageFollowUp) { if (TextUtils.equals(biometricMessage, mBiometricMessage)) { if (TextUtils.equals(biometricMessage, mBiometricMessage) && TextUtils.equals(biometricMessageFollowUp, mBiometricMessageFollowUp)) { return; } Loading @@ -793,7 +795,8 @@ public class KeyguardIndicationController { mHandler.removeMessages(MSG_SHOW_ACTION_TO_UNLOCK); hideBiometricMessageDelayed( mBiometricMessageFollowUp != null !TextUtils.isEmpty(mBiometricMessage) && !TextUtils.isEmpty(mBiometricMessageFollowUp) ? IMPORTANT_MSG_MIN_DURATION * 2 : DEFAULT_HIDE_DELAY_MS ); Loading Loading @@ -1091,6 +1094,8 @@ public class KeyguardIndicationController { && msgId != BIOMETRIC_HELP_FACE_NOT_RECOGNIZED; final boolean faceAuthFailed = biometricSourceType == FACE && msgId == BIOMETRIC_HELP_FACE_NOT_RECOGNIZED; // ran through matcher & failed final boolean fpAuthFailed = biometricSourceType == FINGERPRINT && msgId == BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED; // ran matcher & failed final boolean isUnlockWithFingerprintPossible = canUnlockWithFingerprint(); final boolean isCoExFaceAcquisitionMessage = faceAuthSoftError && isUnlockWithFingerprintPossible; Loading @@ -1113,6 +1118,22 @@ public class KeyguardIndicationController { mContext.getString(R.string.keyguard_face_failed), mContext.getString(R.string.keyguard_suggest_fingerprint) ); } else if (fpAuthFailed && mKeyguardUpdateMonitor.getUserUnlockedWithFace(getCurrentUser())) { // face had already previously unlocked the device, so instead of showing a // fingerprint error, tell them they have already unlocked with face auth // and how to enter their device showBiometricMessage( mContext.getString(R.string.keyguard_face_successful_unlock), mContext.getString(R.string.keyguard_unlock) ); } else if (fpAuthFailed && mKeyguardUpdateMonitor.getUserHasTrust( KeyguardUpdateMonitor.getCurrentUser())) { showBiometricMessage( getTrustGrantedIndication(), mContext.getString(R.string.keyguard_unlock) ); } else { showBiometricMessage(helpString); } Loading
packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java +5 −0 Original line number Diff line number Diff line Loading @@ -437,6 +437,11 @@ public class KeyguardStateControllerImpl implements KeyguardStateController, Dum update(false /* updateAlways */); } @Override public void onLockedOutStateChanged(BiometricSourceType biometricSourceType) { update(false /* updateAlways */); } @Override public void onKeyguardVisibilityChanged(boolean visible) { update(false /* updateAlways */); Loading
packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +25 −1 Original line number Diff line number Diff line Loading @@ -685,11 +685,35 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { // WHEN fingerprint is locked out fingerprintErrorLockedOut(); // THEN unlocking with fingeprint is not allowed // THEN unlocking with fingerprint is not allowed Assert.assertFalse(mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed( BiometricSourceType.FINGERPRINT)); } @Test public void trustAgentHasTrust() { // WHEN user has trust mKeyguardUpdateMonitor.onTrustChanged(true, true, getCurrentUser(), 0, null); // THEN user is considered as "having trust" and bouncer can be skipped Assert.assertTrue(mKeyguardUpdateMonitor.getUserHasTrust(getCurrentUser())); Assert.assertTrue(mKeyguardUpdateMonitor.getUserCanSkipBouncer(getCurrentUser())); } @Test public void trustAgentHasTrust_fingerprintLockout() { // GIVEN user has trust mKeyguardUpdateMonitor.onTrustChanged(true, true, getCurrentUser(), 0, null); Assert.assertTrue(mKeyguardUpdateMonitor.getUserHasTrust(getCurrentUser())); // WHEN fingerprint is locked out fingerprintErrorLockedOut(); // THEN user is NOT considered as "having trust" and bouncer cannot be skipped Assert.assertFalse(mKeyguardUpdateMonitor.getUserHasTrust(getCurrentUser())); Assert.assertFalse(mKeyguardUpdateMonitor.getUserCanSkipBouncer(getCurrentUser())); } @Test public void testTriesToAuthenticate_whenBouncer() { setKeyguardBouncerVisibility(true); Loading
packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java +76 −0 Original line number Diff line number Diff line Loading @@ -619,6 +619,82 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { mContext.getString(R.string.keyguard_suggest_fingerprint)); } @Test public void onBiometricHelp_coEx_fpFailure_faceAlreadyUnlocked() { createController(); // GIVEN face has already unlocked the device when(mKeyguardUpdateMonitor.getUserUnlockedWithFace(anyInt())).thenReturn(true); String message = "A message"; mController.setVisible(true); // WHEN there's a fingerprint not recognized message mController.getKeyguardCallback().onBiometricHelp( BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED, message, BiometricSourceType.FINGERPRINT); // THEN show sequential messages such as: 'Unlocked by face' and // 'Swipe up to open' verifyIndicationMessage( INDICATION_TYPE_BIOMETRIC_MESSAGE, mContext.getString(R.string.keyguard_face_successful_unlock)); verifyIndicationMessage( INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP, mContext.getString(R.string.keyguard_unlock)); } @Test public void onBiometricHelp_coEx_fpFailure_trustAgentAlreadyUnlocked() { createController(); // GIVEN trust agent has already unlocked the device when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(true); String message = "A message"; mController.setVisible(true); // WHEN there's a fingerprint not recognized message mController.getKeyguardCallback().onBiometricHelp( BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED, message, BiometricSourceType.FINGERPRINT); // THEN show sequential messages such as: 'Kept unlocked by TrustAgent' and // 'Swipe up to open' verifyIndicationMessage( INDICATION_TYPE_BIOMETRIC_MESSAGE, mContext.getString(R.string.keyguard_indication_trust_unlocked)); verifyIndicationMessage( INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP, mContext.getString(R.string.keyguard_unlock)); } @Test public void onBiometricHelp_coEx_fpFailure_trustAgentUnlocked_emptyTrustGrantedMessage() { createController(); // GIVEN trust agent has already unlocked the device & trust granted message is empty when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(true); mController.showTrustGrantedMessage(false, ""); String message = "A message"; mController.setVisible(true); // WHEN there's a fingerprint not recognized message mController.getKeyguardCallback().onBiometricHelp( BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED, message, BiometricSourceType.FINGERPRINT); // THEN show action to unlock (ie: 'Swipe up to open') verifyNoMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE); verifyIndicationMessage( INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP, mContext.getString(R.string.keyguard_unlock)); } @Test public void transientIndication_visibleWhenDozing_unlessSwipeUp_fromError() { createController(); Loading