Loading packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt +10 −6 Original line number Diff line number Diff line Loading @@ -66,7 +66,7 @@ import kotlinx.coroutines.flow.transformLatest /** * Acts as source of truth for biometric authentication related settings like enrollments, device * policy, etc. * policy specifically for device entry usage. * * Abstracts-away data sources and their schemas so the rest of the app doesn't need to worry about * upstream changes. Loading @@ -74,7 +74,8 @@ import kotlinx.coroutines.flow.transformLatest interface BiometricSettingsRepository { /** * If the current user can enter the device using fingerprint. This is true if user has enrolled * fingerprints and fingerprint auth is not disabled through settings/device policy * fingerprints and fingerprint auth is not disabled for device entry through settings and * device policy */ val isFingerprintEnrolledAndEnabled: StateFlow<Boolean> Loading Loading @@ -247,9 +248,11 @@ constructor( } } private val isFaceEnabledByBiometricsManagerForCurrentUser: Flow<Boolean> = private val areBiometricsEnabledForCurrentUser: Flow<Boolean> = userRepository.selectedUserInfo.flatMapLatest { userInfo -> isFaceEnabledByBiometricsManager.map { biometricsEnabledForUser[userInfo.id] ?: false } areBiometricsEnabledForDeviceEntryFromUserSetting.map { biometricsEnabledForUser[userInfo.id] ?: false } } private val isFaceEnabledByDevicePolicy: Flow<Boolean> = Loading @@ -263,13 +266,13 @@ constructor( .distinctUntilChanged() private val isFaceAuthenticationEnabled: Flow<Boolean> = combine(isFaceEnabledByBiometricsManagerForCurrentUser, isFaceEnabledByDevicePolicy) { combine(areBiometricsEnabledForCurrentUser, isFaceEnabledByDevicePolicy) { biometricsManagerSetting, devicePolicySetting -> biometricsManagerSetting && devicePolicySetting } private val isFaceEnabledByBiometricsManager: Flow<Pair<Int, Boolean>> = private val areBiometricsEnabledForDeviceEntryFromUserSetting: Flow<Pair<Int, Boolean>> = conflatedCallbackFlow { val callback = object : IBiometricEnabledOnKeyguardCallback.Stub() { Loading Loading @@ -340,6 +343,7 @@ constructor( override val isFingerprintEnrolledAndEnabled: StateFlow<Boolean> = isFingerprintEnrolled .and(areBiometricsEnabledForCurrentUser) .and(isFingerprintEnabledByDevicePolicy) .stateIn(scope, SharingStarted.Eagerly, false) Loading packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt +42 −8 Original line number Diff line number Diff line Loading @@ -154,6 +154,7 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() { fun fingerprintEnrollmentChange() = testScope.runTest { createBiometricSettingsRepository() biometricsAreEnabledBySettings() val fingerprintAllowed = collectLastValue(underTest.isFingerprintEnrolledAndEnabled) runCurrent() Loading @@ -169,12 +170,35 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() { assertThat(fingerprintAllowed()).isFalse() } @Test fun fingerprintEnabledStateChange() = testScope.runTest { createBiometricSettingsRepository() biometricsAreEnabledBySettings() val fingerprintAllowed = collectLastValue(underTest.isFingerprintEnrolledAndEnabled) runCurrent() // start state whenever(authController.isFingerprintEnrolled(anyInt())).thenReturn(true) enrollmentChange(UNDER_DISPLAY_FINGERPRINT, PRIMARY_USER_ID, true) assertThat(fingerprintAllowed()).isTrue() // when biometrics are not enabled by settings biometricsAreNotEnabledBySettings() assertThat(fingerprintAllowed()).isFalse() // when biometrics are enabled by settings biometricsAreEnabledBySettings() assertThat(fingerprintAllowed()).isTrue() } @Test fun strongBiometricAllowedChange() = testScope.runTest { fingerprintIsEnrolled() doNotDisableKeyguardAuthFeatures() createBiometricSettingsRepository() biometricsAreEnabledBySettings() val strongBiometricAllowed by collectLastValue(underTest.isFingerprintAuthCurrentlyAllowed) Loading @@ -197,7 +221,7 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() { createBiometricSettingsRepository() val convenienceFaceAuthAllowed by collectLastValue(underTest.isFaceAuthCurrentlyAllowed) doNotDisableKeyguardAuthFeatures() faceAuthIsEnabledByBiometricManager() biometricsAreEnabledBySettings() onStrongAuthChanged(STRONG_AUTH_NOT_REQUIRED, PRIMARY_USER_ID) onNonStrongAuthChanged(true, PRIMARY_USER_ID) Loading Loading @@ -238,6 +262,7 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() { faceAuthIsNonStrongBiometric() faceAuthIsEnrolled() doNotDisableKeyguardAuthFeatures() biometricsAreEnabledBySettings() val convenienceBiometricAllowed = collectLastValue(underTest.isFaceAuthCurrentlyAllowed) runCurrent() Loading @@ -258,7 +283,7 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() { faceAuthIsEnrolled() createBiometricSettingsRepository() doNotDisableKeyguardAuthFeatures() faceAuthIsEnabledByBiometricManager() biometricsAreEnabledBySettings() runCurrent() val convenienceBiometricAllowed by Loading Loading @@ -291,6 +316,7 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() { testScope.runTest { fingerprintIsEnrolled(PRIMARY_USER_ID) createBiometricSettingsRepository() biometricsAreEnabledBySettings() val fingerprintEnabledByDevicePolicy = collectLastValue(underTest.isFingerprintEnrolledAndEnabled) Loading @@ -316,7 +342,7 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() { createBiometricSettingsRepository() val faceAuthAllowed = collectLastValue(underTest.isFaceAuthEnrolledAndEnabled) faceAuthIsEnabledByBiometricManager() biometricsAreEnabledBySettings() doNotDisableKeyguardAuthFeatures(PRIMARY_USER_ID) Loading Loading @@ -351,12 +377,18 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() { assertThat(faceAuthAllowed()).isTrue() } private fun faceAuthIsEnabledByBiometricManager(userId: Int = PRIMARY_USER_ID) { private fun biometricsAreEnabledBySettings(userId: Int = PRIMARY_USER_ID) { verify(biometricManager, atLeastOnce()) .registerEnabledOnKeyguardCallback(biometricManagerCallback.capture()) biometricManagerCallback.value.onChanged(true, userId) } private fun biometricsAreNotEnabledBySettings(userId: Int = PRIMARY_USER_ID) { verify(biometricManager, atLeastOnce()) .registerEnabledOnKeyguardCallback(biometricManagerCallback.capture()) biometricManagerCallback.value.onChanged(false, userId) } @Test fun faceEnrollmentStatusOfNewUserUponUserSwitch() = testScope.runTest { Loading Loading @@ -427,7 +459,7 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() { faceAuthIsEnrolled() createBiometricSettingsRepository() faceAuthIsEnabledByBiometricManager() biometricsAreEnabledBySettings() doNotDisableKeyguardAuthFeatures() mobileConnectionsRepository.isAnySimSecure.value = false runCurrent() Loading @@ -454,7 +486,7 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() { deviceIsInPostureThatSupportsFaceAuth() doNotDisableKeyguardAuthFeatures() faceAuthIsStrongBiometric() faceAuthIsEnabledByBiometricManager() biometricsAreEnabledBySettings() mobileConnectionsRepository.isAnySimSecure.value = false onStrongAuthChanged(STRONG_AUTH_NOT_REQUIRED, PRIMARY_USER_ID) Loading Loading @@ -636,7 +668,7 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() { deviceIsInPostureThatSupportsFaceAuth() doNotDisableKeyguardAuthFeatures() faceAuthIsStrongBiometric() faceAuthIsEnabledByBiometricManager() biometricsAreEnabledBySettings() onStrongAuthChanged(STRONG_AUTH_NOT_REQUIRED, PRIMARY_USER_ID) onNonStrongAuthChanged(false, PRIMARY_USER_ID) Loading @@ -660,7 +692,7 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() { deviceIsInPostureThatSupportsFaceAuth() doNotDisableKeyguardAuthFeatures() faceAuthIsNonStrongBiometric() faceAuthIsEnabledByBiometricManager() biometricsAreEnabledBySettings() onStrongAuthChanged(STRONG_AUTH_NOT_REQUIRED, PRIMARY_USER_ID) onNonStrongAuthChanged(false, PRIMARY_USER_ID) Loading @@ -682,6 +714,7 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() { fun fpAuthCurrentlyAllowed_dependsOnNonStrongAuthBiometricSetting_ifFpIsNotStrong() = testScope.runTest { createBiometricSettingsRepository() biometricsAreEnabledBySettings() val isFingerprintCurrentlyAllowed by collectLastValue(underTest.isFingerprintAuthCurrentlyAllowed) Loading Loading @@ -723,6 +756,7 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() { fun fpAuthCurrentlyAllowed_dependsOnStrongAuthBiometricSetting_ifFpIsStrong() = testScope.runTest { createBiometricSettingsRepository() biometricsAreEnabledBySettings() val isFingerprintCurrentlyAllowed by collectLastValue(underTest.isFingerprintAuthCurrentlyAllowed) Loading Loading
packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt +10 −6 Original line number Diff line number Diff line Loading @@ -66,7 +66,7 @@ import kotlinx.coroutines.flow.transformLatest /** * Acts as source of truth for biometric authentication related settings like enrollments, device * policy, etc. * policy specifically for device entry usage. * * Abstracts-away data sources and their schemas so the rest of the app doesn't need to worry about * upstream changes. Loading @@ -74,7 +74,8 @@ import kotlinx.coroutines.flow.transformLatest interface BiometricSettingsRepository { /** * If the current user can enter the device using fingerprint. This is true if user has enrolled * fingerprints and fingerprint auth is not disabled through settings/device policy * fingerprints and fingerprint auth is not disabled for device entry through settings and * device policy */ val isFingerprintEnrolledAndEnabled: StateFlow<Boolean> Loading Loading @@ -247,9 +248,11 @@ constructor( } } private val isFaceEnabledByBiometricsManagerForCurrentUser: Flow<Boolean> = private val areBiometricsEnabledForCurrentUser: Flow<Boolean> = userRepository.selectedUserInfo.flatMapLatest { userInfo -> isFaceEnabledByBiometricsManager.map { biometricsEnabledForUser[userInfo.id] ?: false } areBiometricsEnabledForDeviceEntryFromUserSetting.map { biometricsEnabledForUser[userInfo.id] ?: false } } private val isFaceEnabledByDevicePolicy: Flow<Boolean> = Loading @@ -263,13 +266,13 @@ constructor( .distinctUntilChanged() private val isFaceAuthenticationEnabled: Flow<Boolean> = combine(isFaceEnabledByBiometricsManagerForCurrentUser, isFaceEnabledByDevicePolicy) { combine(areBiometricsEnabledForCurrentUser, isFaceEnabledByDevicePolicy) { biometricsManagerSetting, devicePolicySetting -> biometricsManagerSetting && devicePolicySetting } private val isFaceEnabledByBiometricsManager: Flow<Pair<Int, Boolean>> = private val areBiometricsEnabledForDeviceEntryFromUserSetting: Flow<Pair<Int, Boolean>> = conflatedCallbackFlow { val callback = object : IBiometricEnabledOnKeyguardCallback.Stub() { Loading Loading @@ -340,6 +343,7 @@ constructor( override val isFingerprintEnrolledAndEnabled: StateFlow<Boolean> = isFingerprintEnrolled .and(areBiometricsEnabledForCurrentUser) .and(isFingerprintEnabledByDevicePolicy) .stateIn(scope, SharingStarted.Eagerly, false) Loading
packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt +42 −8 Original line number Diff line number Diff line Loading @@ -154,6 +154,7 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() { fun fingerprintEnrollmentChange() = testScope.runTest { createBiometricSettingsRepository() biometricsAreEnabledBySettings() val fingerprintAllowed = collectLastValue(underTest.isFingerprintEnrolledAndEnabled) runCurrent() Loading @@ -169,12 +170,35 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() { assertThat(fingerprintAllowed()).isFalse() } @Test fun fingerprintEnabledStateChange() = testScope.runTest { createBiometricSettingsRepository() biometricsAreEnabledBySettings() val fingerprintAllowed = collectLastValue(underTest.isFingerprintEnrolledAndEnabled) runCurrent() // start state whenever(authController.isFingerprintEnrolled(anyInt())).thenReturn(true) enrollmentChange(UNDER_DISPLAY_FINGERPRINT, PRIMARY_USER_ID, true) assertThat(fingerprintAllowed()).isTrue() // when biometrics are not enabled by settings biometricsAreNotEnabledBySettings() assertThat(fingerprintAllowed()).isFalse() // when biometrics are enabled by settings biometricsAreEnabledBySettings() assertThat(fingerprintAllowed()).isTrue() } @Test fun strongBiometricAllowedChange() = testScope.runTest { fingerprintIsEnrolled() doNotDisableKeyguardAuthFeatures() createBiometricSettingsRepository() biometricsAreEnabledBySettings() val strongBiometricAllowed by collectLastValue(underTest.isFingerprintAuthCurrentlyAllowed) Loading @@ -197,7 +221,7 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() { createBiometricSettingsRepository() val convenienceFaceAuthAllowed by collectLastValue(underTest.isFaceAuthCurrentlyAllowed) doNotDisableKeyguardAuthFeatures() faceAuthIsEnabledByBiometricManager() biometricsAreEnabledBySettings() onStrongAuthChanged(STRONG_AUTH_NOT_REQUIRED, PRIMARY_USER_ID) onNonStrongAuthChanged(true, PRIMARY_USER_ID) Loading Loading @@ -238,6 +262,7 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() { faceAuthIsNonStrongBiometric() faceAuthIsEnrolled() doNotDisableKeyguardAuthFeatures() biometricsAreEnabledBySettings() val convenienceBiometricAllowed = collectLastValue(underTest.isFaceAuthCurrentlyAllowed) runCurrent() Loading @@ -258,7 +283,7 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() { faceAuthIsEnrolled() createBiometricSettingsRepository() doNotDisableKeyguardAuthFeatures() faceAuthIsEnabledByBiometricManager() biometricsAreEnabledBySettings() runCurrent() val convenienceBiometricAllowed by Loading Loading @@ -291,6 +316,7 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() { testScope.runTest { fingerprintIsEnrolled(PRIMARY_USER_ID) createBiometricSettingsRepository() biometricsAreEnabledBySettings() val fingerprintEnabledByDevicePolicy = collectLastValue(underTest.isFingerprintEnrolledAndEnabled) Loading @@ -316,7 +342,7 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() { createBiometricSettingsRepository() val faceAuthAllowed = collectLastValue(underTest.isFaceAuthEnrolledAndEnabled) faceAuthIsEnabledByBiometricManager() biometricsAreEnabledBySettings() doNotDisableKeyguardAuthFeatures(PRIMARY_USER_ID) Loading Loading @@ -351,12 +377,18 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() { assertThat(faceAuthAllowed()).isTrue() } private fun faceAuthIsEnabledByBiometricManager(userId: Int = PRIMARY_USER_ID) { private fun biometricsAreEnabledBySettings(userId: Int = PRIMARY_USER_ID) { verify(biometricManager, atLeastOnce()) .registerEnabledOnKeyguardCallback(biometricManagerCallback.capture()) biometricManagerCallback.value.onChanged(true, userId) } private fun biometricsAreNotEnabledBySettings(userId: Int = PRIMARY_USER_ID) { verify(biometricManager, atLeastOnce()) .registerEnabledOnKeyguardCallback(biometricManagerCallback.capture()) biometricManagerCallback.value.onChanged(false, userId) } @Test fun faceEnrollmentStatusOfNewUserUponUserSwitch() = testScope.runTest { Loading Loading @@ -427,7 +459,7 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() { faceAuthIsEnrolled() createBiometricSettingsRepository() faceAuthIsEnabledByBiometricManager() biometricsAreEnabledBySettings() doNotDisableKeyguardAuthFeatures() mobileConnectionsRepository.isAnySimSecure.value = false runCurrent() Loading @@ -454,7 +486,7 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() { deviceIsInPostureThatSupportsFaceAuth() doNotDisableKeyguardAuthFeatures() faceAuthIsStrongBiometric() faceAuthIsEnabledByBiometricManager() biometricsAreEnabledBySettings() mobileConnectionsRepository.isAnySimSecure.value = false onStrongAuthChanged(STRONG_AUTH_NOT_REQUIRED, PRIMARY_USER_ID) Loading Loading @@ -636,7 +668,7 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() { deviceIsInPostureThatSupportsFaceAuth() doNotDisableKeyguardAuthFeatures() faceAuthIsStrongBiometric() faceAuthIsEnabledByBiometricManager() biometricsAreEnabledBySettings() onStrongAuthChanged(STRONG_AUTH_NOT_REQUIRED, PRIMARY_USER_ID) onNonStrongAuthChanged(false, PRIMARY_USER_ID) Loading @@ -660,7 +692,7 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() { deviceIsInPostureThatSupportsFaceAuth() doNotDisableKeyguardAuthFeatures() faceAuthIsNonStrongBiometric() faceAuthIsEnabledByBiometricManager() biometricsAreEnabledBySettings() onStrongAuthChanged(STRONG_AUTH_NOT_REQUIRED, PRIMARY_USER_ID) onNonStrongAuthChanged(false, PRIMARY_USER_ID) Loading @@ -682,6 +714,7 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() { fun fpAuthCurrentlyAllowed_dependsOnNonStrongAuthBiometricSetting_ifFpIsNotStrong() = testScope.runTest { createBiometricSettingsRepository() biometricsAreEnabledBySettings() val isFingerprintCurrentlyAllowed by collectLastValue(underTest.isFingerprintAuthCurrentlyAllowed) Loading Loading @@ -723,6 +756,7 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() { fun fpAuthCurrentlyAllowed_dependsOnStrongAuthBiometricSetting_ifFpIsStrong() = testScope.runTest { createBiometricSettingsRepository() biometricsAreEnabledBySettings() val isFingerprintCurrentlyAllowed by collectLastValue(underTest.isFingerprintAuthCurrentlyAllowed) Loading