Hide enrollment options that don't match requested biometric strength

When calling biometric enroll intent with biometric_strong, don't include
weak enrollments as options.

Bug: 265898482
Test: Tested manually by calling enrollment and verifying correct
options are shown
Test: atest BiometricEnrollActivityTest

Change-Id: I5fa650a593aee536955ae806f5963ffbdc135a2e
diff --git a/src/com/android/settings/biometrics/BiometricEnrollActivity.java b/src/com/android/settings/biometrics/BiometricEnrollActivity.java
index f0c1ed1..4d05946 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.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 @@
         // 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 @@
                 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 @@
 
     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<FingerprintSensorPropertiesInternal> fpProperties =
                     fpManager.getSensorPropertiesInternal();
@@ -287,8 +298,15 @@
                 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 @@
             }
         }
 
-        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 @@
         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 c5e3a19..0cb73c1 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 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.Test;
 import org.junit.runner.RunWith;
 
+import java.util.List;
+
 @RunWith(AndroidJUnit4.class)
 @MediumTest
 public class BiometricEnrollActivityTest {
@@ -67,6 +76,8 @@
     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 @@
         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<FaceSensorPropertiesInternal> 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<FingerprintSensorPropertiesInternal> fingerProperties =
+                    fingerprintManager.getSensorPropertiesInternal();
+            if (!fingerProperties.isEmpty()) {
+                final FingerprintSensorPropertiesInternal fingerProp = fingerProperties.get(0);
+                mIsFingerprintStrong =
+                        fingerProp.sensorStrength == SensorProperties.STRENGTH_STRONG;
+            }
+        }
     }
 
     @After
@@ -129,6 +162,27 @@
         }
     }
 
+    @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<BiometricEnrollActivity> 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 */);
     }