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

Commit 06994af7 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Remove biometric chained combine operators" into main

parents d0f30ffd 60954bed
Loading
Loading
Loading
Loading
+50 −52
Original line number Diff line number Diff line
@@ -281,16 +281,23 @@ constructor(
                    *gatingConditionsForAuthAndDetect(),
                    Pair(isBypassEnabled, "isBypassEnabled"),
                    Pair(
                        biometricSettingsRepository.isFaceAuthCurrentlyAllowed
                            .isFalse()
                            .or(isLockedOut)
                            .or(keyguardRepository.isKeyguardDismissible),
                        combine(
                            biometricSettingsRepository.isFaceAuthCurrentlyAllowed,
                            isLockedOut,
                            keyguardRepository.isKeyguardDismissible,
                        ) { faceAuthCurrentlyAllowed, isLockedOut, isKeyguardDismissible ->
                            !faceAuthCurrentlyAllowed || isLockedOut || isKeyguardDismissible
                        },
                        "faceAuthIsNotCurrentlyAllowedOrCurrentUserIsTrusted",
                    ),
                    // We don't want to run face detect if fingerprint can be used to unlock the
                    // device bc it's not possible to authenticate with FP from the bouncer (UDFPS)
                    Pair(
                        and(isUdfps(), deviceEntryFingerprintAuthRepository.isRunning).isFalse(),
                        combine(isUdfps(), deviceEntryFingerprintAuthRepository.isRunning) {
                            isUdfps,
                            fingerprintAuthRunning ->
                            !(isUdfps && fingerprintAuthRunning)
                        },
                        "udfpsAuthIsNotPossibleAnymore",
                    ),
                )
@@ -385,13 +392,14 @@ constructor(
    private fun gatingConditionsForAuthAndDetect(): Array<Pair<Flow<Boolean>, String>> {
        return arrayOf(
            Pair(
                and(
                combine(
                    displayStateInteractor.isDefaultDisplayOff,
                    keyguardTransitionInteractor.isFinishedInStateWhere(
                        KeyguardState::deviceIsAwakeInState
                    ),
                    )
                    .isFalse(),
                ) { defaultDisplayOff, finishedInAwakeState ->
                    !(defaultDisplayOff && finishedInAwakeState)
                },
                // this can happen if an app is requesting for screen off, the display can
                // turn off without wakefulness.isStartingToSleepOrAsleep calls
                "displayIsNotOffWhileFullyTransitionedToAwake",
@@ -402,23 +410,21 @@ constructor(
            ),
            Pair(
                if (SceneContainerFlag.isEnabled) {
                    sceneInteractor
                        .get()
                        .transitionState
                        .map { it.isTransitioning(to = Scenes.Gone) || it.isIdle(Scenes.Gone) }
                        .isFalse()
                    sceneInteractor.get().transitionState.map {
                        !it.isTransitioning(to = Scenes.Gone) && !it.isIdle(Scenes.Gone)
                    }
                } else {
                    (keyguardTransitionInteractor
                            .isFinishedIn(KeyguardState.GONE)
                            .or(
                    combine(
                        keyguardTransitionInteractor.isFinishedIn(KeyguardState.GONE),
                        keyguardTransitionInteractor.isInTransition(
                            Edge.create(to = Scenes.Gone),
                            Edge.create(to = KeyguardState.GONE),
                                )
                            ))
                        .isFalse()
                        ),
                    ) { finishedInGone, transitioningToGone ->
                        !finishedInGone && !transitioningToGone
                    }
                },
                "keyguardNotGoneOrTransitioningToGone",
                "keyguardNotGoneAndNotTransitioningToGone",
            ),
            Pair(
                keyguardTransitionInteractor
@@ -427,19 +433,19 @@ constructor(
                "deviceNotTransitioningToAsleepState",
            ),
            Pair(
                keyguardInteractor.isSecureCameraActive
                    .isFalse()
                    .or(
                        alternateBouncerInteractor.isVisible.or(
                combine(
                    keyguardInteractor.isSecureCameraActive,
                    alternateBouncerInteractor.isVisible,
                    if (SceneContainerFlag.isEnabled) {
                        sceneInteractor.get().transitionState.map {
                            it.isIdle(overlay = Overlays.Bouncer)
                        }
                    } else {
                        keyguardInteractor.primaryBouncerShowing
                            }
                        )
                    ),
                    },
                ) { isSecureCameraActive, alternateBouncerVisible, primaryBouncerShowing ->
                    !isSecureCameraActive || alternateBouncerVisible || primaryBouncerShowing
                },
                "secureCameraNotActiveOrAnyBouncerIsShowing",
            ),
            Pair(
@@ -452,10 +458,10 @@ constructor(
            ),
            Pair(keyguardRepository.isKeyguardShowing, "isKeyguardShowing"),
            Pair(
                userRepository.selectedUser
                    .map { it.selectionStatus == SelectionStatus.SELECTION_IN_PROGRESS }
                    .isFalse(),
                "userSwitchingInProgress",
                userRepository.selectedUser.map {
                    it.selectionStatus != SelectionStatus.SELECTION_IN_PROGRESS
                },
                "userSwitchingNotInProgress",
            ),
        )
    }
@@ -769,14 +775,6 @@ constructor(
    }
}

/** Combine two boolean flows by and-ing both of them */
private fun and(flow: Flow<Boolean>, anotherFlow: Flow<Boolean>) =
    flow.combine(anotherFlow) { a, b -> a && b }

/** Combine two boolean flows by or-ing both of them */
private fun Flow<Boolean>.or(anotherFlow: Flow<Boolean>) =
    this.combine(anotherFlow) { a, b -> a || b }

/** "Not" the given flow. The return [Flow] will be true when [this] flow is false. */
private fun Flow<Boolean>.isFalse(): Flow<Boolean> {
    return this.map { !it }
+46 −34
Original line number Diff line number Diff line
@@ -188,7 +188,7 @@ constructor(
    private val devicePolicyChangedForAllUsers =
        broadcastDispatcher.broadcastFlow(
            filter = IntentFilter(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED),
            user = UserHandle.ALL
            user = UserHandle.ALL,
        )

    private val isFingerprintEnrolled: Flow<Boolean> =
@@ -199,13 +199,13 @@ constructor(
                        override fun onEnrollmentsChanged(
                            sensorBiometricType: BiometricType,
                            userId: Int,
                            hasEnrollments: Boolean
                            hasEnrollments: Boolean,
                        ) {
                            if (sensorBiometricType.isFingerprint && userId == currentUserId) {
                                trySendWithFailureLogging(
                                    hasEnrollments,
                                    TAG,
                                    "update fpEnrollment"
                                    "update fpEnrollment",
                                )
                            }
                        }
@@ -214,7 +214,7 @@ constructor(
                trySendWithFailureLogging(
                    authController.isFingerprintEnrolled(currentUserId),
                    TAG,
                    "Initial value of fingerprint enrollment"
                    "Initial value of fingerprint enrollment",
                )
                awaitClose { authController.removeCallback(callback) }
            }
@@ -228,13 +228,13 @@ constructor(
                        override fun onEnrollmentsChanged(
                            sensorBiometricType: BiometricType,
                            userId: Int,
                            hasEnrollments: Boolean
                            hasEnrollments: Boolean,
                        ) {
                            if (sensorBiometricType == BiometricType.FACE) {
                                trySendWithFailureLogging(
                                    authController.isFaceAuthEnrolled(selectedUserId),
                                    TAG,
                                    "Face enrollment changed"
                                    "Face enrollment changed",
                                )
                            }
                        }
@@ -243,7 +243,7 @@ constructor(
                trySendWithFailureLogging(
                    authController.isFaceAuthEnrolled(selectedUserId),
                    TAG,
                    "Initial value of face auth enrollment"
                    "Initial value of face auth enrollment",
                )
                awaitClose { authController.removeCallback(callback) }
            }
@@ -327,8 +327,8 @@ constructor(
            SharingStarted.Eagerly,
            strongAuthTracker.isBiometricAllowedForUser(
                true,
                userRepository.getSelectedUserInfo().id
            )
                userRepository.getSelectedUserInfo().id,
            ),
        )

    private val isNonStrongBiometricAllowed: StateFlow<Boolean> =
@@ -337,8 +337,8 @@ constructor(
            SharingStarted.Eagerly,
            strongAuthTracker.isBiometricAllowedForUser(
                false,
                userRepository.getSelectedUserInfo().id
            )
                userRepository.getSelectedUserInfo().id,
            ),
        )

    private val isFingerprintBiometricAllowed: Flow<Boolean> =
@@ -363,33 +363,47 @@ constructor(
        }

    override val isFingerprintEnrolledAndEnabled: StateFlow<Boolean> =
        isFingerprintEnrolled
            .and(isFingerprintEnabledForCurrentUser)
            .and(isFingerprintEnabledByDevicePolicy)
        combine(
                isFingerprintEnrolled,
                isFingerprintEnabledForCurrentUser,
                isFingerprintEnabledByDevicePolicy,
            ) { enrolled, enabledForCurrentUser, devicePolicyEnabled ->
                enrolled && enabledForCurrentUser && devicePolicyEnabled
            }
            .stateIn(scope, SharingStarted.Eagerly, false)

    override val isFingerprintAuthCurrentlyAllowed: StateFlow<Boolean> =
        isFingerprintEnrolledAndEnabled
            .and(isFingerprintBiometricAllowed)
        combine(isFingerprintEnrolledAndEnabled, isFingerprintBiometricAllowed) {
                enrolledAndEnabled,
                allowed ->
                enrolledAndEnabled && allowed
            }
            .stateIn(scope, SharingStarted.Eagerly, false)

    override val isFaceAuthEnrolledAndEnabled: StateFlow<Boolean> =
        isFaceAuthenticationEnabled
            .and(isFaceEnrolled)
            .and(mobileConnectionsRepository.isAnySimSecure.isFalse())
        combine(
                isFaceAuthenticationEnabled,
                isFaceEnrolled,
                mobileConnectionsRepository.isAnySimSecure,
            ) { enabled, enrolled, isAnySimSecure ->
                enabled && enrolled && !isAnySimSecure
            }
            .stateIn(scope, SharingStarted.Eagerly, false)

    override val isFaceAuthCurrentlyAllowed: Flow<Boolean> =
        isFaceAuthEnrolledAndEnabled
            .and(isFaceBiometricsAllowed)
            .and(isFaceAuthSupportedInCurrentPosture)
        combine(
            isFaceAuthEnrolledAndEnabled,
            isFaceBiometricsAllowed,
            isFaceAuthSupportedInCurrentPosture,
        ) { enrolledAndEnabled, allowed, supportedInCurrentPosture ->
            enrolledAndEnabled && allowed && supportedInCurrentPosture
        }
}

private class StrongAuthTracker(
    private val userRepository: UserRepository,
    @ShadeDisplayAware context: Context?
) :
    LockPatternUtils.StrongAuthTracker(context) {
    @ShadeDisplayAware context: Context?,
) : LockPatternUtils.StrongAuthTracker(context) {

    private val selectedUserId =
        userRepository.selectedUserInfo.map { it.id }.distinctUntilChanged()
@@ -418,8 +432,8 @@ private class StrongAuthTracker(

    /** isNonStrongBiometricAllowed for the current user. */
    val isNonStrongBiometricAllowed: Flow<Boolean> =
        selectedUserId
            .flatMapLatest { userId ->
        combine(
            selectedUserId.flatMapLatest { userId ->
                _nonStrongBiometricAllowed
                    .filter { it.first == userId }
                    .map { it.second }
@@ -427,8 +441,11 @@ private class StrongAuthTracker(
                        Log.d(TAG, "isNonStrongBiometricAllowed changed for current user: $it")
                    }
                    .onStart { emit(isNonStrongBiometricAllowedAfterIdleTimeout(userId)) }
            },
            isStrongBiometricAllowed,
        ) { nonStrongBiometricAllowed, strongBiometricAllowed ->
            nonStrongBiometricAllowed && strongBiometricAllowed
        }
            .and(isStrongBiometricAllowed)

    private val currentUserId
        get() = userRepository.getSelectedUserInfo().id
@@ -454,8 +471,3 @@ private fun DevicePolicyManager.isFingerprintDisabled(userId: Int): Boolean =

private fun DevicePolicyManager.isNotActive(userId: Int, policy: Int): Boolean =
    (getKeyguardDisabledFeatures(null, userId) and policy) == 0

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

private fun Flow<Boolean>.isFalse(): Flow<Boolean> = this.map { !it }