Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 04079089 authored by Chandru S's avatar Chandru S Committed by Android (Google) Code Review
Browse files

Merge "Provide better API methods that can provide face/fp auth status" into udc-qpr-dev

parents 59b6f065 821c4280
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -36,7 +36,6 @@ import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_RESTART_FOR_MAINL
import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TIMEOUT
import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TRUSTAGENT_EXPIRED
import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_USER_REQUEST
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.R.string.bouncer_face_not_recognized
import com.android.systemui.R.string.keyguard_enter_password
import com.android.systemui.R.string.keyguard_enter_pattern
@@ -80,13 +79,14 @@ import com.android.systemui.R.string.kg_wrong_pin_try_again
import com.android.systemui.bouncer.shared.model.BouncerMessageModel
import com.android.systemui.bouncer.shared.model.Message
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
import javax.inject.Inject

@SysUISingleton
class BouncerMessageFactory
@Inject
constructor(
    private val updateMonitor: KeyguardUpdateMonitor,
    private val biometricSettingsRepository: BiometricSettingsRepository,
    private val securityModel: KeyguardSecurityModel,
) {

@@ -99,7 +99,7 @@ constructor(
            getBouncerMessage(
                reason,
                securityModel.getSecurityMode(userId),
                updateMonitor.isUnlockingWithFingerprintAllowed
                biometricSettingsRepository.isFingerprintAuthCurrentlyAllowed.value
            )
        return pair?.let {
            BouncerMessageModel(
+4 −16
Original line number Diff line number Diff line
@@ -123,20 +123,11 @@ constructor(
    fingerprintAuthRepository: DeviceEntryFingerprintAuthRepository,
) : BouncerMessageRepository {

    private val isFaceEnrolledAndEnabled =
        and(
            biometricSettingsRepository.isFaceAuthenticationEnabled,
            biometricSettingsRepository.isFaceEnrolled
        )

    private val isFingerprintEnrolledAndEnabled =
        and(
            biometricSettingsRepository.isFingerprintEnabledByDevicePolicy,
            biometricSettingsRepository.isFingerprintEnrolled
        )

    private val isAnyBiometricsEnabledAndEnrolled =
        or(isFaceEnrolledAndEnabled, isFingerprintEnrolledAndEnabled)
        or(
            biometricSettingsRepository.isFaceAuthEnrolledAndEnabled,
            biometricSettingsRepository.isFingerprintEnrolledAndEnabled,
        )

    private val wasRebootedForMainlineUpdate
        get() = systemPropertiesHelper.get(SYS_BOOT_REASON_PROP) == REBOOT_MAINLINE_UPDATE
@@ -335,8 +326,5 @@ constructor(
    }
}

private fun and(flow: Flow<Boolean>, anotherFlow: Flow<Boolean>) =
    flow.combine(anotherFlow) { a, b -> a && b }

private fun or(flow: Flow<Boolean>, anotherFlow: Flow<Boolean>) =
    flow.combine(anotherFlow) { a, b -> a || b }
+1 −3
Original line number Diff line number Diff line
@@ -83,9 +83,7 @@ constructor(

    fun canShowAlternateBouncerForFingerprint(): Boolean {
        return bouncerRepository.alternateBouncerUIAvailable.value &&
            biometricSettingsRepository.isFingerprintEnrolled.value &&
            biometricSettingsRepository.isStrongBiometricAllowed.value &&
            biometricSettingsRepository.isFingerprintEnabledByDevicePolicy.value &&
            biometricSettingsRepository.isFingerprintAuthCurrentlyAllowed.value &&
            !keyguardUpdateMonitor.isFingerprintLockedOut &&
            !keyguardStateController.isUnlocked &&
            !statusBarStateController.isDozing
+68 −33
Original line number Diff line number Diff line
@@ -28,6 +28,9 @@ import com.android.internal.widget.LockPatternUtils
import com.android.systemui.Dumpable
import com.android.systemui.R
import com.android.systemui.biometrics.AuthController
import com.android.systemui.biometrics.data.repository.FacePropertyRepository
import com.android.systemui.biometrics.data.repository.FingerprintPropertyRepository
import com.android.systemui.biometrics.shared.model.SensorStrength
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
@@ -68,34 +71,32 @@ import kotlinx.coroutines.flow.transformLatest
 * upstream changes.
 */
interface BiometricSettingsRepository {
    /** Whether any fingerprints are enrolled for the current user. */
    val isFingerprintEnrolled: StateFlow<Boolean>

    /** Whether face authentication is enrolled for the current user. */
    val isFaceEnrolled: Flow<Boolean>

    /**
     * Whether face authentication is enabled/disabled based on system settings like device policy,
     * biometrics setting.
     * 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
     */
    val isFaceAuthenticationEnabled: Flow<Boolean>
    val isFingerprintEnrolledAndEnabled: StateFlow<Boolean>

    /**
     * Whether the current user is allowed to use a strong biometric for device entry based on
     * Android Security policies. If false, the user may be able to use primary authentication for
     * device entry.
     * If the current user can enter the device using fingerprint, right now.
     *
     * This returns true if there are no strong auth flags that restrict the user from using
     * fingerprint and [isFingerprintEnrolledAndEnabled] is true
     */
    val isStrongBiometricAllowed: StateFlow<Boolean>
    val isFingerprintAuthCurrentlyAllowed: StateFlow<Boolean>

    /**
     * Whether the current user is allowed to use a convenience biometric for device entry based on
     * Android Security policies. If false, the user may be able to use strong biometric or primary
     * authentication for device entry.
     * If the current user can use face auth to enter the device. This is true when the user has
     * face auth enrolled, and is enabled in settings/device policy.
     */
    val isNonStrongBiometricAllowed: StateFlow<Boolean>
    val isFaceAuthEnrolledAndEnabled: Flow<Boolean>

    /** Whether fingerprint feature is enabled for the current user by the DevicePolicy */
    val isFingerprintEnabledByDevicePolicy: StateFlow<Boolean>
    /**
     * If the current user can use face auth to enter the device right now. This is true when
     * [isFaceAuthEnrolledAndEnabled] is true and strong auth settings allow face auth to run and
     * face auth is supported by the current device posture.
     */
    val isFaceAuthCurrentlyAllowed: Flow<Boolean>

    /**
     * Whether face authentication is supported for the current device posture. Face auth can be
@@ -130,6 +131,8 @@ constructor(
    @Background backgroundDispatcher: CoroutineDispatcher,
    biometricManager: BiometricManager?,
    devicePostureRepository: DevicePostureRepository,
    facePropertyRepository: FacePropertyRepository,
    fingerprintPropertyRepository: FingerprintPropertyRepository,
    dumpManager: DumpManager,
) : BiometricSettingsRepository, Dumpable {

@@ -165,7 +168,9 @@ constructor(
    }

    override fun dump(pw: PrintWriter, args: Array<String?>) {
        pw.println("isFingerprintEnrolled=${isFingerprintEnrolled.value}")
        pw.println("isFingerprintEnrolledAndEnabled=${isFingerprintEnrolledAndEnabled.value}")
        pw.println("isFingerprintAuthCurrentlyAllowed=${isFingerprintAuthCurrentlyAllowed.value}")
        pw.println("isNonStrongBiometricAllowed=${isNonStrongBiometricAllowed.value}")
        pw.println("isStrongBiometricAllowed=${isStrongBiometricAllowed.value}")
        pw.println("isFingerprintEnabledByDevicePolicy=${isFingerprintEnabledByDevicePolicy.value}")
    }
@@ -180,7 +185,7 @@ constructor(
            user = UserHandle.ALL
        )

    override val isFingerprintEnrolled: StateFlow<Boolean> =
    private val isFingerprintEnrolled: Flow<Boolean> =
        selectedUserId
            .flatMapLatest { currentUserId ->
                conflatedCallbackFlow {
@@ -211,7 +216,7 @@ constructor(
                    authController.isFingerprintEnrolled(userRepository.getSelectedUserInfo().id)
            )

    override val isFaceEnrolled: Flow<Boolean> =
    private val isFaceEnrolled: Flow<Boolean> =
        selectedUserId.flatMapLatest { selectedUserId: Int ->
            conflatedCallbackFlow {
                val callback =
@@ -245,14 +250,6 @@ constructor(
            isFaceEnabledByBiometricsManager.map { biometricsEnabledForUser[userInfo.id] ?: false }
        }

    override val isFaceAuthenticationEnabled: Flow<Boolean>
        get() =
            combine(isFaceEnabledByBiometricsManagerForCurrentUser, isFaceEnabledByDevicePolicy) {
                biometricsManagerSetting,
                devicePolicySetting ->
                biometricsManagerSetting && devicePolicySetting
            }

    private val isFaceEnabledByDevicePolicy: Flow<Boolean> =
        combine(selectedUserId, devicePolicyChangedForAllUsers) { userId, _ ->
                devicePolicyManager.isFaceDisabled(userId)
@@ -263,6 +260,13 @@ constructor(
            .flowOn(backgroundDispatcher)
            .distinctUntilChanged()

    private val isFaceAuthenticationEnabled: Flow<Boolean> =
        combine(isFaceEnabledByBiometricsManagerForCurrentUser, isFaceEnabledByDevicePolicy) {
            biometricsManagerSetting,
            devicePolicySetting ->
            biometricsManagerSetting && devicePolicySetting
        }

    private val isFaceEnabledByBiometricsManager: Flow<Pair<Int, Boolean>> =
        conflatedCallbackFlow {
                val callback =
@@ -283,7 +287,7 @@ constructor(
            // being registered.
            .stateIn(scope, SharingStarted.Eagerly, Pair(0, false))

    override val isStrongBiometricAllowed: StateFlow<Boolean> =
    private val isStrongBiometricAllowed: StateFlow<Boolean> =
        strongAuthTracker.isStrongBiometricAllowed.stateIn(
            scope,
            SharingStarted.Eagerly,
@@ -293,7 +297,7 @@ constructor(
            )
        )

    override val isNonStrongBiometricAllowed: StateFlow<Boolean> =
    private val isNonStrongBiometricAllowed: StateFlow<Boolean> =
        strongAuthTracker.isNonStrongBiometricAllowed.stateIn(
            scope,
            SharingStarted.Eagerly,
@@ -303,7 +307,19 @@ constructor(
            )
        )

    override val isFingerprintEnabledByDevicePolicy: StateFlow<Boolean> =
    private val isFingerprintBiometricAllowed: Flow<Boolean> =
        fingerprintPropertyRepository.strength.flatMapLatest {
            if (it == SensorStrength.STRONG) isStrongBiometricAllowed
            else isNonStrongBiometricAllowed
        }

    private val isFaceBiometricsAllowed: Flow<Boolean> =
        facePropertyRepository.sensorInfo.flatMapLatest {
            if (it?.strength == SensorStrength.STRONG) isStrongBiometricAllowed
            else isNonStrongBiometricAllowed
        }

    private val isFingerprintEnabledByDevicePolicy: StateFlow<Boolean> =
        selectedUserId
            .flatMapLatest { userId ->
                devicePolicyChangedForAllUsers
@@ -319,6 +335,25 @@ constructor(
                        userRepository.getSelectedUserInfo().id
                    )
            )

    override val isFingerprintEnrolledAndEnabled: StateFlow<Boolean> =
        isFingerprintEnrolled
            .and(isFingerprintEnabledByDevicePolicy)
            .stateIn(scope, SharingStarted.Eagerly, false)

    override val isFingerprintAuthCurrentlyAllowed: StateFlow<Boolean> =
        isFingerprintEnrolledAndEnabled
            .and(isFingerprintBiometricAllowed)
            .stateIn(scope, SharingStarted.Eagerly, false)

    override val isFaceAuthEnrolledAndEnabled: Flow<Boolean>
        get() = isFaceAuthenticationEnabled.and(isFaceEnrolled)

    override val isFaceAuthCurrentlyAllowed: Flow<Boolean>
        get() =
            isFaceAuthEnrolledAndEnabled
                .and(isFaceBiometricsAllowed)
                .and(isFaceAuthSupportedInCurrentPosture)
}

@OptIn(ExperimentalCoroutinesApi::class)
+11 −21
Original line number Diff line number Diff line
@@ -26,8 +26,6 @@ import com.android.internal.logging.UiEventLogger
import com.android.keyguard.FaceAuthUiEvent
import com.android.systemui.Dumpable
import com.android.systemui.R
import com.android.systemui.biometrics.data.repository.FacePropertyRepository
import com.android.systemui.biometrics.shared.model.SensorStrength
import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
@@ -72,7 +70,6 @@ import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
@@ -162,7 +159,6 @@ constructor(
    @FaceAuthTableLog private val faceAuthLog: TableLogBuffer,
    private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
    private val featureFlags: FeatureFlags,
    facePropertyRepository: FacePropertyRepository,
    dumpManager: DumpManager,
) : DeviceEntryFaceAuthRepository, Dumpable {
    private var authCancellationSignal: CancellationSignal? = null
@@ -182,13 +178,6 @@ constructor(
    override val detectionStatus: Flow<FaceDetectionStatus>
        get() = _detectionStatus.filterNotNull()

    private val isFaceBiometricsAllowed: Flow<Boolean> =
        facePropertyRepository.sensorInfo.flatMapLatest {
            if (it?.strength == SensorStrength.STRONG)
                biometricSettingsRepository.isStrongBiometricAllowed
            else biometricSettingsRepository.isNonStrongBiometricAllowed
        }

    private val _isLockedOut = MutableStateFlow(false)
    override val isLockedOut: StateFlow<Boolean> = _isLockedOut

@@ -313,8 +302,10 @@ constructor(
                canFaceAuthOrDetectRun(faceDetectLog),
                logAndObserve(isBypassEnabled, "isBypassEnabled", faceDetectLog),
                logAndObserve(
                    isFaceBiometricsAllowed.isFalse().or(trustRepository.isCurrentUserTrusted),
                    "biometricIsNotAllowedOrCurrentUserIsTrusted",
                    biometricSettingsRepository.isFaceAuthCurrentlyAllowed
                        .isFalse()
                        .or(trustRepository.isCurrentUserTrusted),
                    "faceAuthIsNotCurrentlyAllowedOrCurrentUserIsTrusted",
                    faceDetectLog
                ),
                // We don't want to run face detect if fingerprint can be used to unlock the device
@@ -346,13 +337,8 @@ constructor(
    private fun canFaceAuthOrDetectRun(tableLogBuffer: TableLogBuffer): Flow<Boolean> {
        return listOf(
                logAndObserve(
                    biometricSettingsRepository.isFaceEnrolled,
                    "isFaceEnrolled",
                    tableLogBuffer
                ),
                logAndObserve(
                    biometricSettingsRepository.isFaceAuthenticationEnabled,
                    "isFaceAuthenticationEnabled",
                    biometricSettingsRepository.isFaceAuthEnrolledAndEnabled,
                    "isFaceAuthEnrolledAndEnabled",
                    tableLogBuffer
                ),
                logAndObserve(faceAuthPaused.isFalse(), "faceAuthIsNotPaused", tableLogBuffer),
@@ -406,7 +392,11 @@ constructor(
                    "currentUserIsNotTrusted",
                    faceAuthLog
                ),
                logAndObserve(isFaceBiometricsAllowed, "isFaceBiometricsAllowed", faceAuthLog),
                logAndObserve(
                    biometricSettingsRepository.isFaceAuthCurrentlyAllowed,
                    "isFaceAuthCurrentlyAllowed",
                    faceAuthLog
                ),
                logAndObserve(isAuthenticated.isFalse(), "faceNotAuthenticated", faceAuthLog),
            )
            .reduce(::and)
Loading