Merge "Update face strong auth strongAuth message" into tm-qpr-dev am: 72ee972de5
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/21299211 Change-Id: I08e79c39d65f2a0baf8b05542a0c419f9c45f223 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -260,6 +260,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public static final int BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED = -1;
|
public static final int BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED = -1;
|
||||||
public static final int BIOMETRIC_HELP_FACE_NOT_RECOGNIZED = -2;
|
public static final int BIOMETRIC_HELP_FACE_NOT_RECOGNIZED = -2;
|
||||||
|
public static final int BIOMETRIC_HELP_FACE_NOT_AVAILABLE = -3;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If no cancel signal has been received after this amount of time, set the biometric running
|
* If no cancel signal has been received after this amount of time, set the biometric running
|
||||||
@@ -2948,9 +2949,26 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
// This would need to be updated for multi-sensor devices
|
// This would need to be updated for multi-sensor devices
|
||||||
final boolean supportsFaceDetection = !mFaceSensorProperties.isEmpty()
|
final boolean supportsFaceDetection = !mFaceSensorProperties.isEmpty()
|
||||||
&& mFaceSensorProperties.get(0).supportsFaceDetection;
|
&& mFaceSensorProperties.get(0).supportsFaceDetection;
|
||||||
if (!isUnlockingWithBiometricAllowed(FACE) && supportsFaceDetection) {
|
if (!isUnlockingWithBiometricAllowed(FACE)) {
|
||||||
|
final boolean udfpsFingerprintAuthRunning = isUdfpsSupported()
|
||||||
|
&& isFingerprintDetectionRunning();
|
||||||
|
if (supportsFaceDetection && !udfpsFingerprintAuthRunning) {
|
||||||
|
// Run face detection. (If a face is detected, show the bouncer.)
|
||||||
mLogger.v("startListeningForFace - detect");
|
mLogger.v("startListeningForFace - detect");
|
||||||
mFaceManager.detectFace(mFaceCancelSignal, mFaceDetectionCallback, userId);
|
mFaceManager.detectFace(mFaceCancelSignal, mFaceDetectionCallback, userId);
|
||||||
|
} else {
|
||||||
|
// Don't run face detection. Instead, inform the user
|
||||||
|
// face auth is unavailable and how to proceed.
|
||||||
|
// (ie: "Use fingerprint instead" or "Swipe up to open")
|
||||||
|
mLogger.v("Ignoring \"startListeningForFace - detect\". "
|
||||||
|
+ "Informing user face isn't available.");
|
||||||
|
mFaceAuthenticationCallback.onAuthenticationHelp(
|
||||||
|
BIOMETRIC_HELP_FACE_NOT_AVAILABLE,
|
||||||
|
mContext.getResources().getString(
|
||||||
|
R.string.keyguard_face_unlock_unavailable)
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
mLogger.v("startListeningForFace - authenticate");
|
mLogger.v("startListeningForFace - authenticate");
|
||||||
final boolean isBypassEnabled = mKeyguardBypassController != null
|
final boolean isBypassEnabled = mKeyguardBypassController != null
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import static android.hardware.biometrics.BiometricSourceType.FINGERPRINT;
|
|||||||
import static android.view.View.GONE;
|
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_AVAILABLE;
|
||||||
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.BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED;
|
||||||
import static com.android.keyguard.KeyguardUpdateMonitor.getCurrentUser;
|
import static com.android.keyguard.KeyguardUpdateMonitor.getCurrentUser;
|
||||||
@@ -1084,18 +1085,23 @@ public class KeyguardIndicationController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final boolean faceAuthUnavailable = biometricSourceType == FACE
|
||||||
|
&& msgId == BIOMETRIC_HELP_FACE_NOT_AVAILABLE;
|
||||||
|
|
||||||
// TODO(b/141025588): refactor to reduce repetition of code/comments
|
// TODO(b/141025588): refactor to reduce repetition of code/comments
|
||||||
// Only checking if unlocking with Biometric is allowed (no matter strong or non-strong
|
// Only checking if unlocking with Biometric is allowed (no matter strong or non-strong
|
||||||
// as long as primary auth, i.e. PIN/pattern/password, is not required), so it's ok to
|
// as long as primary auth, i.e. PIN/pattern/password, is not required), so it's ok to
|
||||||
// pass true for isStrongBiometric to isUnlockingWithBiometricAllowed() to bypass the
|
// pass true for isStrongBiometric to isUnlockingWithBiometricAllowed() to bypass the
|
||||||
// check of whether non-strong biometric is allowed
|
// check of whether non-strong biometric is allowed
|
||||||
if (!mKeyguardUpdateMonitor
|
if (!mKeyguardUpdateMonitor
|
||||||
.isUnlockingWithBiometricAllowed(true /* isStrongBiometric */)) {
|
.isUnlockingWithBiometricAllowed(true /* isStrongBiometric */)
|
||||||
|
&& !faceAuthUnavailable) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean faceAuthSoftError = biometricSourceType == FACE
|
final boolean faceAuthSoftError = biometricSourceType == FACE
|
||||||
&& msgId != BIOMETRIC_HELP_FACE_NOT_RECOGNIZED;
|
&& msgId != BIOMETRIC_HELP_FACE_NOT_RECOGNIZED
|
||||||
|
&& msgId != BIOMETRIC_HELP_FACE_NOT_AVAILABLE;
|
||||||
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
|
final boolean fpAuthFailed = biometricSourceType == FINGERPRINT
|
||||||
@@ -1138,6 +1144,13 @@ public class KeyguardIndicationController {
|
|||||||
getTrustGrantedIndication(),
|
getTrustGrantedIndication(),
|
||||||
mContext.getString(R.string.keyguard_unlock)
|
mContext.getString(R.string.keyguard_unlock)
|
||||||
);
|
);
|
||||||
|
} else if (faceAuthUnavailable) {
|
||||||
|
showBiometricMessage(
|
||||||
|
helpString,
|
||||||
|
isUnlockWithFingerprintPossible
|
||||||
|
? mContext.getString(R.string.keyguard_suggest_fingerprint)
|
||||||
|
: mContext.getString(R.string.keyguard_unlock)
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
showBiometricMessage(helpString);
|
showBiometricMessage(helpString);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOM
|
|||||||
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT;
|
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT;
|
||||||
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
|
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
|
||||||
import static com.android.keyguard.FaceAuthApiRequestReason.NOTIFICATION_PANEL_CLICKED;
|
import static com.android.keyguard.FaceAuthApiRequestReason.NOTIFICATION_PANEL_CLICKED;
|
||||||
|
import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_AVAILABLE;
|
||||||
import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_STATE_CANCELLING_RESTARTING;
|
import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_STATE_CANCELLING_RESTARTING;
|
||||||
import static com.android.keyguard.KeyguardUpdateMonitor.DEFAULT_CANCEL_SIGNAL_TIMEOUT;
|
import static com.android.keyguard.KeyguardUpdateMonitor.DEFAULT_CANCEL_SIGNAL_TIMEOUT;
|
||||||
import static com.android.keyguard.KeyguardUpdateMonitor.HAL_POWER_PRESS_TIMEOUT;
|
import static com.android.keyguard.KeyguardUpdateMonitor.HAL_POWER_PRESS_TIMEOUT;
|
||||||
@@ -240,7 +241,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
|
|||||||
@Mock
|
@Mock
|
||||||
private FingerprintInteractiveToAuthProvider mInteractiveToAuthProvider;
|
private FingerprintInteractiveToAuthProvider mInteractiveToAuthProvider;
|
||||||
|
|
||||||
|
private List<FingerprintSensorPropertiesInternal> mFingerprintSensorProperties;
|
||||||
private final int mCurrentUserId = 100;
|
private final int mCurrentUserId = 100;
|
||||||
private final UserInfo mCurrentUserInfo = new UserInfo(mCurrentUserId, "Test user", 0);
|
private final UserInfo mCurrentUserInfo = new UserInfo(mCurrentUserId, "Test user", 0);
|
||||||
|
|
||||||
@@ -280,9 +281,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
|
|||||||
when(mFaceSensorProperties.get(anyInt())).thenReturn(
|
when(mFaceSensorProperties.get(anyInt())).thenReturn(
|
||||||
createFaceSensorProperties(/* supportsFaceDetection = */ false));
|
createFaceSensorProperties(/* supportsFaceDetection = */ false));
|
||||||
|
|
||||||
when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
|
mFingerprintSensorProperties = List.of(
|
||||||
when(mFingerprintManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
|
|
||||||
when(mFingerprintManager.getSensorPropertiesInternal()).thenReturn(List.of(
|
|
||||||
new FingerprintSensorPropertiesInternal(1 /* sensorId */,
|
new FingerprintSensorPropertiesInternal(1 /* sensorId */,
|
||||||
FingerprintSensorProperties.STRENGTH_STRONG,
|
FingerprintSensorProperties.STRENGTH_STRONG,
|
||||||
1 /* maxEnrollmentsPerUser */,
|
1 /* maxEnrollmentsPerUser */,
|
||||||
@@ -291,7 +290,11 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
|
|||||||
"1.01" /* firmwareVersion */,
|
"1.01" /* firmwareVersion */,
|
||||||
"00000001" /* serialNumber */, "" /* softwareVersion */)),
|
"00000001" /* serialNumber */, "" /* softwareVersion */)),
|
||||||
FingerprintSensorProperties.TYPE_UDFPS_OPTICAL,
|
FingerprintSensorProperties.TYPE_UDFPS_OPTICAL,
|
||||||
false /* resetLockoutRequiresHAT */)));
|
false /* resetLockoutRequiresHAT */));
|
||||||
|
when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
|
||||||
|
when(mFingerprintManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
|
||||||
|
when(mFingerprintManager.getSensorPropertiesInternal()).thenReturn(
|
||||||
|
mFingerprintSensorProperties);
|
||||||
when(mUserManager.isUserUnlocked(anyInt())).thenReturn(true);
|
when(mUserManager.isUserUnlocked(anyInt())).thenReturn(true);
|
||||||
when(mUserManager.isPrimaryUser()).thenReturn(true);
|
when(mUserManager.isPrimaryUser()).thenReturn(true);
|
||||||
when(mStrongAuthTracker.getStub()).thenReturn(mock(IStrongAuthTracker.Stub.class));
|
when(mStrongAuthTracker.getStub()).thenReturn(mock(IStrongAuthTracker.Stub.class));
|
||||||
@@ -769,6 +772,36 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
|
|||||||
anyBoolean());
|
anyBoolean());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void nofaceDetect_whenStrongAuthRequiredAndBypassUdfpsSupportedAndFpRunning() {
|
||||||
|
// GIVEN mocked keyguardUpdateMonitorCallback
|
||||||
|
KeyguardUpdateMonitorCallback keyguardUpdateMonitorCallback =
|
||||||
|
mock(KeyguardUpdateMonitorCallback.class);
|
||||||
|
mKeyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback);
|
||||||
|
|
||||||
|
// GIVEN bypass is enabled, face detection is supported
|
||||||
|
lockscreenBypassIsAllowed();
|
||||||
|
supportsFaceDetection();
|
||||||
|
keyguardIsVisible();
|
||||||
|
|
||||||
|
// GIVEN udfps is supported and strong auth required for weak biometrics (face) only
|
||||||
|
givenUdfpsSupported();
|
||||||
|
strongAuthRequiredForWeakBiometricOnly(); // this allows fingerprint to run but not face
|
||||||
|
|
||||||
|
// WHEN the device wakes up
|
||||||
|
mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
|
||||||
|
mTestableLooper.processAllMessages();
|
||||||
|
|
||||||
|
// THEN face detect and authenticate are NOT triggered
|
||||||
|
verify(mFaceManager, never()).detectFace(any(), any(), anyInt());
|
||||||
|
verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
|
||||||
|
anyBoolean());
|
||||||
|
|
||||||
|
// THEN biometric help message sent to callback
|
||||||
|
verify(keyguardUpdateMonitorCallback).onBiometricHelp(
|
||||||
|
eq(BIOMETRIC_HELP_FACE_NOT_AVAILABLE), anyString(), eq(BiometricSourceType.FACE));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void faceDetect_whenStrongAuthRequiredAndBypass() {
|
public void faceDetect_whenStrongAuthRequiredAndBypass() {
|
||||||
// GIVEN bypass is enabled, face detection is supported and strong auth is required
|
// GIVEN bypass is enabled, face detection is supported and strong auth is required
|
||||||
@@ -776,6 +809,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
|
|||||||
supportsFaceDetection();
|
supportsFaceDetection();
|
||||||
strongAuthRequiredEncrypted();
|
strongAuthRequiredEncrypted();
|
||||||
keyguardIsVisible();
|
keyguardIsVisible();
|
||||||
|
// fingerprint is NOT running, UDFPS is NOT supported
|
||||||
|
|
||||||
// WHEN the device wakes up
|
// WHEN the device wakes up
|
||||||
mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
|
mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
|
||||||
@@ -2466,6 +2500,11 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
|
|||||||
when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
|
when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void strongAuthRequiredForWeakBiometricOnly() {
|
||||||
|
when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(eq(true))).thenReturn(true);
|
||||||
|
when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(eq(false))).thenReturn(false);
|
||||||
|
}
|
||||||
|
|
||||||
private void strongAuthNotRequired() {
|
private void strongAuthNotRequired() {
|
||||||
when(mStrongAuthTracker.getStrongAuthForUser(KeyguardUpdateMonitor.getCurrentUser()))
|
when(mStrongAuthTracker.getStrongAuthForUser(KeyguardUpdateMonitor.getCurrentUser()))
|
||||||
.thenReturn(0);
|
.thenReturn(0);
|
||||||
@@ -2520,6 +2559,12 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
|
|||||||
mTestableLooper.processAllMessages();
|
mTestableLooper.processAllMessages();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void givenUdfpsSupported() {
|
||||||
|
Assert.assertFalse(mFingerprintSensorProperties.isEmpty());
|
||||||
|
when(mAuthController.getUdfpsProps()).thenReturn(mFingerprintSensorProperties);
|
||||||
|
Assert.assertTrue(mKeyguardUpdateMonitor.isUdfpsSupported());
|
||||||
|
}
|
||||||
|
|
||||||
private void setBroadcastReceiverPendingResult(BroadcastReceiver receiver) {
|
private void setBroadcastReceiverPendingResult(BroadcastReceiver receiver) {
|
||||||
BroadcastReceiver.PendingResult pendingResult =
|
BroadcastReceiver.PendingResult pendingResult =
|
||||||
new BroadcastReceiver.PendingResult(Activity.RESULT_OK,
|
new BroadcastReceiver.PendingResult(Activity.RESULT_OK,
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_T
|
|||||||
import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT;
|
import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT;
|
||||||
import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_TIMEOUT;
|
import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_TIMEOUT;
|
||||||
|
|
||||||
|
import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_AVAILABLE;
|
||||||
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.BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED;
|
||||||
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_ALIGNMENT;
|
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_ALIGNMENT;
|
||||||
@@ -619,6 +620,33 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
|
|||||||
mContext.getString(R.string.keyguard_suggest_fingerprint));
|
mContext.getString(R.string.keyguard_suggest_fingerprint));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onBiometricHelp_coEx_faceUnavailable() {
|
||||||
|
createController();
|
||||||
|
|
||||||
|
// GIVEN unlocking with fingerprint is possible
|
||||||
|
when(mKeyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible(anyInt()))
|
||||||
|
.thenReturn(true);
|
||||||
|
|
||||||
|
String message = "A message";
|
||||||
|
mController.setVisible(true);
|
||||||
|
|
||||||
|
// WHEN there's a face unavailable message
|
||||||
|
mController.getKeyguardCallback().onBiometricHelp(
|
||||||
|
BIOMETRIC_HELP_FACE_NOT_AVAILABLE,
|
||||||
|
message,
|
||||||
|
BiometricSourceType.FACE);
|
||||||
|
|
||||||
|
// THEN show sequential messages such as: 'face unlock unavailable' and
|
||||||
|
// 'try fingerprint instead'
|
||||||
|
verifyIndicationMessage(
|
||||||
|
INDICATION_TYPE_BIOMETRIC_MESSAGE,
|
||||||
|
message);
|
||||||
|
verifyIndicationMessage(
|
||||||
|
INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP,
|
||||||
|
mContext.getString(R.string.keyguard_suggest_fingerprint));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onBiometricHelp_coEx_fpFailure_faceAlreadyUnlocked() {
|
public void onBiometricHelp_coEx_fpFailure_faceAlreadyUnlocked() {
|
||||||
createController();
|
createController();
|
||||||
|
|||||||
Reference in New Issue
Block a user