1 /*
<lambda>null2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.systemui.deviceentry.domain.interactor
18 
19 import com.android.systemui.biometrics.data.repository.FingerprintPropertyRepository
20 import com.android.systemui.biometrics.shared.model.FingerprintSensorType
21 import com.android.systemui.dagger.SysUISingleton
22 import com.android.systemui.keyguard.data.repository.DeviceEntryFingerprintAuthRepository
23 import com.android.systemui.keyguard.shared.model.ErrorFingerprintAuthenticationStatus
24 import com.android.systemui.keyguard.shared.model.FailFingerprintAuthenticationStatus
25 import com.android.systemui.keyguard.shared.model.FingerprintAuthenticationStatus
26 import com.android.systemui.keyguard.shared.model.HelpFingerprintAuthenticationStatus
27 import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
28 import javax.inject.Inject
29 import kotlinx.coroutines.ExperimentalCoroutinesApi
30 import kotlinx.coroutines.flow.Flow
31 import kotlinx.coroutines.flow.StateFlow
32 import kotlinx.coroutines.flow.combine
33 import kotlinx.coroutines.flow.filterIsInstance
34 import kotlinx.coroutines.flow.flatMapLatest
35 import kotlinx.coroutines.flow.flowOf
36 import kotlinx.coroutines.flow.map
37 
38 @OptIn(ExperimentalCoroutinesApi::class)
39 @SysUISingleton
40 class DeviceEntryFingerprintAuthInteractor
41 @Inject
42 constructor(
43     repository: DeviceEntryFingerprintAuthRepository,
44     biometricSettingsInteractor: DeviceEntryBiometricSettingsInteractor,
45     fingerprintPropertyRepository: FingerprintPropertyRepository,
46 ) {
47     /**
48      * Whether fingerprint authentication is currently running or not. This does not mean the user
49      * [isEngaged] with the fingerprint.
50      */
51     val isRunning: Flow<Boolean> = repository.isRunning
52 
53     /** Whether the user is actively engaging with the fingerprint sensor */
54     val isEngaged: StateFlow<Boolean> = repository.isEngaged
55 
56     /** Provide the current status of fingerprint authentication. */
57     val authenticationStatus: Flow<FingerprintAuthenticationStatus> =
58         repository.authenticationStatus
59 
60     val isLockedOut: Flow<Boolean> = repository.isLockedOut
61 
62     val fingerprintFailure: Flow<FailFingerprintAuthenticationStatus> =
63         repository.authenticationStatus.filterIsInstance<FailFingerprintAuthenticationStatus>()
64     val fingerprintError: Flow<ErrorFingerprintAuthenticationStatus> =
65         repository.authenticationStatus.filterIsInstance<ErrorFingerprintAuthenticationStatus>()
66     val fingerprintHelp: Flow<HelpFingerprintAuthenticationStatus> =
67         repository.authenticationStatus.filterIsInstance<HelpFingerprintAuthenticationStatus>()
68 
69     val fingerprintSuccess: Flow<SuccessFingerprintAuthenticationStatus> =
70         repository.authenticationStatus.filterIsInstance<SuccessFingerprintAuthenticationStatus>()
71 
72     /**
73      * Whether fingerprint authentication is currently allowed for the user. This is true if the
74      * user has fingerprint auth enabled, enrolled, it is not disabled by any security timeouts by
75      * [com.android.systemui.keyguard.shared.model.AuthenticationFlags] and not locked out due to
76      * too many incorrect attempts.
77      */
78     val isFingerprintAuthCurrentlyAllowed: Flow<Boolean> =
79         combine(isLockedOut, biometricSettingsInteractor.fingerprintAuthCurrentlyAllowed, ::Pair)
80             .map { (lockedOut, currentlyAllowed) -> !lockedOut && currentlyAllowed }
81 
82     /**
83      * Whether the fingerprint sensor is present under the display as opposed to being on the power
84      * button or behind/rear of the phone.
85      */
86     val isSensorUnderDisplay =
87         fingerprintPropertyRepository.sensorType.map(FingerprintSensorType::isUdfps)
88 
89     /** Whether fingerprint authentication is currently allowed while on the bouncer. */
90     val isFingerprintCurrentlyAllowedOnBouncer =
91         isSensorUnderDisplay.flatMapLatest { sensorBelowDisplay ->
92             if (sensorBelowDisplay) {
93                 flowOf(false)
94             } else {
95                 isFingerprintAuthCurrentlyAllowed
96             }
97         }
98 }
99