Merge "Update FP failure logic when device is unlocked" into tm-qpr-dev

This commit is contained in:
Beverly Tai
2023-02-03 18:37:15 +00:00
committed by Android (Google) Code Review
5 changed files with 161 additions and 23 deletions

View File

@@ -1311,7 +1311,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
} }
public boolean getUserHasTrust(int userId) { public boolean getUserHasTrust(int userId) {
return !isTrustDisabled() && mUserHasTrust.get(userId); return !isTrustDisabled() && mUserHasTrust.get(userId)
&& isUnlockingWithTrustAgentAllowed();
} }
/** /**
@@ -1319,12 +1320,19 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
*/ */
public boolean getUserUnlockedWithBiometric(int userId) { public boolean getUserUnlockedWithBiometric(int userId) {
BiometricAuthenticated fingerprint = mUserFingerprintAuthenticated.get(userId); BiometricAuthenticated fingerprint = mUserFingerprintAuthenticated.get(userId);
BiometricAuthenticated face = mUserFaceAuthenticated.get(userId);
boolean fingerprintAllowed = fingerprint != null && fingerprint.mAuthenticated boolean fingerprintAllowed = fingerprint != null && fingerprint.mAuthenticated
&& isUnlockingWithBiometricAllowed(fingerprint.mIsStrongBiometric); && 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); && isUnlockingWithBiometricAllowed(face.mIsStrongBiometric);
return fingerprintAllowed || faceAllowed;
} }
/** /**
@@ -1399,6 +1407,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
return mUserTrustIsUsuallyManaged.get(userId); return mUserTrustIsUsuallyManaged.get(userId);
} }
private boolean isUnlockingWithTrustAgentAllowed() {
return isUnlockingWithBiometricAllowed(true);
}
public boolean isUnlockingWithBiometricAllowed(boolean isStrongBiometric) { public boolean isUnlockingWithBiometricAllowed(boolean isStrongBiometric) {
// StrongAuthTracker#isUnlockingWithBiometricAllowed includes // StrongAuthTracker#isUnlockingWithBiometricAllowed includes
// STRONG_AUTH_REQUIRED_AFTER_LOCKOUT which is the same as mFingerprintLockedOutPermanent; // STRONG_AUTH_REQUIRED_AFTER_LOCKOUT which is the same as mFingerprintLockedOutPermanent;

View File

@@ -26,6 +26,7 @@ import static android.view.View.GONE;
import static android.view.View.VISIBLE; 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_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.keyguard.KeyguardUpdateMonitor.getCurrentUser;
import static com.android.systemui.DejankUtils.whitelistIpcs; import static com.android.systemui.DejankUtils.whitelistIpcs;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.IMPORTANT_MSG_MIN_DURATION; import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.IMPORTANT_MSG_MIN_DURATION;
@@ -539,6 +540,10 @@ public class KeyguardIndicationController {
.build(), .build(),
true true
); );
} else {
mRotateTextViewController.hideIndication(
INDICATION_TYPE_BIOMETRIC_MESSAGE);
}
if (!TextUtils.isEmpty(mBiometricMessageFollowUp)) { if (!TextUtils.isEmpty(mBiometricMessageFollowUp)) {
mRotateTextViewController.updateIndication( mRotateTextViewController.updateIndication(
INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP, INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP,
@@ -553,10 +558,6 @@ public class KeyguardIndicationController {
mRotateTextViewController.hideIndication( mRotateTextViewController.hideIndication(
INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP); INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP);
} }
} else {
mRotateTextViewController.hideIndication(INDICATION_TYPE_BIOMETRIC_MESSAGE);
mRotateTextViewController.hideIndication(INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP);
}
} }
private void updateTransient() { private void updateTransient() {
@@ -784,7 +785,8 @@ public class KeyguardIndicationController {
*/ */
private void showBiometricMessage(CharSequence biometricMessage, private void showBiometricMessage(CharSequence biometricMessage,
@Nullable CharSequence biometricMessageFollowUp) { @Nullable CharSequence biometricMessageFollowUp) {
if (TextUtils.equals(biometricMessage, mBiometricMessage)) { if (TextUtils.equals(biometricMessage, mBiometricMessage)
&& TextUtils.equals(biometricMessageFollowUp, mBiometricMessageFollowUp)) {
return; return;
} }
@@ -793,7 +795,8 @@ public class KeyguardIndicationController {
mHandler.removeMessages(MSG_SHOW_ACTION_TO_UNLOCK); mHandler.removeMessages(MSG_SHOW_ACTION_TO_UNLOCK);
hideBiometricMessageDelayed( hideBiometricMessageDelayed(
mBiometricMessageFollowUp != null !TextUtils.isEmpty(mBiometricMessage)
&& !TextUtils.isEmpty(mBiometricMessageFollowUp)
? IMPORTANT_MSG_MIN_DURATION * 2 ? IMPORTANT_MSG_MIN_DURATION * 2
: DEFAULT_HIDE_DELAY_MS : DEFAULT_HIDE_DELAY_MS
); );
@@ -1091,6 +1094,8 @@ public class KeyguardIndicationController {
&& msgId != BIOMETRIC_HELP_FACE_NOT_RECOGNIZED; && msgId != BIOMETRIC_HELP_FACE_NOT_RECOGNIZED;
final boolean faceAuthFailed = biometricSourceType == FACE final boolean faceAuthFailed = biometricSourceType == FACE
&& msgId == BIOMETRIC_HELP_FACE_NOT_RECOGNIZED; // ran through matcher & failed && 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 isUnlockWithFingerprintPossible = canUnlockWithFingerprint();
final boolean isCoExFaceAcquisitionMessage = final boolean isCoExFaceAcquisitionMessage =
faceAuthSoftError && isUnlockWithFingerprintPossible; faceAuthSoftError && isUnlockWithFingerprintPossible;
@@ -1113,6 +1118,22 @@ public class KeyguardIndicationController {
mContext.getString(R.string.keyguard_face_failed), mContext.getString(R.string.keyguard_face_failed),
mContext.getString(R.string.keyguard_suggest_fingerprint) 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 { } else {
showBiometricMessage(helpString); showBiometricMessage(helpString);
} }

View File

@@ -437,6 +437,11 @@ public class KeyguardStateControllerImpl implements KeyguardStateController, Dum
update(false /* updateAlways */); update(false /* updateAlways */);
} }
@Override
public void onLockedOutStateChanged(BiometricSourceType biometricSourceType) {
update(false /* updateAlways */);
}
@Override @Override
public void onKeyguardVisibilityChanged(boolean visible) { public void onKeyguardVisibilityChanged(boolean visible) {
update(false /* updateAlways */); update(false /* updateAlways */);

View File

@@ -685,11 +685,35 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
// WHEN fingerprint is locked out // WHEN fingerprint is locked out
fingerprintErrorLockedOut(); fingerprintErrorLockedOut();
// THEN unlocking with fingeprint is not allowed // THEN unlocking with fingerprint is not allowed
Assert.assertFalse(mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed( Assert.assertFalse(mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
BiometricSourceType.FINGERPRINT)); 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 @Test
public void testTriesToAuthenticate_whenBouncer() { public void testTriesToAuthenticate_whenBouncer() {
setKeyguardBouncerVisibility(true); setKeyguardBouncerVisibility(true);

View File

@@ -619,6 +619,82 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
mContext.getString(R.string.keyguard_suggest_fingerprint)); 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 @Test
public void transientIndication_visibleWhenDozing_unlessSwipeUp_fromError() { public void transientIndication_visibleWhenDozing_unlessSwipeUp_fromError() {
createController(); createController();