diff --git a/src/com/android/settings/biometrics/BiometricEnrollActivity.java b/src/com/android/settings/biometrics/BiometricEnrollActivity.java index 83f23bdcf7a..401abbe6621 100644 --- a/src/com/android/settings/biometrics/BiometricEnrollActivity.java +++ b/src/com/android/settings/biometrics/BiometricEnrollActivity.java @@ -335,7 +335,7 @@ public class BiometricEnrollActivity extends InstrumentedActivity { // enrollments already exists. if (!setupWizard && !mParentalOptionsRequired) { final BiometricManager bm = getSystemService(BiometricManager.class); - final @BiometricError int result = bm.canAuthenticate(authenticators); + final @BiometricError int result = bm.canAuthenticate(mUserId, authenticators); if (result != BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED) { Log.e(TAG, "Unexpected result (has enrollments): " + result); finish(); diff --git a/src/com/android/settings/safetycenter/BiometricSourcesUtils.java b/src/com/android/settings/safetycenter/BiometricSourcesUtils.java index 9cadbbb5fcf..786e3cf3865 100644 --- a/src/com/android/settings/safetycenter/BiometricSourcesUtils.java +++ b/src/com/android/settings/safetycenter/BiometricSourcesUtils.java @@ -19,11 +19,15 @@ package com.android.settings.safetycenter; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; +import android.hardware.face.FaceManager; +import android.hardware.fingerprint.FingerprintManager; import android.safetycenter.SafetyEvent; import android.safetycenter.SafetySourceData; import android.safetycenter.SafetySourceIssue; import android.safetycenter.SafetySourceStatus; +import com.android.settings.Utils; + /** Static helpers for setting SafetyCenter data for biometric safety sources. */ public final class BiometricSourcesUtils { @@ -89,6 +93,15 @@ public final class BiometricSourcesUtils { .setSafetySourceData(context, safetySourceId, safetySourceData, safetyEvent); } + /** Check whether the multiple biometrics enrollment is needed. */ + public static boolean isMultipleBiometricsEnrollmentNeeded(Context context, int userId) { + FaceManager faceManager = Utils.getFaceManagerOrNull(context); + FingerprintManager fingerprintManager = Utils.getFingerprintManagerOrNull(context); + return Utils.isMultipleBiometricsSupported(context) + && !faceManager.hasEnrolledTemplates(userId) + && !fingerprintManager.hasEnrolledFingerprints(userId); + } + /** Helper method for creating a pending intent. */ public static PendingIntent createPendingIntent( Context context, Intent intent, int requestCode) { diff --git a/src/com/android/settings/safetycenter/FaceSafetySource.java b/src/com/android/settings/safetycenter/FaceSafetySource.java index 73b6df56803..28754006d43 100644 --- a/src/com/android/settings/safetycenter/FaceSafetySource.java +++ b/src/com/android/settings/safetycenter/FaceSafetySource.java @@ -16,6 +16,7 @@ package com.android.settings.safetycenter; +import static com.android.settings.biometrics.BiometricEnrollActivity.EXTRA_LAUNCH_FACE_ENROLL_FIRST; import static com.android.settings.safetycenter.BiometricSourcesUtils.REQUEST_CODE_FACE_SETTING; import android.content.Context; @@ -27,6 +28,7 @@ import android.os.UserManager; import android.safetycenter.SafetyEvent; import com.android.settings.Utils; +import com.android.settings.biometrics.BiometricEnrollActivity; import com.android.settings.biometrics.BiometricNavigationUtils; import com.android.settings.biometrics.face.FaceStatusUtils; import com.android.settings.flags.Flags; @@ -73,6 +75,16 @@ public final class FaceSafetySource { Context profileParentContext = context.createContextAsUser(profileParentUserHandle, 0); if (Utils.hasFaceHardware(context)) { + boolean isMultipleBiometricsEnrollmentNeeded = + BiometricSourcesUtils.isMultipleBiometricsEnrollmentNeeded(context, userId); + String settingClassName = isMultipleBiometricsEnrollmentNeeded + ? BiometricEnrollActivity.InternalActivity.class.getName() + : faceStatusUtils.getSettingsClassName(); + Bundle bundle = new Bundle(); + if (isMultipleBiometricsEnrollmentNeeded) { + // Launch face enrollment first then fingerprint enrollment. + bundle.putBoolean(EXTRA_LAUNCH_FACE_ENROLL_FIRST, true); + } RestrictedLockUtils.EnforcedAdmin disablingAdmin = faceStatusUtils.getDisablingAdmin(); BiometricSourcesUtils.setBiometricSafetySourceData( SAFETY_SOURCE_ID, @@ -84,9 +96,9 @@ public final class FaceSafetySource { biometricNavigationUtils .getBiometricSettingsIntent( context, - faceStatusUtils.getSettingsClassName(), + settingClassName, disablingAdmin, - Bundle.EMPTY) + bundle) .setIdentifier(Integer.toString(userId)), REQUEST_CODE_FACE_SETTING), disablingAdmin == null /* enabled */, diff --git a/src/com/android/settings/safetycenter/FingerprintSafetySource.java b/src/com/android/settings/safetycenter/FingerprintSafetySource.java index 62f218bd519..6366783c19b 100644 --- a/src/com/android/settings/safetycenter/FingerprintSafetySource.java +++ b/src/com/android/settings/safetycenter/FingerprintSafetySource.java @@ -27,6 +27,7 @@ import android.os.UserManager; import android.safetycenter.SafetyEvent; import com.android.settings.Utils; +import com.android.settings.biometrics.BiometricEnrollActivity; import com.android.settings.biometrics.BiometricNavigationUtils; import com.android.settings.biometrics.fingerprint.FingerprintStatusUtils; import com.android.settings.flags.Flags; @@ -74,6 +75,11 @@ public final class FingerprintSafetySource { Context profileParentContext = context.createContextAsUser(profileParentUserHandle, 0); if (Utils.hasFingerprintHardware(context)) { + boolean isMultipleBiometricsEnrollmentNeeded = + BiometricSourcesUtils.isMultipleBiometricsEnrollmentNeeded(context, userId); + String settingClassName = isMultipleBiometricsEnrollmentNeeded + ? BiometricEnrollActivity.InternalActivity.class.getName() + : fingerprintStatusUtils.getSettingsClassName(); RestrictedLockUtils.EnforcedAdmin disablingAdmin = fingerprintStatusUtils.getDisablingAdmin(); BiometricSourcesUtils.setBiometricSafetySourceData( @@ -86,7 +92,7 @@ public final class FingerprintSafetySource { biometricNavigationUtils .getBiometricSettingsIntent( context, - fingerprintStatusUtils.getSettingsClassName(), + settingClassName, disablingAdmin, Bundle.EMPTY) .setIdentifier(Integer.toString(userId)), diff --git a/tests/unit/src/com/android/settings/safetycenter/FaceSafetySourceTest.java b/tests/unit/src/com/android/settings/safetycenter/FaceSafetySourceTest.java index 1d6f48f728c..1cb739592cd 100644 --- a/tests/unit/src/com/android/settings/safetycenter/FaceSafetySourceTest.java +++ b/tests/unit/src/com/android/settings/safetycenter/FaceSafetySourceTest.java @@ -37,6 +37,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.hardware.face.FaceManager; +import android.hardware.fingerprint.FingerprintManager; import android.os.UserHandle; import android.platform.test.annotations.DisableFlags; import android.platform.test.annotations.EnableFlags; @@ -52,6 +53,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import com.android.internal.widget.LockPatternUtils; import com.android.settings.Settings; +import com.android.settings.biometrics.BiometricEnrollActivity; import com.android.settings.biometrics.face.FaceEnrollIntroductionInternal; import com.android.settings.flags.Flags; import com.android.settings.testutils.FakeFeatureFactory; @@ -83,6 +85,7 @@ public class FaceSafetySourceTest { @Mock private PackageManager mPackageManager; @Mock private DevicePolicyManager mDevicePolicyManager; @Mock private FaceManager mFaceManager; + @Mock private FingerprintManager mFingerprintManager; @Mock private LockPatternUtils mLockPatternUtils; @Mock private SafetyCenterManagerWrapper mSafetyCenterManagerWrapper; @Mock private SupervisionManager mSupervisionManager; @@ -97,6 +100,8 @@ public class FaceSafetySourceTest { when(mApplicationContext.getSystemService(Context.DEVICE_POLICY_SERVICE)) .thenReturn(mDevicePolicyManager); when(mApplicationContext.getSystemService(Context.FACE_SERVICE)).thenReturn(mFaceManager); + when(mApplicationContext.getSystemService(Context.FINGERPRINT_SERVICE)) + .thenReturn(mFingerprintManager); when(mApplicationContext.getSystemService(Context.SUPERVISION_SERVICE)) .thenReturn(mSupervisionManager); FakeFeatureFactory featureFactory = FakeFeatureFactory.setupForTest(); @@ -211,10 +216,12 @@ public class FaceSafetySourceTest { @Test @RequiresFlagsEnabled(Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION) - public void setSafetySourceData_withFaceNotEnrolled_whenNotDisabledByAdmin_setsData() { + public void setSafetySourceData_onlyFaceNotEnrolled_whenNotDisabledByAdmin_setsData() { when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); when(mFaceManager.isHardwareDetected()).thenReturn(true); when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(false); + when(mFingerprintManager.isHardwareDetected()).thenReturn(true); + when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(true); when(mDevicePolicyManager.getKeyguardDisabledFeatures(COMPONENT_NAME)).thenReturn(0); FaceSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED); @@ -225,6 +232,24 @@ public class FaceSafetySourceTest { FaceEnrollIntroductionInternal.class.getName()); } + @Test + @RequiresFlagsEnabled(Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION) + public void setSafetySourceData_noBiometricEnrolled_whenNotDisabledByAdmin_setsData() { + when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); + when(mFaceManager.isHardwareDetected()).thenReturn(true); + when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(false); + when(mFingerprintManager.isHardwareDetected()).thenReturn(true); + when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(false); + when(mDevicePolicyManager.getKeyguardDisabledFeatures(COMPONENT_NAME)).thenReturn(0); + + FaceSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED); + + assertSafetySourceEnabledDataSetWithSingularSummary( + "security_settings_face_preference_title_new", + "security_settings_face_preference_summary_none_new", + BiometricEnrollActivity.InternalActivity.class.getName()); + } + @Test @RequiresFlagsEnabled(Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION) @DisableFlags(android.app.supervision.flags.Flags.FLAG_DEPRECATE_DPM_SUPERVISION_APIS) diff --git a/tests/unit/src/com/android/settings/safetycenter/FingerprintSafetySourceTest.java b/tests/unit/src/com/android/settings/safetycenter/FingerprintSafetySourceTest.java index dac2699ac71..980a2730e8b 100644 --- a/tests/unit/src/com/android/settings/safetycenter/FingerprintSafetySourceTest.java +++ b/tests/unit/src/com/android/settings/safetycenter/FingerprintSafetySourceTest.java @@ -36,6 +36,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; +import android.hardware.face.FaceManager; import android.hardware.fingerprint.Fingerprint; import android.hardware.fingerprint.FingerprintManager; import android.os.UserHandle; @@ -52,6 +53,7 @@ import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.android.internal.widget.LockPatternUtils; +import com.android.settings.biometrics.BiometricEnrollActivity; import com.android.settings.biometrics.fingerprint.FingerprintSettings; import com.android.settings.flags.Flags; import com.android.settings.testutils.FakeFeatureFactory; @@ -87,6 +89,7 @@ public class FingerprintSafetySourceTest { @Mock private PackageManager mPackageManager; @Mock private DevicePolicyManager mDevicePolicyManager; @Mock private FingerprintManager mFingerprintManager; + @Mock private FaceManager mFaceManager; @Mock private LockPatternUtils mLockPatternUtils; @Mock private SafetyCenterManagerWrapper mSafetyCenterManagerWrapper; @Mock private SupervisionManager mSupervisionManager; @@ -100,6 +103,7 @@ public class FingerprintSafetySourceTest { when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE)).thenReturn(true); when(mApplicationContext.getSystemService(Context.FINGERPRINT_SERVICE)) .thenReturn(mFingerprintManager); + when(mApplicationContext.getSystemService(Context.FACE_SERVICE)).thenReturn(mFaceManager); when(mApplicationContext.getSystemService(Context.DEVICE_POLICY_SERVICE)) .thenReturn(mDevicePolicyManager); when(mApplicationContext.getSystemService(Context.SUPERVISION_SERVICE)) @@ -228,10 +232,12 @@ public class FingerprintSafetySourceTest { @Test @RequiresFlagsEnabled(Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION) - public void setSafetySourceData_withFingerprintNotEnrolled_whenNotDisabledByAdmin_setsData() { + public void setSafetySourceData_onlyFingerprintNotEnrolled_whenNotDisabledByAdmin_setsData() { when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); when(mFingerprintManager.isHardwareDetected()).thenReturn(true); when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(false); + when(mFaceManager.isHardwareDetected()).thenReturn(true); + when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(true); when(mDevicePolicyManager.getKeyguardDisabledFeatures(COMPONENT_NAME)).thenReturn(0); FingerprintSafetySource.setSafetySourceData( @@ -243,6 +249,25 @@ public class FingerprintSafetySourceTest { FingerprintSettings.class.getName()); } + @Test + @RequiresFlagsEnabled(Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION) + public void setSafetySourceData_noBiometricEnrolled_whenNotDisabledByAdmin_setsData() { + when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); + when(mFingerprintManager.isHardwareDetected()).thenReturn(true); + when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(false); + when(mFaceManager.isHardwareDetected()).thenReturn(true); + when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(false); + when(mDevicePolicyManager.getKeyguardDisabledFeatures(COMPONENT_NAME)).thenReturn(0); + + FingerprintSafetySource.setSafetySourceData( + mApplicationContext, EVENT_SOURCE_STATE_CHANGED); + + assertSafetySourceEnabledDataSetWithSingularSummary( + "security_settings_fingerprint", + "security_settings_fingerprint_preference_summary_none_new", + BiometricEnrollActivity.InternalActivity.class.getName()); + } + @Test @RequiresFlagsEnabled(Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION) @DisableFlags(android.app.supervision.flags.Flags.FLAG_DEPRECATE_DPM_SUPERVISION_APIS)