• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2024 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.FacePropertyRepository
20 import com.android.systemui.biometrics.shared.model.SensorStrength
21 import com.android.systemui.dagger.SysUISingleton
22 import javax.inject.Inject
23 import kotlinx.coroutines.flow.Flow
24 import kotlinx.coroutines.flow.StateFlow
25 import kotlinx.coroutines.flow.combine
26 import kotlinx.coroutines.flow.flatMapLatest
27 import kotlinx.coroutines.flow.flowOf
28 import kotlinx.coroutines.flow.map
29 
30 /**
31  * Individual biometrics (ie: fingerprint or face) may not be allowed to be used based on the
32  * lockout states of biometrics of the same or higher sensor strength.
33  *
34  * This class coordinates the lockout states of each individual biometric based on the lockout
35  * states of other biometrics.
36  */
37 @SysUISingleton
38 class DeviceEntryBiometricsAllowedInteractor
39 @Inject
40 constructor(
41     deviceEntryFingerprintAuthInteractor: DeviceEntryFingerprintAuthInteractor,
42     deviceEntryFaceAuthInteractor: DeviceEntryFaceAuthInteractor,
43     biometricSettingsInteractor: DeviceEntryBiometricSettingsInteractor,
44     facePropertyRepository: FacePropertyRepository,
45 ) {
46     /**
47      * Whether face is locked out due to too many failed face attempts. This currently includes
48      * whether face is not allowed based on other biometric lockouts; however does not include if
49      * face isn't allowed due to other strong or primary authentication requirements.
50      */
51     val isFaceLockedOut: StateFlow<Boolean> = deviceEntryFaceAuthInteractor.isLockedOut
52 
53     private val isStrongFaceAuth: Flow<Boolean> =
54         facePropertyRepository.sensorInfo.map { it?.strength == SensorStrength.STRONG }
55 
56     private val isStrongFaceAuthLockedOut: Flow<Boolean> =
57         combine(isStrongFaceAuth, isFaceLockedOut) { isStrongFaceAuth, isFaceAuthLockedOut ->
58             isStrongFaceAuth && isFaceAuthLockedOut
59         }
60 
61     /**
62      * Whether fingerprint is locked out due to too many failed fingerprint attempts. This does NOT
63      * include whether fingerprint is not allowed based on other biometric lockouts nor if
64      * fingerprint isn't allowed due to other strong or primary authentication requirements.
65      */
66     val isFingerprintLockedOut: StateFlow<Boolean> =
67         deviceEntryFingerprintAuthInteractor.isLockedOut
68 
69     /**
70      * Whether fingerprint authentication is currently allowed for the user. This is true if the
71      * user has fingerprint auth enabled, enrolled, it is not disabled by any security timeouts by
72      * [com.android.systemui.keyguard.shared.model.AuthenticationFlags], not locked out due to too
73      * many incorrect attempts, and other biometrics at a higher or equal strenght are not locking
74      * fingerprint out.
75      */
76     val isFingerprintAuthCurrentlyAllowed: Flow<Boolean> =
77         combine(
78             isFingerprintLockedOut,
79             biometricSettingsInteractor.fingerprintAuthCurrentlyAllowed,
80             isStrongFaceAuthLockedOut,
81         ) { fpLockedOut, fpAllowedBySettings, strongAuthFaceAuthLockedOut ->
82             !fpLockedOut && fpAllowedBySettings && !strongAuthFaceAuthLockedOut
83         }
84 
85     /** Whether fingerprint authentication is currently allowed while on the bouncer. */
86     val isFingerprintCurrentlyAllowedOnBouncer =
87         deviceEntryFingerprintAuthInteractor.isSensorUnderDisplay.flatMapLatest { sensorBelowDisplay
88             ->
89             if (sensorBelowDisplay) {
90                 flowOf(false)
91             } else {
92                 isFingerprintAuthCurrentlyAllowed
93             }
94         }
95 }
96