diff --git a/src/com/android/settings/biometrics/BiometricEnrollActivity.java b/src/com/android/settings/biometrics/BiometricEnrollActivity.java index f0c1ed1a00b..4d05946f18c 100644 --- a/src/com/android/settings/biometrics/BiometricEnrollActivity.java +++ b/src/com/android/settings/biometrics/BiometricEnrollActivity.java @@ -35,6 +35,7 @@ import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricManager; import android.hardware.biometrics.BiometricManager.Authenticators; import android.hardware.biometrics.BiometricManager.BiometricError; +import android.hardware.biometrics.SensorProperties; import android.hardware.face.FaceManager; import android.hardware.face.FaceSensorPropertiesInternal; import android.hardware.fingerprint.FingerprintManager; @@ -198,7 +199,7 @@ public class BiometricEnrollActivity extends InstrumentedActivity { // Default behavior is to enroll BIOMETRIC_WEAK or above. See ACTION_BIOMETRIC_ENROLL. final int authenticators = getIntent().getIntExtra( EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED, Authenticators.BIOMETRIC_WEAK); - Log.d(TAG, "Authenticators: " + authenticators); + Log.d(TAG, "Authenticators: " + BiometricManager.authenticatorToStr(authenticators)); mParentalOptionsRequired = intent.getBooleanExtra(EXTRA_REQUIRE_PARENTAL_CONSENT, false); mSkipReturnToParent = intent.getBooleanExtra(EXTRA_SKIP_RETURN_TO_PARENT, false); @@ -222,9 +223,16 @@ public class BiometricEnrollActivity extends InstrumentedActivity { final FaceSensorPropertiesInternal props = faceProperties.get(0); final int maxEnrolls = isSetupWizard ? maxFacesEnrollableIfSUW : props.maxEnrollmentsPerUser; + final boolean isFaceStrong = + props.sensorStrength == SensorProperties.STRENGTH_STRONG; mIsFaceEnrollable = faceManager.getEnrolledFaces(mUserId).size() < maxEnrolls; + // If we expect strong bio only, check if face is strong + if (authenticators == Authenticators.BIOMETRIC_STRONG && !isFaceStrong) { + mIsFaceEnrollable = false; + } + final boolean parentalConsent = isSetupWizard || (mParentalOptionsRequired && !WizardManagerHelper.isUserSetupComplete(this)); if (parentalConsent && isMultiSensor && mIsFaceEnrollable) { @@ -278,6 +286,9 @@ public class BiometricEnrollActivity extends InstrumentedActivity { private void updateFingerprintEnrollable(boolean isSetupWizard) { if (mHasFeatureFingerprint) { + final int authenticators = getIntent().getIntExtra( + EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED, Authenticators.BIOMETRIC_WEAK); + final FingerprintManager fpManager = getSystemService(FingerprintManager.class); final List fpProperties = fpManager.getSensorPropertiesInternal(); @@ -287,8 +298,15 @@ public class BiometricEnrollActivity extends InstrumentedActivity { final int maxEnrolls = isSetupWizard ? maxFingerprintsEnrollableIfSUW : fpProperties.get(0).maxEnrollmentsPerUser; + final boolean isFingerprintStrong = + fpProperties.get(0).sensorStrength == SensorProperties.STRENGTH_STRONG; mIsFingerprintEnrollable = fpManager.getEnrolledFingerprints(mUserId).size() < maxEnrolls; + + // If we expect strong bio only, check if fingerprint is strong + if (authenticators == Authenticators.BIOMETRIC_STRONG && !isFingerprintStrong) { + mIsFingerprintEnrollable = false; + } } } } @@ -308,8 +326,8 @@ public class BiometricEnrollActivity extends InstrumentedActivity { } } - boolean canUseFace = mHasFeatureFace; - boolean canUseFingerprint = mHasFeatureFingerprint; + boolean canUseFace = mIsFaceEnrollable; + boolean canUseFingerprint = mIsFingerprintEnrollable; if (mParentalOptionsRequired) { if (mParentalOptions == null) { throw new IllegalStateException("consent options required, but not set"); @@ -612,11 +630,11 @@ public class BiometricEnrollActivity extends InstrumentedActivity { Intent intent = BiometricUtils.getChooseLockIntent(this, getIntent()); intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.HIDE_INSECURE_OPTIONS, true); intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, true); - if (mHasFeatureFingerprint && mHasFeatureFace) { + if (mIsFingerprintEnrollable && mIsFaceEnrollable) { intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS, true); - } else if (mHasFeatureFace) { + } else if (mIsFaceEnrollable) { intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, true); - } else if (mHasFeatureFingerprint) { + } else if (mIsFingerprintEnrollable) { intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, true); } diff --git a/tests/componenttests/src/com/android/settings/biometrics/BiometricEnrollActivityTest.java b/tests/componenttests/src/com/android/settings/biometrics/BiometricEnrollActivityTest.java index c5e3a19cc92..0cb73c17cad 100644 --- a/tests/componenttests/src/com/android/settings/biometrics/BiometricEnrollActivityTest.java +++ b/tests/componenttests/src/com/android/settings/biometrics/BiometricEnrollActivityTest.java @@ -16,6 +16,7 @@ package com.android.settings.biometrics; +import static android.hardware.biometrics.BiometricManager.Authenticators.BIOMETRIC_STRONG; import static android.provider.Settings.ACTION_BIOMETRIC_ENROLL; import static androidx.test.espresso.intent.Intents.intended; @@ -33,7 +34,13 @@ import static org.junit.Assume.assumeTrue; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; +import android.hardware.biometrics.SensorProperties; +import android.hardware.face.FaceManager; +import android.hardware.face.FaceSensorPropertiesInternal; +import android.hardware.fingerprint.FingerprintManager; +import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.os.UserHandle; +import android.provider.Settings; import androidx.test.core.app.ActivityScenario; import androidx.test.core.app.ApplicationProvider; @@ -56,6 +63,8 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.List; + @RunWith(AndroidJUnit4.class) @MediumTest public class BiometricEnrollActivityTest { @@ -67,6 +76,8 @@ public class BiometricEnrollActivityTest { private final Context mContext = ApplicationProvider.getApplicationContext(); private boolean mHasFace; private boolean mHasFingerprint; + private boolean mIsFaceStrong; + private boolean mIsFingerprintStrong; @Before public void setup() { @@ -74,6 +85,28 @@ public class BiometricEnrollActivityTest { final PackageManager pm = mContext.getPackageManager(); mHasFingerprint = pm.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT); mHasFace = pm.hasSystemFeature(PackageManager.FEATURE_FACE); + + if (mHasFace) { + final FaceManager faceManager = mContext.getSystemService(FaceManager.class); + final List faceProperties = + faceManager.getSensorPropertiesInternal(); + if (!faceProperties.isEmpty()) { + final FaceSensorPropertiesInternal faceProp = faceProperties.get(0); + mIsFaceStrong = faceProp.sensorStrength == SensorProperties.STRENGTH_STRONG; + } + } + + if (mHasFingerprint) { + final FingerprintManager fingerprintManager = mContext.getSystemService( + FingerprintManager.class); + final List fingerProperties = + fingerprintManager.getSensorPropertiesInternal(); + if (!fingerProperties.isEmpty()) { + final FingerprintSensorPropertiesInternal fingerProp = fingerProperties.get(0); + mIsFingerprintStrong = + fingerProp.sensorStrength == SensorProperties.STRENGTH_STRONG; + } + } } @After @@ -129,6 +162,27 @@ public class BiometricEnrollActivityTest { } } + @Test + public void launchWithStrongBiometricAllowed_doNotEnrollWeak() throws Exception { + assumeTrue(mHasFace || mHasFingerprint); + + // Allow only strong biometrics + Intent intent = getIntent(); + intent.putExtra(Settings.EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED, BIOMETRIC_STRONG); + + try (ActivityScenario scenario = + ActivityScenario.launch(intent)) { + intended(hasComponent(ChooseLockGeneric.class.getName())); + if (mIsFaceStrong && mIsFingerprintStrong) { + intended(hasExtra(EXTRA_KEY_FOR_BIOMETRICS, true)); + } else if (mIsFaceStrong) { + intended(hasExtra(EXTRA_KEY_FOR_FACE, true)); + } else if (mIsFingerprintStrong) { + intended(hasExtra(EXTRA_KEY_FOR_FINGERPRINT, true)); + } + } + } + private Intent getIntent() { return getIntent(false /* useInternal */); }