Split enabledForApp & enabledOnKeyguard settings for FP and Face

Make fingerprint & face have their own set of setting keys of
enablaedForApps and enabledForKeyguard.

Bug: 370940762
Test: atest AuthSessionTest
            BiometricServiceTest
	    PreAuthInfoTest
	    KeyguardUpdateMonitorTest
	    BiometricSettingsRepositoryTest
	    SettingsBackupTest
Flag: com.android.settings.flags.biometrics_onboarding_education

Change-Id: Ia7156828d0bce2bbf0389431d3d5299f646bbffe
diff --git a/core/java/android/hardware/biometrics/IBiometricEnabledOnKeyguardCallback.aidl b/core/java/android/hardware/biometrics/IBiometricEnabledOnKeyguardCallback.aidl
index 1268658..cf25b7e 100644
--- a/core/java/android/hardware/biometrics/IBiometricEnabledOnKeyguardCallback.aidl
+++ b/core/java/android/hardware/biometrics/IBiometricEnabledOnKeyguardCallback.aidl
@@ -20,5 +20,5 @@
  * @hide
  */
 oneway interface IBiometricEnabledOnKeyguardCallback {
-    void onChanged(boolean enabled, int userId);
+    void onChanged(boolean enabled, int userId, int modality);
 }
\ No newline at end of file
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 73d1e17..7d067fb 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -11346,17 +11346,54 @@
 
         /**
          * Whether or not biometric is allowed on Keyguard.
+         *
+         * @deprecated Use {@link #FINGERPRINT_KEYGUARD_ENABLED} or {@link #FACE_KEYGUARD_ENABLED}
+         * instead.
+         *
          * @hide
          */
+        @Deprecated
         @Readable
         public static final String BIOMETRIC_KEYGUARD_ENABLED = "biometric_keyguard_enabled";
 
         /**
          * Whether or not biometric is allowed for apps (through BiometricPrompt).
+         *
+         * @deprecated Use {@link #FINGERPRINT_APP_ENABLED} or {@link #FACE_APP_ENABLED} instead.
+         *
+         * @hide
+         */
+        @Deprecated
+        @Readable
+        public static final String BIOMETRIC_APP_ENABLED = "biometric_app_enabled";
+
+        /**
+         * Whether or not fingerprint is allowed on Keyguard.
          * @hide
          */
         @Readable
-        public static final String BIOMETRIC_APP_ENABLED = "biometric_app_enabled";
+        public static final String FINGERPRINT_KEYGUARD_ENABLED = "fingerprint_keyguard_enabled";
+
+        /**
+         * Whether or not fingerprint is allowed for apps (through BiometricPrompt).
+         * @hide
+         */
+        @Readable
+        public static final String FINGERPRINT_APP_ENABLED = "fingerptint_app_enabled";
+
+        /**
+         * Whether or not face is allowed on Keyguard.
+         * @hide
+         */
+        @Readable
+        public static final String FACE_KEYGUARD_ENABLED = "face_keyguard_enabled";
+
+        /**
+         * Whether or not face is allowed for apps (through BiometricPrompt).
+         * @hide
+         */
+        @Readable
+        public static final String FACE_APP_ENABLED = "face_app_enabled";
 
         /**
          * Whether or not mandatory biometrics is enabled.
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index 7b4a2ca..7aef657 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -287,5 +287,9 @@
         Settings.Secure.ADVANCED_PROTECTION_MODE,
         Settings.Secure.ACCESSIBILITY_KEY_GESTURE_TARGETS,
         Settings.Secure.EM_VALUE,
+        Settings.Secure.FACE_APP_ENABLED,
+        Settings.Secure.FACE_KEYGUARD_ENABLED,
+        Settings.Secure.FINGERPRINT_APP_ENABLED,
+        Settings.Secure.FINGERPRINT_KEYGUARD_ENABLED,
     };
 }
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index 6681c014..43ceda7 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -455,5 +455,9 @@
                 new InclusiveIntegerRangeValidator(0, 1));
         VALIDATORS.put(Secure.ADVANCED_PROTECTION_MODE, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.DISABLE_ADAPTIVE_AUTH_LIMIT_LOCK, BOOLEAN_VALIDATOR);
+        VALIDATORS.put(Secure.FACE_APP_ENABLED,  BOOLEAN_VALIDATOR);
+        VALIDATORS.put(Secure.FACE_KEYGUARD_ENABLED,  BOOLEAN_VALIDATOR);
+        VALIDATORS.put(Secure.FINGERPRINT_APP_ENABLED,  BOOLEAN_VALIDATOR);
+        VALIDATORS.put(Secure.FINGERPRINT_KEYGUARD_ENABLED, BOOLEAN_VALIDATOR);
     }
 }
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index a935aac..67a9064 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -521,6 +521,7 @@
         "androidx.compose.animation_animation-graphics",
         "androidx.lifecycle_lifecycle-viewmodel-compose",
         "kairos",
+        "aconfig_settings_flags_lib",
     ],
     libs: [
         "keepanno-annotations",
@@ -702,6 +703,7 @@
         "androidx.lifecycle_lifecycle-viewmodel-compose",
         "TraceurCommon",
         "Traceur-res",
+        "aconfig_settings_flags_lib",
     ],
 }
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt
index 69fb03d..4e8a2a3 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt
@@ -22,8 +22,12 @@
 import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT
 import android.content.Intent
 import android.content.pm.UserInfo
+import android.hardware.biometrics.BiometricAuthenticator.TYPE_ANY_BIOMETRIC
+import android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE
+import android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT
 import android.hardware.biometrics.BiometricManager
 import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback
+import android.platform.test.annotations.EnableFlags
 import android.testing.TestableLooper
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
@@ -75,6 +79,8 @@
 import org.mockito.Mockito.times
 import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.stub
 
 @OptIn(ExperimentalCoroutinesApi::class)
 @SmallTest
@@ -153,7 +159,7 @@
     fun fingerprintEnrollmentChange() =
         testScope.runTest {
             createBiometricSettingsRepository()
-            biometricsAreEnabledBySettings()
+            biometricsAreEnabledBySettings(PRIMARY_USER_ID, TYPE_FINGERPRINT)
             val fingerprintAllowed = collectLastValue(underTest.isFingerprintEnrolledAndEnabled)
             runCurrent()
 
@@ -173,7 +179,7 @@
     fun fingerprintEnabledStateChange() =
         testScope.runTest {
             createBiometricSettingsRepository()
-            biometricsAreEnabledBySettings()
+            biometricsAreEnabledBySettings(PRIMARY_USER_ID, TYPE_FINGERPRINT)
             val fingerprintAllowed = collectLastValue(underTest.isFingerprintEnrolledAndEnabled)
             runCurrent()
 
@@ -183,21 +189,59 @@
             assertThat(fingerprintAllowed()).isTrue()
 
             // when biometrics are not enabled by settings
-            biometricsAreNotEnabledBySettings()
+            biometricsAreNotEnabledBySettings(PRIMARY_USER_ID, TYPE_FINGERPRINT)
             assertThat(fingerprintAllowed()).isFalse()
 
             // when biometrics are enabled by settings
-            biometricsAreEnabledBySettings()
+            biometricsAreEnabledBySettings(PRIMARY_USER_ID, TYPE_FINGERPRINT)
             assertThat(fingerprintAllowed()).isTrue()
         }
 
     @Test
+    @EnableFlags(com.android.settings.flags.Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION)
+    fun enabledStateChange_typeFingerprintEnabled_typeFaceDisabled() =
+        testScope.runTest {
+            createBiometricSettingsRepository()
+            biometricsAreEnabledBySettings(PRIMARY_USER_ID, TYPE_FINGERPRINT)
+            val fingerprintAllowed = collectLastValue(underTest.isFingerprintEnrolledAndEnabled)
+            val faceAllowed = collectLastValue(underTest.isFaceAuthEnrolledAndEnabled)
+            runCurrent()
+
+            // start state
+            authController.stub {
+                on { isFingerprintEnrolled(anyInt()) } doReturn true
+            }
+            enrollmentChange(UNDER_DISPLAY_FINGERPRINT, PRIMARY_USER_ID, true)
+            assertThat(fingerprintAllowed()).isTrue()
+            assertThat(faceAllowed()).isFalse()
+        }
+
+    @Test
+    @EnableFlags(com.android.settings.flags.Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION)
+    fun enabledStateChange_typeFingerprintDisabled_typeFaceEnabled() =
+        testScope.runTest {
+            createBiometricSettingsRepository()
+            biometricsAreEnabledBySettings(PRIMARY_USER_ID, TYPE_FACE)
+            val fingerprintAllowed = collectLastValue(underTest.isFingerprintEnrolledAndEnabled)
+            val faceAllowed = collectLastValue(underTest.isFaceAuthEnrolledAndEnabled)
+            runCurrent()
+
+            // start state
+            authController.stub {
+                on { isFaceAuthEnrolled(anyInt()) } doReturn true
+            }
+            enrollmentChange(FACE, PRIMARY_USER_ID, true)
+            assertThat(fingerprintAllowed()).isFalse()
+            assertThat(faceAllowed()).isTrue()
+        }
+
+    @Test
     fun strongBiometricAllowedChange() =
         testScope.runTest {
             fingerprintIsEnrolled()
             doNotDisableKeyguardAuthFeatures()
             createBiometricSettingsRepository()
-            biometricsAreEnabledBySettings()
+            biometricsAreEnabledBySettings(PRIMARY_USER_ID, TYPE_FINGERPRINT)
 
             val strongBiometricAllowed by
                 collectLastValue(underTest.isFingerprintAuthCurrentlyAllowed)
@@ -220,7 +264,7 @@
             createBiometricSettingsRepository()
             val convenienceFaceAuthAllowed by collectLastValue(underTest.isFaceAuthCurrentlyAllowed)
             doNotDisableKeyguardAuthFeatures()
-            biometricsAreEnabledBySettings()
+            biometricsAreEnabledBySettings(PRIMARY_USER_ID, TYPE_FACE)
 
             onStrongAuthChanged(STRONG_AUTH_NOT_REQUIRED, PRIMARY_USER_ID)
             onNonStrongAuthChanged(true, PRIMARY_USER_ID)
@@ -282,7 +326,7 @@
             faceAuthIsEnrolled()
             createBiometricSettingsRepository()
             doNotDisableKeyguardAuthFeatures()
-            biometricsAreEnabledBySettings()
+            biometricsAreEnabledBySettings(PRIMARY_USER_ID, TYPE_FACE)
             runCurrent()
 
             val convenienceBiometricAllowed by
@@ -315,7 +359,7 @@
         testScope.runTest {
             fingerprintIsEnrolled(PRIMARY_USER_ID)
             createBiometricSettingsRepository()
-            biometricsAreEnabledBySettings()
+            biometricsAreEnabledBySettings(PRIMARY_USER_ID, TYPE_FINGERPRINT)
 
             val fingerprintEnabledByDevicePolicy =
                 collectLastValue(underTest.isFingerprintEnrolledAndEnabled)
@@ -341,7 +385,7 @@
             createBiometricSettingsRepository()
             val faceAuthAllowed = collectLastValue(underTest.isFaceAuthEnrolledAndEnabled)
 
-            biometricsAreEnabledBySettings()
+            biometricsAreEnabledBySettings(PRIMARY_USER_ID, TYPE_FACE)
 
             doNotDisableKeyguardAuthFeatures(PRIMARY_USER_ID)
 
@@ -376,16 +420,22 @@
             assertThat(faceAuthAllowed()).isTrue()
         }
 
-    private fun biometricsAreEnabledBySettings(userId: Int = PRIMARY_USER_ID) {
+    private fun biometricsAreEnabledBySettings(
+        userId: Int = PRIMARY_USER_ID,
+        modality: Int = TYPE_ANY_BIOMETRIC,
+    ) {
         verify(biometricManager, atLeastOnce())
             .registerEnabledOnKeyguardCallback(biometricManagerCallback.capture())
-        biometricManagerCallback.value.onChanged(true, userId)
+        biometricManagerCallback.value.onChanged(true, userId, modality)
     }
 
-    private fun biometricsAreNotEnabledBySettings(userId: Int = PRIMARY_USER_ID) {
+    private fun biometricsAreNotEnabledBySettings(
+        userId: Int = PRIMARY_USER_ID,
+        modality: Int = TYPE_ANY_BIOMETRIC,
+    ) {
         verify(biometricManager, atLeastOnce())
             .registerEnabledOnKeyguardCallback(biometricManagerCallback.capture())
-        biometricManagerCallback.value.onChanged(false, userId)
+        biometricManagerCallback.value.onChanged(false, userId, modality)
     }
 
     @Test
@@ -413,7 +463,7 @@
 
             userRepository.setSelectedUserInfo(ANOTHER_USER)
             doNotDisableKeyguardAuthFeatures(ANOTHER_USER_ID)
-            biometricManagerCallback.value.onChanged(true, ANOTHER_USER_ID)
+            biometricManagerCallback.value.onChanged(true, ANOTHER_USER_ID, TYPE_FACE)
             onNonStrongAuthChanged(true, ANOTHER_USER_ID)
             whenever(authController.isFaceAuthEnrolled(ANOTHER_USER_ID)).thenReturn(true)
             enrollmentChange(FACE, ANOTHER_USER_ID, true)
@@ -441,7 +491,7 @@
 
             assertThat(isFaceAuthAllowed()).isFalse()
 
-            biometricManagerCallback.value.onChanged(true, PRIMARY_USER_ID)
+            biometricManagerCallback.value.onChanged(true, PRIMARY_USER_ID, TYPE_FACE)
             runCurrent()
             assertThat(isFaceAuthAllowed()).isFalse()
 
@@ -458,7 +508,7 @@
             faceAuthIsEnrolled()
             createBiometricSettingsRepository()
 
-            biometricsAreEnabledBySettings()
+            biometricsAreEnabledBySettings(PRIMARY_USER_ID, TYPE_FACE)
             doNotDisableKeyguardAuthFeatures()
             mobileConnectionsRepository.fake.isAnySimSecure.value = false
             runCurrent()
@@ -485,7 +535,7 @@
             deviceIsInPostureThatSupportsFaceAuth()
             doNotDisableKeyguardAuthFeatures()
             faceAuthIsStrongBiometric()
-            biometricsAreEnabledBySettings()
+            biometricsAreEnabledBySettings(PRIMARY_USER_ID, TYPE_FACE)
             mobileConnectionsRepository.fake.isAnySimSecure.value = false
 
             onStrongAuthChanged(STRONG_AUTH_NOT_REQUIRED, PRIMARY_USER_ID)
@@ -512,12 +562,12 @@
             assertThat(isFaceAuthAllowed()).isFalse()
 
             // Value changes for another user
-            biometricManagerCallback.value.onChanged(true, ANOTHER_USER_ID)
+            biometricManagerCallback.value.onChanged(true, ANOTHER_USER_ID, TYPE_FACE)
 
             assertThat(isFaceAuthAllowed()).isFalse()
 
             // Value changes for current user.
-            biometricManagerCallback.value.onChanged(true, PRIMARY_USER_ID)
+            biometricManagerCallback.value.onChanged(true, PRIMARY_USER_ID, TYPE_FACE)
 
             assertThat(isFaceAuthAllowed()).isTrue()
         }
@@ -537,13 +587,13 @@
                 .registerEnabledOnKeyguardCallback(biometricManagerCallback.capture())
             val isFingerprintEnrolledAndEnabled =
                 collectLastValue(underTest.isFingerprintEnrolledAndEnabled)
-            biometricManagerCallback.value.onChanged(true, ANOTHER_USER_ID)
+            biometricManagerCallback.value.onChanged(true, ANOTHER_USER_ID, TYPE_FINGERPRINT)
             runCurrent()
             userRepository.setSelectedUserInfo(ANOTHER_USER)
             runCurrent()
             assertThat(isFingerprintEnrolledAndEnabled()).isFalse()
 
-            biometricManagerCallback.value.onChanged(true, PRIMARY_USER_ID)
+            biometricManagerCallback.value.onChanged(true, PRIMARY_USER_ID, TYPE_FINGERPRINT)
             runCurrent()
             userRepository.setSelectedUserInfo(PRIMARY_USER)
             runCurrent()
@@ -559,7 +609,7 @@
             verify(biometricManager)
                 .registerEnabledOnKeyguardCallback(biometricManagerCallback.capture())
             val isFaceAuthAllowed = collectLastValue(underTest.isFaceAuthEnrolledAndEnabled)
-            biometricManagerCallback.value.onChanged(true, ANOTHER_USER_ID)
+            biometricManagerCallback.value.onChanged(true, ANOTHER_USER_ID, TYPE_FACE)
             runCurrent()
 
             userRepository.setSelectedUserInfo(ANOTHER_USER)
@@ -691,7 +741,7 @@
             deviceIsInPostureThatSupportsFaceAuth()
             doNotDisableKeyguardAuthFeatures()
             faceAuthIsStrongBiometric()
-            biometricsAreEnabledBySettings()
+            biometricsAreEnabledBySettings(PRIMARY_USER_ID, TYPE_FACE)
 
             onStrongAuthChanged(STRONG_AUTH_NOT_REQUIRED, PRIMARY_USER_ID)
             onNonStrongAuthChanged(false, PRIMARY_USER_ID)
@@ -715,7 +765,7 @@
             deviceIsInPostureThatSupportsFaceAuth()
             doNotDisableKeyguardAuthFeatures()
             faceAuthIsNonStrongBiometric()
-            biometricsAreEnabledBySettings()
+            biometricsAreEnabledBySettings(PRIMARY_USER_ID, TYPE_FACE)
 
             onStrongAuthChanged(STRONG_AUTH_NOT_REQUIRED, PRIMARY_USER_ID)
             onNonStrongAuthChanged(false, PRIMARY_USER_ID)
@@ -737,7 +787,7 @@
     fun fpAuthCurrentlyAllowed_dependsOnNonStrongAuthBiometricSetting_ifFpIsNotStrong() =
         testScope.runTest {
             createBiometricSettingsRepository()
-            biometricsAreEnabledBySettings()
+            biometricsAreEnabledBySettings(PRIMARY_USER_ID, TYPE_FINGERPRINT)
             val isFingerprintCurrentlyAllowed by
                 collectLastValue(underTest.isFingerprintAuthCurrentlyAllowed)
 
@@ -779,7 +829,7 @@
     fun fpAuthCurrentlyAllowed_dependsOnStrongAuthBiometricSetting_ifFpIsStrong() =
         testScope.runTest {
             createBiometricSettingsRepository()
-            biometricsAreEnabledBySettings()
+            biometricsAreEnabledBySettings(PRIMARY_USER_ID, TYPE_FINGERPRINT)
             val isFingerprintCurrentlyAllowed by
                 collectLastValue(underTest.isFingerprintAuthCurrentlyAllowed)
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 7d291c3..61038ef 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -437,8 +437,12 @@
     private final IBiometricEnabledOnKeyguardCallback mBiometricEnabledCallback =
             new IBiometricEnabledOnKeyguardCallback.Stub() {
                 @Override
-                public void onChanged(boolean enabled, int userId) {
+                public void onChanged(boolean enabled, int userId, int modality) {
                     mHandler.post(() -> {
+                        if (com.android.settings.flags.Flags.biometricsOnboardingEducation()
+                                && modality != TYPE_FINGERPRINT) {
+                            return;
+                        }
                         mBiometricEnabledForUser.put(userId, enabled);
                         updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE);
                     });
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt
index ab8cc71..4e7de5d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt
@@ -20,6 +20,9 @@
 import android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED
 import android.content.Context
 import android.content.IntentFilter
+import android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE
+import android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT
+import android.hardware.biometrics.BiometricAuthenticator.TYPE_NONE
 import android.hardware.biometrics.BiometricManager
 import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback
 import android.os.UserHandle
@@ -141,6 +144,8 @@
 ) : BiometricSettingsRepository, Dumpable {
 
     private val biometricsEnabledForUser = mutableMapOf<Int, Boolean>()
+    private val fingerprintEnabledForUser = mutableMapOf<Int, Boolean>()
+    private val faceEnabledForUser = mutableMapOf<Int, Boolean>()
 
     override val isFaceAuthSupportedInCurrentPosture: Flow<Boolean>
 
@@ -246,10 +251,25 @@
             }
         }
 
-    private val areBiometricsEnabledForCurrentUser: Flow<Boolean> =
+    private val isFingerprintEnabledForCurrentUser: Flow<Boolean> =
         userRepository.selectedUserInfo.flatMapLatest { userInfo ->
             areBiometricsEnabledForDeviceEntryFromUserSetting.map {
-                biometricsEnabledForUser[userInfo.id] ?: false
+                if (com.android.settings.flags.Flags.biometricsOnboardingEducation()) {
+                    fingerprintEnabledForUser[userInfo.id] ?: false
+                } else {
+                    biometricsEnabledForUser[userInfo.id] ?: false
+                }
+            }
+        }
+
+    private val isFaceEnabledForCurrentUser: Flow<Boolean> =
+        userRepository.selectedUserInfo.flatMapLatest { userInfo ->
+            areBiometricsEnabledForDeviceEntryFromUserSetting.map {
+                if (com.android.settings.flags.Flags.biometricsOnboardingEducation()) {
+                    faceEnabledForUser[userInfo.id] ?: false
+                } else {
+                    biometricsEnabledForUser[userInfo.id] ?: false
+                }
             }
         }
 
@@ -264,31 +284,44 @@
             .distinctUntilChanged()
 
     private val isFaceAuthenticationEnabled: Flow<Boolean> =
-        combine(areBiometricsEnabledForCurrentUser, isFaceEnabledByDevicePolicy) {
+        combine(isFaceEnabledForCurrentUser, isFaceEnabledByDevicePolicy) {
             biometricsManagerSetting,
             devicePolicySetting ->
             biometricsManagerSetting && devicePolicySetting
         }
 
-    private val areBiometricsEnabledForDeviceEntryFromUserSetting: Flow<Pair<Int, Boolean>> =
+    private val areBiometricsEnabledForDeviceEntryFromUserSetting: Flow<Triple<Int, Boolean, Int>> =
         conflatedCallbackFlow {
                 val callback =
                     object : IBiometricEnabledOnKeyguardCallback.Stub() {
-                        override fun onChanged(enabled: Boolean, userId: Int) {
+                        override fun onChanged(enabled: Boolean, userId: Int, modality: Int) {
                             trySendWithFailureLogging(
-                                Pair(userId, enabled),
+                                Triple(userId, enabled, modality),
                                 TAG,
-                                "biometricsEnabled state changed"
+                                "biometricsEnabled state changed",
                             )
                         }
                     }
                 biometricManager?.registerEnabledOnKeyguardCallback(callback)
                 awaitClose {}
             }
-            .onEach { biometricsEnabledForUser[it.first] = it.second }
+            .onEach {
+                if (com.android.settings.flags.Flags.biometricsOnboardingEducation()) {
+                    when (it.third) {
+                        TYPE_FACE -> {
+                            faceEnabledForUser[it.first] = it.second
+                        }
+                        TYPE_FINGERPRINT -> {
+                            fingerprintEnabledForUser[it.first] = it.second
+                        }
+                    }
+                } else {
+                    biometricsEnabledForUser[it.first] = it.second
+                }
+            }
             // This is because the callback is binder-based and we want to avoid multiple callbacks
             // being registered.
-            .stateIn(scope, SharingStarted.Eagerly, Pair(0, false))
+            .stateIn(scope, SharingStarted.Eagerly, Triple(0, false, TYPE_NONE))
 
     private val isStrongBiometricAllowed: StateFlow<Boolean> =
         strongAuthTracker.isStrongBiometricAllowed.stateIn(
@@ -333,7 +366,7 @@
 
     override val isFingerprintEnrolledAndEnabled: StateFlow<Boolean> =
         isFingerprintEnrolled
-            .and(areBiometricsEnabledForCurrentUser)
+            .and(isFingerprintEnabledForCurrentUser)
             .and(isFingerprintEnabledByDevicePolicy)
             .stateIn(scope, SharingStarted.Eagerly, false)
 
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 839a2bd..2645811 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -18,6 +18,8 @@
 
 import static android.app.StatusBarManager.SESSION_KEYGUARD;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.hardware.biometrics.BiometricAuthenticator.TYPE_ANY_BIOMETRIC;
+import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
 import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT;
 import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT;
@@ -1507,6 +1509,72 @@
     }
 
     @Test
+    @EnableFlags(com.android.settings.flags.Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION)
+    public void listenForFingerprint_whenEnabledForUser_typeFingerprint()
+            throws RemoteException {
+        // GIVEN keyguard showing
+        mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
+        mKeyguardUpdateMonitor.setKeyguardShowing(true, false);
+
+        biometricsEnabledForCurrentUser(true, TYPE_FINGERPRINT);
+        mTestableLooper.processAllMessages();
+
+        assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(true)).isEqualTo(true);
+    }
+
+    @Test
+    @EnableFlags(com.android.settings.flags.Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION)
+    public void doNotListenForFingerprint_whenDisabledForUser_typeFingerprint()
+            throws RemoteException {
+        // GIVEN keyguard showing
+        mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
+        mKeyguardUpdateMonitor.setKeyguardShowing(true, false);
+
+        biometricsEnabledForCurrentUser(false, TYPE_FINGERPRINT);
+        mTestableLooper.processAllMessages();
+
+        assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(true)).isEqualTo(false);
+    }
+
+    @Test
+    @EnableFlags(com.android.settings.flags.Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION)
+    public void listenForFingerprint_typeFingerprintEnabled_typeFaceDisabled()
+            throws RemoteException {
+        // GIVEN keyguard showing
+        mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
+        mKeyguardUpdateMonitor.setKeyguardShowing(true, false);
+
+        // Enable with fingerprint
+        biometricsEnabledForCurrentUser(true, TYPE_FINGERPRINT);
+        mTestableLooper.processAllMessages();
+
+        // Disable with face
+        biometricsEnabledForCurrentUser(false, TYPE_FACE);
+        mTestableLooper.processAllMessages();
+
+        assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(true)).isEqualTo(true);
+    }
+
+    @Test
+    @EnableFlags(com.android.settings.flags.Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION)
+    public void doNotListenForFingerprint_typeFingerprintDisabled_typeFaceEnabled()
+            throws RemoteException {
+        // GIVEN keyguard showing
+        mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
+        mKeyguardUpdateMonitor.setKeyguardShowing(true, false);
+
+        // Enable with face
+        biometricsEnabledForCurrentUser(true, TYPE_FACE);
+        mTestableLooper.processAllMessages();
+
+        // Disable with fingerprint
+        biometricsEnabledForCurrentUser(false, TYPE_FINGERPRINT);
+        mTestableLooper.processAllMessages();
+
+        assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(true)).isEqualTo(false);
+    }
+
+    @Test
     public void testOccludingAppFingerprintListeningState() {
         // GIVEN keyguard isn't visible (app occluding)
         mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
@@ -2464,8 +2532,13 @@
     }
 
     private void biometricsEnabledForCurrentUser() throws RemoteException {
-        mBiometricEnabledOnKeyguardCallback.onChanged(true,
-                mSelectedUserInteractor.getSelectedUserId());
+        biometricsEnabledForCurrentUser(true /* enabled */, TYPE_FINGERPRINT);
+    }
+
+    private void biometricsEnabledForCurrentUser(boolean enabled, int modality)
+            throws RemoteException {
+        mBiometricEnabledOnKeyguardCallback.onChanged(enabled,
+                mSelectedUserInteractor.getSelectedUserId(), modality);
     }
 
     private void primaryAuthNotRequiredByStrongAuthTracker() {
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 42385fc..bb49337 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -230,6 +230,7 @@
         "notification_flags_lib",
         "power_hint_flags_lib",
         "biometrics_flags_lib",
+        "aconfig_settings_flags_lib",
         "am_flags_lib",
         "com_android_server_accessibility_flags_lib",
         "//frameworks/libs/systemui:com_android_systemui_shared_flags_lib",
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index b365ef7..15b1f22 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -17,6 +17,7 @@
 package com.android.server.biometrics;
 
 import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
+import static android.hardware.biometrics.BiometricAuthenticator.TYPE_ANY_BIOMETRIC;
 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
 import static android.hardware.biometrics.BiometricManager.Authenticators;
@@ -81,6 +82,7 @@
 import android.util.ArraySet;
 import android.util.Pair;
 import android.util.Slog;
+import android.util.SparseBooleanArray;
 import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.R;
@@ -100,8 +102,8 @@
 import java.util.Map;
 import java.util.Random;
 import java.util.Set;
-import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.atomic.AtomicLong;
 import java.util.function.Supplier;
 
 /**
@@ -263,6 +265,14 @@
                 Settings.Secure.getUriFor(Settings.Secure.BIOMETRIC_KEYGUARD_ENABLED);
         private final Uri BIOMETRIC_APP_ENABLED =
                 Settings.Secure.getUriFor(Settings.Secure.BIOMETRIC_APP_ENABLED);
+        private final Uri FACE_KEYGUARD_ENABLED =
+                Settings.Secure.getUriFor(Settings.Secure.FACE_KEYGUARD_ENABLED);
+        private final Uri FACE_APP_ENABLED =
+                Settings.Secure.getUriFor(Settings.Secure.FACE_APP_ENABLED);
+        private final Uri FINGERPRINT_KEYGUARD_ENABLED =
+                Settings.Secure.getUriFor(Settings.Secure.FINGERPRINT_KEYGUARD_ENABLED);
+        private final Uri FINGERPRINT_APP_ENABLED =
+                Settings.Secure.getUriFor(Settings.Secure.FINGERPRINT_APP_ENABLED);
         private final Uri MANDATORY_BIOMETRICS_ENABLED =
                 Settings.Secure.getUriFor(Settings.Secure.MANDATORY_BIOMETRICS);
         private final Uri MANDATORY_BIOMETRICS_REQUIREMENTS_SATISFIED = Settings.Secure.getUriFor(
@@ -274,6 +284,10 @@
 
         private final Map<Integer, Boolean> mBiometricEnabledOnKeyguard = new HashMap<>();
         private final Map<Integer, Boolean> mBiometricEnabledForApps = new HashMap<>();
+        private final SparseBooleanArray mFaceEnabledOnKeyguard = new SparseBooleanArray();
+        private final SparseBooleanArray mFaceEnabledForApps = new SparseBooleanArray();
+        private final SparseBooleanArray mFingerprintEnabledOnKeyguard = new SparseBooleanArray();
+        private final SparseBooleanArray mFingerprintEnabledForApps = new SparseBooleanArray();
         private final Map<Integer, Boolean> mFaceAlwaysRequireConfirmation = new HashMap<>();
         private final Map<Integer, Boolean> mMandatoryBiometricsEnabled = new HashMap<>();
         private final Map<Integer, Boolean> mMandatoryBiometricsRequirementsSatisfied =
@@ -323,6 +337,23 @@
                         false /* notifyForDescendants */,
                         this /* observer */,
                         UserHandle.USER_ALL);
+            } else if (com.android.settings.flags.Flags.biometricsOnboardingEducation()) {
+                mContentResolver.registerContentObserver(FINGERPRINT_KEYGUARD_ENABLED,
+                        false /* notifyForDescendants */,
+                        this /* observer */,
+                        UserHandle.USER_ALL);
+                mContentResolver.registerContentObserver(FACE_KEYGUARD_ENABLED,
+                        false /* notifyForDescendants */,
+                        this /* observer */,
+                        UserHandle.USER_ALL);
+                mContentResolver.registerContentObserver(FINGERPRINT_APP_ENABLED,
+                        false /* notifyForDescendants */,
+                        this /* observer */,
+                        UserHandle.USER_ALL);
+                mContentResolver.registerContentObserver(FACE_APP_ENABLED,
+                        false /* notifyForDescendants */,
+                        this /* observer */,
+                        UserHandle.USER_ALL);
             } else {
                 mContentResolver.registerContentObserver(BIOMETRIC_KEYGUARD_ENABLED,
                         false /* notifyForDescendants */,
@@ -357,7 +388,7 @@
                                 userId) != 0);
 
                 if (userId == ActivityManager.getCurrentUser() && !selfChange) {
-                    notifyEnabledOnKeyguardCallbacks(userId);
+                    notifyEnabledOnKeyguardCallbacks(userId, TYPE_FACE);
                 }
             } else if (FACE_UNLOCK_APP_ENABLED.equals(uri)) {
                 mBiometricEnabledForApps.put(userId, Settings.Secure.getIntForUser(
@@ -379,7 +410,27 @@
                         userId) != 0);
 
                 if (userId == ActivityManager.getCurrentUser() && !selfChange) {
-                    notifyEnabledOnKeyguardCallbacks(userId);
+                    notifyEnabledOnKeyguardCallbacks(userId, TYPE_ANY_BIOMETRIC);
+                }
+            } else if (FACE_KEYGUARD_ENABLED.equals(uri)) {
+                mFaceEnabledOnKeyguard.put(userId, Settings.Secure.getIntForUser(
+                        mContentResolver,
+                        Settings.Secure.FACE_KEYGUARD_ENABLED,
+                        DEFAULT_KEYGUARD_ENABLED ? 1 : 0 /* default */,
+                        userId) != 0);
+
+                if (userId == ActivityManager.getCurrentUser() && !selfChange) {
+                    notifyEnabledOnKeyguardCallbacks(userId, TYPE_FACE);
+                }
+            }  else if (FINGERPRINT_KEYGUARD_ENABLED.equals(uri)) {
+                mFingerprintEnabledOnKeyguard.put(userId, Settings.Secure.getIntForUser(
+                        mContentResolver,
+                        Settings.Secure.FINGERPRINT_KEYGUARD_ENABLED,
+                        DEFAULT_KEYGUARD_ENABLED ? 1 : 0 /* default */,
+                        userId) != 0);
+
+                if (userId == ActivityManager.getCurrentUser() && !selfChange) {
+                    notifyEnabledOnKeyguardCallbacks(userId, TYPE_FINGERPRINT);
                 }
             } else if (BIOMETRIC_APP_ENABLED.equals(uri)) {
                 mBiometricEnabledForApps.put(userId, Settings.Secure.getIntForUser(
@@ -387,6 +438,18 @@
                         Settings.Secure.BIOMETRIC_APP_ENABLED,
                         DEFAULT_APP_ENABLED ? 1 : 0 /* default */,
                         userId) != 0);
+            } else if (FACE_APP_ENABLED.equals(uri)) {
+                mFaceEnabledForApps.put(userId, Settings.Secure.getIntForUser(
+                        mContentResolver,
+                        Settings.Secure.FACE_APP_ENABLED,
+                        DEFAULT_APP_ENABLED ? 1 : 0 /* default */,
+                        userId) != 0);
+            } else if (FINGERPRINT_APP_ENABLED.equals(uri)) {
+                mFingerprintEnabledForApps.put(userId, Settings.Secure.getIntForUser(
+                        mContentResolver,
+                        Settings.Secure.FINGERPRINT_APP_ENABLED,
+                        DEFAULT_APP_ENABLED ? 1 : 0 /* default */,
+                        userId) != 0);
             } else if (MANDATORY_BIOMETRICS_ENABLED.equals(uri)) {
                 updateMandatoryBiometricsForAllProfiles(userId);
             } else if (MANDATORY_BIOMETRICS_REQUIREMENTS_SATISFIED.equals(uri)) {
@@ -394,26 +457,60 @@
             }
         }
 
-        public boolean getEnabledOnKeyguard(int userId) {
-            if (!mBiometricEnabledOnKeyguard.containsKey(userId)) {
-                if (mUseLegacyFaceOnlySettings) {
-                    onChange(true /* selfChange */, FACE_UNLOCK_KEYGUARD_ENABLED, userId);
-                } else {
-                    onChange(true /* selfChange */, BIOMETRIC_KEYGUARD_ENABLED, userId);
+        public boolean getEnabledOnKeyguard(int userId, int modality) {
+            if (com.android.settings.flags.Flags.biometricsOnboardingEducation()) {
+                if (modality == TYPE_FACE) {
+                    if (mFaceEnabledOnKeyguard.indexOfKey(userId) < 0) {
+                        onChange(true /* selfChange */, FACE_KEYGUARD_ENABLED, userId);
+                    }
+                    return mFaceEnabledOnKeyguard.get(userId, DEFAULT_KEYGUARD_ENABLED);
+                } else if (modality == TYPE_FINGERPRINT) {
+                    if (mFingerprintEnabledOnKeyguard.indexOfKey(userId) < 0) {
+                        onChange(true /* selfChange */, FINGERPRINT_KEYGUARD_ENABLED, userId);
+                    }
+                    return mFingerprintEnabledOnKeyguard.get(userId, DEFAULT_KEYGUARD_ENABLED);
+                } else { // modality == TYPE_ANY_BIOMETRIC
+                    return mFingerprintEnabledOnKeyguard.get(userId, DEFAULT_KEYGUARD_ENABLED)
+                            || mFaceEnabledOnKeyguard.get(userId, DEFAULT_KEYGUARD_ENABLED);
                 }
+            } else {
+                if (!mBiometricEnabledOnKeyguard.containsKey(userId)) {
+                    if (mUseLegacyFaceOnlySettings) {
+                        onChange(true /* selfChange */, FACE_UNLOCK_KEYGUARD_ENABLED, userId);
+                    } else {
+                        onChange(true /* selfChange */, BIOMETRIC_KEYGUARD_ENABLED, userId);
+                    }
+                }
+                return mBiometricEnabledOnKeyguard.get(userId);
             }
-            return mBiometricEnabledOnKeyguard.get(userId);
         }
 
-        public boolean getEnabledForApps(int userId) {
-            if (!mBiometricEnabledForApps.containsKey(userId)) {
-                if (mUseLegacyFaceOnlySettings) {
-                    onChange(true /* selfChange */, FACE_UNLOCK_APP_ENABLED, userId);
-                } else {
-                    onChange(true /* selfChange */, BIOMETRIC_APP_ENABLED, userId);
+        public boolean getEnabledForApps(int userId, int modality) {
+            if (com.android.settings.flags.Flags.biometricsOnboardingEducation()) {
+                if (modality == TYPE_FACE) {
+                    if (mFaceEnabledForApps.indexOfKey(userId) < 0) {
+                        onChange(true /* selfChange */, FACE_APP_ENABLED, userId);
+                    }
+                    return mFaceEnabledForApps.get(userId, DEFAULT_APP_ENABLED);
+                } else if (modality == TYPE_FINGERPRINT) {
+                    if (mFingerprintEnabledForApps.indexOfKey(userId) < 0) {
+                        onChange(true /* selfChange */, FINGERPRINT_APP_ENABLED, userId);
+                    }
+                    return mFingerprintEnabledForApps.get(userId, DEFAULT_APP_ENABLED);
+                } else { // modality == TYPE_ANY_BIOMETRIC
+                    return mFingerprintEnabledForApps.get(userId, DEFAULT_APP_ENABLED)
+                            || mFaceEnabledForApps.get(userId, DEFAULT_APP_ENABLED);
                 }
+            } else {
+                if (!mBiometricEnabledForApps.containsKey(userId)) {
+                    if (mUseLegacyFaceOnlySettings) {
+                        onChange(true /* selfChange */, FACE_UNLOCK_APP_ENABLED, userId);
+                    } else {
+                        onChange(true /* selfChange */, BIOMETRIC_APP_ENABLED, userId);
+                    }
+                }
+                return mBiometricEnabledForApps.getOrDefault(userId, DEFAULT_APP_ENABLED);
             }
-            return mBiometricEnabledForApps.getOrDefault(userId, DEFAULT_APP_ENABLED);
         }
 
         public boolean getConfirmationAlwaysRequired(@BiometricAuthenticator.Modality int modality,
@@ -444,17 +541,16 @@
                     DEFAULT_MANDATORY_BIOMETRICS_STATUS)
                     && mMandatoryBiometricsRequirementsSatisfied.getOrDefault(userId,
                     DEFAULT_MANDATORY_BIOMETRICS_REQUIREMENTS_SATISFIED_STATUS)
-                    && getEnabledForApps(userId)
+                    && getEnabledForApps(userId, TYPE_ANY_BIOMETRIC)
                     && (mFingerprintEnrolledForUser.getOrDefault(userId, false /* default */)
                     || mFaceEnrolledForUser.getOrDefault(userId, false /* default */));
         }
 
-        void notifyEnabledOnKeyguardCallbacks(int userId) {
+        void notifyEnabledOnKeyguardCallbacks(int userId, int modality) {
             List<EnabledOnKeyguardCallback> callbacks = mCallbacks;
+            final boolean enabled = getEnabledOnKeyguard(userId, modality);
             for (int i = 0; i < callbacks.size(); i++) {
-                callbacks.get(i).notify(
-                        mBiometricEnabledOnKeyguard.getOrDefault(userId, DEFAULT_KEYGUARD_ENABLED),
-                        userId);
+                callbacks.get(i).notify(enabled, userId, modality);
             }
         }
 
@@ -596,9 +692,9 @@
             }
         }
 
-        void notify(boolean enabled, int userId) {
+        void notify(boolean enabled, int userId, int modality) {
             try {
-                mCallback.onChanged(enabled, userId);
+                mCallback.onChanged(enabled, userId, modality);
             } catch (DeadObjectException e) {
                 Slog.w(TAG, "Death while invoking notify", e);
                 mEnabledOnKeyguardCallbacks.remove(this);
@@ -930,8 +1026,16 @@
             try {
                 for (UserInfo userInfo: aliveUsers) {
                     final int userId = userInfo.id;
-                    callback.onChanged(mSettingObserver.getEnabledOnKeyguard(userId),
-                            userId);
+                    if (com.android.settings.flags.Flags.biometricsOnboardingEducation()) {
+                        callback.onChanged(mSettingObserver.getEnabledOnKeyguard(userId, TYPE_FACE),
+                                userId, TYPE_FACE);
+                        callback.onChanged(
+                                mSettingObserver.getEnabledOnKeyguard(userId, TYPE_FINGERPRINT),
+                                userId, TYPE_FINGERPRINT);
+                    } else {
+                        callback.onChanged(mSettingObserver.getEnabledOnKeyguard(userId,
+                                        TYPE_ANY_BIOMETRIC), userId, TYPE_ANY_BIOMETRIC);
+                    }
                 }
             } catch (RemoteException e) {
                 Slog.w(TAG, "Remote exception", e);
@@ -1309,7 +1413,15 @@
                         @Override
                         public void onUserSwitchComplete(int newUserId) {
                             mSettingObserver.updateContentObserver();
-                            mSettingObserver.notifyEnabledOnKeyguardCallbacks(newUserId);
+                            if (com.android.settings.flags.Flags.biometricsOnboardingEducation()) {
+                                mSettingObserver.notifyEnabledOnKeyguardCallbacks(newUserId,
+                                        TYPE_FACE);
+                                mSettingObserver.notifyEnabledOnKeyguardCallbacks(
+                                        newUserId, TYPE_FINGERPRINT);
+                            } else {
+                                mSettingObserver.notifyEnabledOnKeyguardCallbacks(
+                                        newUserId, TYPE_ANY_BIOMETRIC);
+                            }
                         }
                     }, BiometricService.class.getName()
             );
diff --git a/services/core/java/com/android/server/biometrics/PreAuthInfo.java b/services/core/java/com/android/server/biometrics/PreAuthInfo.java
index 6ed1ac85..c739118 100644
--- a/services/core/java/com/android/server/biometrics/PreAuthInfo.java
+++ b/services/core/java/com/android/server/biometrics/PreAuthInfo.java
@@ -284,7 +284,7 @@
 
     private static boolean isEnabledForApp(BiometricService.SettingObserver settingObserver,
             @BiometricAuthenticator.Modality int modality, int userId) {
-        return settingObserver.getEnabledForApps(userId);
+        return settingObserver.getEnabledForApps(userId, modality);
     }
 
     private static boolean isBiometricDisabledByDevicePolicy(
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java b/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java
index 4ef37b9..8b9def9 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java
@@ -908,7 +908,7 @@
                 type,
                 false /* resetLockoutRequiresHardwareAuthToken */));
 
-        when(mSettingObserver.getEnabledForApps(anyInt())).thenReturn(true);
+        when(mSettingObserver.getEnabledForApps(anyInt(), anyInt())).thenReturn(true);
     }
 
     private void setupFace(int id, boolean confirmationAlwaysRequired,
@@ -930,6 +930,6 @@
             }
         });
 
-        when(mSettingObserver.getEnabledForApps(anyInt())).thenReturn(true);
+        when(mSettingObserver.getEnabledForApps(anyInt(), anyInt())).thenReturn(true);
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
index 88829c1..acca4cc 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
@@ -16,6 +16,7 @@
 
 package com.android.server.biometrics;
 
+import static android.hardware.biometrics.BiometricAuthenticator.TYPE_ANY_BIOMETRIC;
 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_CREDENTIAL;
 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
@@ -588,7 +589,8 @@
         setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG);
 
         // Disabled in user settings receives onError
-        when(mBiometricService.mSettingObserver.getEnabledForApps(anyInt())).thenReturn(false);
+        when(mBiometricService.mSettingObserver.getEnabledForApps(anyInt(), anyInt()))
+                .thenReturn(false);
         invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
                 null /* authenticators */, false /* useDefaultSubtitle */,
                 false /* deviceCredentialAllowed */);
@@ -602,7 +604,8 @@
 
         // Enrolled, not disabled in settings, user requires confirmation in settings
         resetReceivers();
-        when(mBiometricService.mSettingObserver.getEnabledForApps(anyInt())).thenReturn(true);
+        when(mBiometricService.mSettingObserver.getEnabledForApps(anyInt(), anyInt()))
+                .thenReturn(true);
         when(mBiometricService.mSettingObserver.getConfirmationAlwaysRequired(
                 anyInt() /* modality */, anyInt() /* userId */))
                 .thenReturn(true);
@@ -1493,7 +1496,8 @@
     public void testCanAuthenticate_whenBiometricsNotEnabledForApps_returnsHardwareUnavailable()
             throws Exception {
         setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG);
-        when(mBiometricService.mSettingObserver.getEnabledForApps(anyInt())).thenReturn(false);
+        when(mBiometricService.mSettingObserver.getEnabledForApps(anyInt(), anyInt()))
+                .thenReturn(false);
         when(mTrustManager.isDeviceSecure(anyInt(), anyInt()))
                 .thenReturn(true);
 
@@ -1512,7 +1516,8 @@
     @RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS)
     public void testCanAuthenticate_whenBiometricsNotEnabledForApps() throws Exception {
         setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG);
-        when(mBiometricService.mSettingObserver.getEnabledForApps(anyInt())).thenReturn(false);
+        when(mBiometricService.mSettingObserver.getEnabledForApps(anyInt(), anyInt()))
+                .thenReturn(false);
         when(mTrustManager.isDeviceSecure(anyInt(), anyInt()))
                 .thenReturn(true);
 
@@ -1741,7 +1746,8 @@
 
         final int testId = 0;
 
-        when(mBiometricService.mSettingObserver.getEnabledForApps(anyInt())).thenReturn(true);
+        when(mBiometricService.mSettingObserver.getEnabledForApps(anyInt(), anyInt()))
+                .thenReturn(true);
 
         when(mFingerprintAuthenticator.hasEnrolledTemplates(anyInt(), any()))
                 .thenReturn(true);
@@ -1947,7 +1953,8 @@
     }
 
     @Test
-    public void testRegisterEnabledOnKeyguardCallback() throws RemoteException {
+    @RequiresFlagsDisabled(com.android.settings.flags.Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION)
+    public void testRegisterEnabledOnKeyguardCallback_flagDisabled() throws RemoteException {
         final UserInfo userInfo1 = new UserInfo(0 /* userId */, "user1" /* name */, 0 /* flags */);
         final UserInfo userInfo2 = new UserInfo(10 /* userId */, "user2" /* name */, 0 /* flags */);
         final List<UserInfo> aliveUsers = List.of(userInfo1, userInfo2);
@@ -1957,10 +1964,10 @@
         mBiometricService = new BiometricService(mContext, mInjector, mBiometricHandlerProvider);
 
         when(mUserManager.getAliveUsers()).thenReturn(aliveUsers);
-        when(mBiometricService.mSettingObserver.getEnabledOnKeyguard(userInfo1.id))
-                .thenReturn(true);
-        when(mBiometricService.mSettingObserver.getEnabledOnKeyguard(userInfo2.id))
-                .thenReturn(false);
+        when(mBiometricService.mSettingObserver
+                .getEnabledOnKeyguard(userInfo1.id, TYPE_ANY_BIOMETRIC)).thenReturn(true);
+        when(mBiometricService.mSettingObserver
+                .getEnabledOnKeyguard(userInfo2.id, TYPE_ANY_BIOMETRIC)).thenReturn(false);
         when(callback.asBinder()).thenReturn(mock(IBinder.class));
 
         mBiometricService.mImpl.registerEnabledOnKeyguardCallback(callback);
@@ -1968,8 +1975,42 @@
         waitForIdle();
 
         verify(callback).asBinder();
-        verify(callback).onChanged(true, userInfo1.id);
-        verify(callback).onChanged(false, userInfo2.id);
+        verify(callback).onChanged(true, userInfo1.id, TYPE_ANY_BIOMETRIC);
+        verify(callback).onChanged(false, userInfo2.id, TYPE_ANY_BIOMETRIC);
+        verifyNoMoreInteractions(callback);
+    }
+
+    @Test
+    @RequiresFlagsEnabled(com.android.settings.flags.Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION)
+    public void testRegisterEnabledOnKeyguardCallback_flagEnabled() throws RemoteException {
+        final UserInfo userInfo1 = new UserInfo(0 /* userId */, "user1" /* name */, 0 /* flags */);
+        final UserInfo userInfo2 = new UserInfo(10 /* userId */, "user2" /* name */, 0 /* flags */);
+        final List<UserInfo> aliveUsers = List.of(userInfo1, userInfo2);
+        final IBiometricEnabledOnKeyguardCallback callback =
+                mock(IBiometricEnabledOnKeyguardCallback.class);
+
+        mBiometricService = new BiometricService(mContext, mInjector, mBiometricHandlerProvider);
+
+        when(mUserManager.getAliveUsers()).thenReturn(aliveUsers);
+        when(mBiometricService.mSettingObserver.getEnabledOnKeyguard(userInfo1.id, TYPE_FACE))
+                .thenReturn(true);
+        when(mBiometricService.mSettingObserver.getEnabledOnKeyguard(userInfo1.id,
+                TYPE_FINGERPRINT)).thenReturn(true);
+        when(mBiometricService.mSettingObserver.getEnabledOnKeyguard(userInfo2.id, TYPE_FACE))
+                .thenReturn(false);
+        when(mBiometricService.mSettingObserver.getEnabledOnKeyguard(userInfo2.id,
+                TYPE_FINGERPRINT)).thenReturn(false);
+        when(callback.asBinder()).thenReturn(mock(IBinder.class));
+
+        mBiometricService.mImpl.registerEnabledOnKeyguardCallback(callback);
+
+        waitForIdle();
+
+        verify(callback).asBinder();
+        verify(callback).onChanged(true, userInfo1.id, TYPE_FACE);
+        verify(callback).onChanged(true, userInfo1.id, TYPE_FINGERPRINT);
+        verify(callback).onChanged(false, userInfo2.id, TYPE_FACE);
+        verify(callback).onChanged(false, userInfo2.id, TYPE_FINGERPRINT);
         verifyNoMoreInteractions(callback);
     }
 
@@ -2065,6 +2106,58 @@
                 userId));
     }
 
+    @Test
+    @RequiresFlagsEnabled(com.android.settings.flags.Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION)
+    public void testCanAuthenticate_faceEnabledForApps() throws Exception {
+        setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG);
+        when(mBiometricService.mSettingObserver.getEnabledForApps(0 /* userId */, TYPE_FACE))
+                .thenReturn(true);
+        when(mTrustManager.isDeviceSecure(anyInt(), anyInt()))
+                .thenReturn(true);
+
+        assertEquals(BiometricManager.BIOMETRIC_SUCCESS,
+                invokeCanAuthenticate(mBiometricService, Authenticators.BIOMETRIC_STRONG));
+    }
+
+    @Test
+    @RequiresFlagsEnabled(com.android.settings.flags.Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION)
+    public void testCanAuthenticate_faceDisabledForApps() throws Exception {
+        setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG);
+        when(mBiometricService.mSettingObserver.getEnabledForApps(0 /* userId */, TYPE_FACE))
+                .thenReturn(false);
+        when(mTrustManager.isDeviceSecure(anyInt(), anyInt()))
+                .thenReturn(true);
+
+        assertEquals(BiometricManager.BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS,
+                invokeCanAuthenticate(mBiometricService, Authenticators.BIOMETRIC_STRONG));
+    }
+
+    @Test
+    @RequiresFlagsEnabled(com.android.settings.flags.Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION)
+    public void testCanAuthenticate_fingerprintsEnabledForApps() throws Exception {
+        setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG);
+        when(mBiometricService.mSettingObserver.getEnabledForApps(0 /* userId */, TYPE_FINGERPRINT))
+                .thenReturn(true);
+        when(mTrustManager.isDeviceSecure(anyInt(), anyInt()))
+                .thenReturn(true);
+
+        assertEquals(BiometricManager.BIOMETRIC_SUCCESS,
+                invokeCanAuthenticate(mBiometricService, Authenticators.BIOMETRIC_STRONG));
+    }
+
+    @Test
+    @RequiresFlagsEnabled(com.android.settings.flags.Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION)
+    public void testCanAuthenticate_fingerprintsDisabledForApps() throws Exception {
+        setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG);
+        when(mBiometricService.mSettingObserver.getEnabledForApps(0 /* userId */, TYPE_FINGERPRINT))
+                .thenReturn(false);
+        when(mTrustManager.isDeviceSecure(anyInt(), anyInt()))
+                .thenReturn(true);
+
+        assertEquals(BiometricManager.BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS,
+                invokeCanAuthenticate(mBiometricService, Authenticators.BIOMETRIC_STRONG));
+    }
+
     // Helper methods
 
     private int invokeCanAuthenticate(BiometricService service, int authenticators)
@@ -2082,7 +2175,8 @@
         mBiometricService = new BiometricService(mContext, mInjector, mBiometricHandlerProvider);
         mBiometricService.onStart();
 
-        when(mBiometricService.mSettingObserver.getEnabledForApps(anyInt())).thenReturn(true);
+        when(mBiometricService.mSettingObserver.getEnabledForApps(anyInt(), anyInt()))
+                .thenReturn(true);
 
         if ((modality & TYPE_FINGERPRINT) != 0) {
             when(mFingerprintAuthenticator.hasEnrolledTemplates(anyInt(), any()))
@@ -2115,7 +2209,8 @@
         mBiometricService = new BiometricService(mContext, mInjector, mBiometricHandlerProvider);
         mBiometricService.onStart();
 
-        when(mBiometricService.mSettingObserver.getEnabledForApps(anyInt())).thenReturn(true);
+        when(mBiometricService.mSettingObserver.getEnabledForApps(anyInt(), anyInt()))
+                .thenReturn(true);
 
         assertEquals(modalities.length, strengths.length);
 
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java b/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java
index f6f831f..f8cf21d 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java
@@ -23,6 +23,7 @@
 import static android.hardware.biometrics.BiometricManager.BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS;
 import static android.hardware.biometrics.BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE;
 
+import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_NOT_ENABLED_FOR_APPS;
 import static com.android.server.biometrics.sensors.LockoutTracker.LOCKOUT_NONE;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -96,7 +97,7 @@
         when(mTrustManager.isDeviceSecure(anyInt(), anyInt())).thenReturn(true);
         when(mDevicePolicyManager.getKeyguardDisabledFeatures(any(), anyInt()))
                 .thenReturn(KEYGUARD_DISABLE_FEATURES_NONE);
-        when(mSettingObserver.getEnabledForApps(anyInt())).thenReturn(true);
+        when(mSettingObserver.getEnabledForApps(anyInt(), anyInt())).thenReturn(true);
         when(mSettingObserver.getMandatoryBiometricsEnabledAndRequirementsSatisfiedForUser(
                 anyInt())).thenReturn(true);
         when(mFaceAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(true);
@@ -280,7 +281,7 @@
     public void testCalculateByPriority()
             throws Exception {
         when(mFaceAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(false);
-        when(mSettingObserver.getEnabledForApps(anyInt())).thenReturn(false);
+        when(mSettingObserver.getEnabledForApps(anyInt(), anyInt())).thenReturn(false);
 
         BiometricSensor faceSensor = getFaceSensor();
         BiometricSensor fingerprintSensor = getFingerprintSensor();
@@ -370,6 +371,58 @@
         assertThat(preAuthInfo.getCanAuthenticateResult()).isEqualTo(BIOMETRIC_ERROR_NO_HARDWARE);
     }
 
+    @Test
+    @RequiresFlagsEnabled(com.android.settings.flags.Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION)
+    public void testBiometricsEnabledForApps_fingerprintEnabled_faceDisabled()
+            throws Exception {
+        when(mSettingObserver.getEnabledForApps(USER_ID, TYPE_FINGERPRINT)).thenReturn(true);
+        when(mSettingObserver.getEnabledForApps(USER_ID, TYPE_FACE)).thenReturn(false);
+        when(mTrustManager.isInSignificantPlace()).thenReturn(true);
+
+        final BiometricSensor sensor = getFaceSensor();
+        BiometricSensor fingerprintSensor = getFingerprintSensor();
+        final PromptInfo promptInfo = new PromptInfo();
+        promptInfo.setAuthenticators(BiometricManager.Authenticators.IDENTITY_CHECK
+                | BiometricManager.Authenticators.BIOMETRIC_STRONG);
+        final PreAuthInfo preAuthInfo = PreAuthInfo.create(mTrustManager, mDevicePolicyManager,
+                mSettingObserver, List.of(sensor, fingerprintSensor), USER_ID, promptInfo,
+                TEST_PACKAGE_NAME, false /* checkDevicePolicyManager */, mContext,
+                mBiometricCameraManager, mUserManager);
+
+        assertThat(preAuthInfo.eligibleSensors).hasSize(1);
+        assertThat(preAuthInfo.eligibleSensors.get(0).modality).isEqualTo(TYPE_FINGERPRINT);
+        assertThat(preAuthInfo.ineligibleSensors).hasSize(1);
+        assertThat(preAuthInfo.ineligibleSensors.get(0).first.modality).isEqualTo(TYPE_FACE);
+        assertThat(preAuthInfo.ineligibleSensors.get(0).second)
+                .isEqualTo(BIOMETRIC_NOT_ENABLED_FOR_APPS);
+    }
+
+    @Test
+    @RequiresFlagsEnabled(com.android.settings.flags.Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION)
+    public void testBiometricsEnabledForApps_fingerprintDisabled_faceEnabled()
+            throws Exception {
+        when(mSettingObserver.getEnabledForApps(USER_ID, TYPE_FINGERPRINT)).thenReturn(false);
+        when(mSettingObserver.getEnabledForApps(USER_ID, TYPE_FACE)).thenReturn(true);
+        when(mTrustManager.isInSignificantPlace()).thenReturn(true);
+
+        final BiometricSensor sensor = getFaceSensor();
+        BiometricSensor fingerprintSensor = getFingerprintSensor();
+        final PromptInfo promptInfo = new PromptInfo();
+        promptInfo.setAuthenticators(BiometricManager.Authenticators.IDENTITY_CHECK
+                | BiometricManager.Authenticators.BIOMETRIC_STRONG);
+        final PreAuthInfo preAuthInfo = PreAuthInfo.create(mTrustManager, mDevicePolicyManager,
+                mSettingObserver, List.of(sensor, fingerprintSensor), USER_ID, promptInfo,
+                TEST_PACKAGE_NAME, false /* checkDevicePolicyManager */, mContext,
+                mBiometricCameraManager, mUserManager);
+
+        assertThat(preAuthInfo.eligibleSensors).hasSize(1);
+        assertThat(preAuthInfo.eligibleSensors.get(0).modality).isEqualTo(TYPE_FACE);
+        assertThat(preAuthInfo.ineligibleSensors).hasSize(1);
+        assertThat(preAuthInfo.ineligibleSensors.get(0).first.modality).isEqualTo(TYPE_FINGERPRINT);
+        assertThat(preAuthInfo.ineligibleSensors.get(0).second)
+                .isEqualTo(BIOMETRIC_NOT_ENABLED_FOR_APPS);
+    }
+
     private BiometricSensor getFingerprintSensor() {
         BiometricSensor sensor = new BiometricSensor(mContext, SENSOR_ID_FINGERPRINT,
                 TYPE_FINGERPRINT, BiometricManager.Authenticators.BIOMETRIC_STRONG,