diff options
5 files changed, 161 insertions, 24 deletions
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 54886c3e2080..f95e28c9028e 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -108,7 +108,6 @@ import android.os.Looper; import android.os.Message; import android.os.PowerManager; import android.os.RemoteException; -import android.os.SystemClock; import android.os.Trace; import android.os.UserHandle; import android.os.UserManager; @@ -1311,7 +1310,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } public boolean getUserHasTrust(int userId) { - return !isTrustDisabled() && mUserHasTrust.get(userId); + return !isTrustDisabled() && mUserHasTrust.get(userId) + && isUnlockingWithTrustAgentAllowed(); } /** @@ -1319,12 +1319,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; } /** @@ -1399,6 +1406,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; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java index 648185503ef6..4bf84f76d224 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java @@ -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; @@ -539,23 +540,23 @@ public class KeyguardIndicationController { .build(), true ); - if (!TextUtils.isEmpty(mBiometricMessageFollowUp)) { - mRotateTextViewController.updateIndication( - INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP, - new KeyguardIndication.Builder() - .setMessage(mBiometricMessageFollowUp) - .setMinVisibilityMillis(IMPORTANT_MSG_MIN_DURATION) - .setTextColor(mInitialTextColorState) - .build(), - true - ); - } else { - mRotateTextViewController.hideIndication( - INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP); - } } else { - mRotateTextViewController.hideIndication(INDICATION_TYPE_BIOMETRIC_MESSAGE); - mRotateTextViewController.hideIndication(INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP); + mRotateTextViewController.hideIndication( + INDICATION_TYPE_BIOMETRIC_MESSAGE); + } + if (!TextUtils.isEmpty(mBiometricMessageFollowUp)) { + mRotateTextViewController.updateIndication( + INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP, + new KeyguardIndication.Builder() + .setMessage(mBiometricMessageFollowUp) + .setMinVisibilityMillis(IMPORTANT_MSG_MIN_DURATION) + .setTextColor(mInitialTextColorState) + .build(), + true + ); + } else { + mRotateTextViewController.hideIndication( + INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP); } } @@ -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; } @@ -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 ); @@ -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; @@ -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); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java index cc6fdccba789..9ad36fd58fe1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java @@ -438,6 +438,11 @@ public class KeyguardStateControllerImpl implements KeyguardStateController, Dum } @Override + public void onLockedOutStateChanged(BiometricSourceType biometricSourceType) { + update(false /* updateAlways */); + } + + @Override public void onKeyguardVisibilityChanged(boolean visible) { update(false /* updateAlways */); } diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java index d1650b776052..66481807fbb4 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java @@ -685,12 +685,36 @@ 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); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java index dffa566c97c0..f9f2c45190bc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java @@ -620,6 +620,82 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { } @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(); String message = mContext.getString(R.string.keyguard_unlock); |