Do not ignore lockout error from face if it's class3.
Test: atest AuthBiometricFingerprintAndFaceViewTest Bug: 277261318 Change-Id: Ibe971762f0dba4eabbd1b0f566e7df8e19b4422d
This commit is contained in:
@@ -1970,8 +1970,8 @@
|
||||
<string name="face_error_user_canceled">Face Unlock canceled by user</string>
|
||||
<!-- Generic error message shown when the face operation fails because too many attempts have been made. [CHAR LIMIT=50] -->
|
||||
<string name="face_error_lockout">Too many attempts. Try again later.</string>
|
||||
<!-- Generic error message shown when the face operation fails because strong authentication is required. [CHAR LIMIT=90] -->
|
||||
<string name="face_error_lockout_permanent">Too many attempts. Face Unlock disabled.</string>
|
||||
<!-- Generic error message shown when the face operation fails because strong authentication is required. [CHAR LIMIT=100] -->
|
||||
<string name="face_error_lockout_permanent">Too many attempts. Face Unlock unavailable.</string>
|
||||
<!-- Generic error message shown when the face operation fails because strong authentication is required. [CHAR LIMIT=90] -->
|
||||
<string name="face_error_lockout_screen_lock">Too many attempts. Enter screen lock instead.</string>
|
||||
<!-- Generic error message shown when the face hardware can't recognize the face. [CHAR LIMIT=50] -->
|
||||
|
||||
@@ -19,6 +19,8 @@ package com.android.systemui.biometrics
|
||||
import android.content.Context
|
||||
import android.hardware.biometrics.BiometricAuthenticator.Modality
|
||||
import android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE
|
||||
import android.hardware.biometrics.BiometricConstants
|
||||
import android.hardware.face.FaceManager
|
||||
import android.util.AttributeSet
|
||||
import com.android.systemui.R
|
||||
|
||||
@@ -27,6 +29,7 @@ class AuthBiometricFingerprintAndFaceView(
|
||||
context: Context,
|
||||
attrs: AttributeSet?
|
||||
) : AuthBiometricFingerprintView(context, attrs) {
|
||||
var isFaceClass3 = false
|
||||
|
||||
constructor (context: Context) : this(context, null)
|
||||
|
||||
@@ -34,10 +37,22 @@ class AuthBiometricFingerprintAndFaceView(
|
||||
|
||||
override fun forceRequireConfirmation(@Modality modality: Int) = modality == TYPE_FACE
|
||||
|
||||
override fun ignoreUnsuccessfulEventsFrom(@Modality modality: Int) = modality == TYPE_FACE
|
||||
override fun ignoreUnsuccessfulEventsFrom(@Modality modality: Int, unsuccessfulReason: String) =
|
||||
modality == TYPE_FACE && !(isFaceClass3 && isLockoutErrorString(unsuccessfulReason))
|
||||
|
||||
override fun onPointerDown(failedModalities: Set<Int>) = failedModalities.contains(TYPE_FACE)
|
||||
|
||||
override fun createIconController(): AuthIconController =
|
||||
AuthBiometricFingerprintAndFaceIconController(mContext, mIconView, mIconViewOverlay)
|
||||
|
||||
private fun isLockoutErrorString(unsuccessfulReason: String) =
|
||||
unsuccessfulReason == FaceManager.getErrorString(
|
||||
mContext,
|
||||
BiometricConstants.BIOMETRIC_ERROR_LOCKOUT,
|
||||
0 /*vendorCode */
|
||||
) || unsuccessfulReason == FaceManager.getErrorString(
|
||||
mContext,
|
||||
BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT,
|
||||
0 /*vendorCode */
|
||||
)
|
||||
}
|
||||
|
||||
@@ -258,7 +258,8 @@ public abstract class AuthBiometricView extends LinearLayout {
|
||||
}
|
||||
|
||||
/** Ignore all events from this (secondary) modality except successful authentication. */
|
||||
protected boolean ignoreUnsuccessfulEventsFrom(@Modality int modality) {
|
||||
protected boolean ignoreUnsuccessfulEventsFrom(@Modality int modality,
|
||||
String unsuccessfulReason) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -541,7 +542,7 @@ public abstract class AuthBiometricView extends LinearLayout {
|
||||
*/
|
||||
public void onAuthenticationFailed(
|
||||
@Modality int modality, @Nullable String failureReason) {
|
||||
if (ignoreUnsuccessfulEventsFrom(modality)) {
|
||||
if (ignoreUnsuccessfulEventsFrom(modality, failureReason)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -556,7 +557,7 @@ public abstract class AuthBiometricView extends LinearLayout {
|
||||
* @param error message
|
||||
*/
|
||||
public void onError(@Modality int modality, String error) {
|
||||
if (ignoreUnsuccessfulEventsFrom(modality)) {
|
||||
if (ignoreUnsuccessfulEventsFrom(modality, error)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -586,7 +587,7 @@ public abstract class AuthBiometricView extends LinearLayout {
|
||||
* @param help message
|
||||
*/
|
||||
public void onHelp(@Modality int modality, String help) {
|
||||
if (ignoreUnsuccessfulEventsFrom(modality)) {
|
||||
if (ignoreUnsuccessfulEventsFrom(modality, help)) {
|
||||
return;
|
||||
}
|
||||
if (mSize != AuthDialog.SIZE_MEDIUM) {
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.systemui.biometrics;
|
||||
|
||||
import static android.hardware.biometrics.BiometricManager.BIOMETRIC_MULTI_SENSOR_DEFAULT;
|
||||
import static android.hardware.biometrics.BiometricManager.BiometricMultiSensorMode;
|
||||
import static android.hardware.biometrics.SensorProperties.STRENGTH_STRONG;
|
||||
|
||||
import static com.android.internal.jank.InteractionJankMonitor.CUJ_BIOMETRIC_PROMPT_TRANSITION;
|
||||
|
||||
@@ -383,6 +384,8 @@ public class AuthContainerView extends LinearLayout
|
||||
fingerprintAndFaceView.setSensorProperties(fpProperties);
|
||||
fingerprintAndFaceView.setScaleFactorProvider(config.mScaleProvider);
|
||||
fingerprintAndFaceView.updateOverrideIconLayoutParamsSize();
|
||||
fingerprintAndFaceView.setFaceClass3(
|
||||
faceProperties.sensorStrength == STRENGTH_STRONG);
|
||||
mBiometricView = fingerprintAndFaceView;
|
||||
} else if (fpProperties != null) {
|
||||
final AuthBiometricFingerprintView fpView =
|
||||
|
||||
@@ -18,6 +18,8 @@ package com.android.systemui.biometrics
|
||||
|
||||
import android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE
|
||||
import android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT
|
||||
import android.hardware.biometrics.BiometricConstants
|
||||
import android.hardware.face.FaceManager
|
||||
import android.testing.TestableLooper
|
||||
import android.testing.TestableLooper.RunWithLooper
|
||||
import android.view.View
|
||||
@@ -34,6 +36,7 @@ import org.junit.runner.RunWith
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.never
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.Mockito.times
|
||||
import org.mockito.junit.MockitoJUnit
|
||||
|
||||
|
||||
@@ -98,7 +101,7 @@ class AuthBiometricFingerprintAndFaceViewTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun ignoresFaceErrors() {
|
||||
fun ignoresFaceErrors_faceIsNotClass3_notLockoutError() {
|
||||
biometricView.onDialogAnimatedIn()
|
||||
biometricView.onError(TYPE_FACE, "not a face")
|
||||
waitForIdleSync()
|
||||
@@ -113,5 +116,47 @@ class AuthBiometricFingerprintAndFaceViewTest : SysuiTestCase() {
|
||||
verify(callback).onAction(AuthBiometricView.Callback.ACTION_ERROR)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun doNotIgnoresFaceErrors_faceIsClass3_notLockoutError() {
|
||||
biometricView.isFaceClass3 = true
|
||||
biometricView.onDialogAnimatedIn()
|
||||
biometricView.onError(TYPE_FACE, "not a face")
|
||||
waitForIdleSync()
|
||||
|
||||
assertThat(biometricView.isAuthenticating).isTrue()
|
||||
verify(callback, never()).onAction(AuthBiometricView.Callback.ACTION_ERROR)
|
||||
|
||||
biometricView.onError(TYPE_FINGERPRINT, "that's a nope")
|
||||
TestableLooper.get(this).moveTimeForward(1000)
|
||||
waitForIdleSync()
|
||||
|
||||
verify(callback).onAction(AuthBiometricView.Callback.ACTION_ERROR)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun doNotIgnoresFaceErrors_faceIsClass3_lockoutError() {
|
||||
biometricView.isFaceClass3 = true
|
||||
biometricView.onDialogAnimatedIn()
|
||||
biometricView.onError(
|
||||
TYPE_FACE,
|
||||
FaceManager.getErrorString(
|
||||
biometricView.context,
|
||||
BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT,
|
||||
0 /*vendorCode */
|
||||
)
|
||||
)
|
||||
waitForIdleSync()
|
||||
|
||||
assertThat(biometricView.isAuthenticating).isTrue()
|
||||
verify(callback).onAction(AuthBiometricView.Callback.ACTION_ERROR)
|
||||
|
||||
biometricView.onError(TYPE_FINGERPRINT, "that's a nope")
|
||||
TestableLooper.get(this).moveTimeForward(1000)
|
||||
waitForIdleSync()
|
||||
|
||||
verify(callback, times(2)).onAction(AuthBiometricView.Callback.ACTION_ERROR)
|
||||
}
|
||||
|
||||
|
||||
override fun waitForIdleSync() = TestableLooper.get(this).processAllMessages()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user