Merge "Update FP failure logic when device is unlocked" into tm-qpr-dev
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 */);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user