1 /*
2  * 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 
18 package com.android.systemui.biometrics.data.repository
19 
20 import android.hardware.face.FaceManager
21 import android.hardware.face.FaceSensorPropertiesInternal
22 import android.hardware.face.IFaceAuthenticatorsRegisteredCallback
23 import com.android.systemui.biometrics.shared.model.SensorStrength
24 import com.android.systemui.biometrics.shared.model.toSensorStrength
25 import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
26 import com.android.systemui.common.coroutine.ConflatedCallbackFlow
27 import com.android.systemui.dagger.SysUISingleton
28 import com.android.systemui.dagger.qualifiers.Application
29 import javax.inject.Inject
30 import kotlinx.coroutines.CoroutineScope
31 import kotlinx.coroutines.channels.awaitClose
32 import kotlinx.coroutines.flow.Flow
33 import kotlinx.coroutines.flow.SharingStarted
34 import kotlinx.coroutines.flow.flowOf
35 import kotlinx.coroutines.flow.map
36 import kotlinx.coroutines.flow.shareIn
37 
38 /** A repository for the global state of Face sensor. */
39 interface FacePropertyRepository {
40     /** Face sensor information, null if it is not available. */
41     val sensorInfo: Flow<FaceSensorInfo?>
42 }
43 
44 /** Describes a biometric sensor */
45 data class FaceSensorInfo(val id: Int, val strength: SensorStrength)
46 
47 private const val TAG = "FaceSensorPropertyRepositoryImpl"
48 
49 @SysUISingleton
50 class FacePropertyRepositoryImpl
51 @Inject
52 constructor(@Application private val applicationScope: CoroutineScope, faceManager: FaceManager?) :
53     FacePropertyRepository {
54 
55     private val sensorProps: Flow<List<FaceSensorPropertiesInternal>> =
56         faceManager?.let {
57             ConflatedCallbackFlow.conflatedCallbackFlow {
58                     val callback =
59                         object : IFaceAuthenticatorsRegisteredCallback.Stub() {
60                             override fun onAllAuthenticatorsRegistered(
61                                 sensors: List<FaceSensorPropertiesInternal>
62                             ) {
63                                 trySendWithFailureLogging(
64                                     sensors,
65                                     TAG,
66                                     "onAllAuthenticatorsRegistered"
67                                 )
68                             }
69                         }
70                     it.addAuthenticatorsRegisteredCallback(callback)
71                     awaitClose {}
72                 }
73                 .shareIn(applicationScope, SharingStarted.Eagerly)
74         }
75             ?: flowOf(emptyList())
76 
77     override val sensorInfo: Flow<FaceSensorInfo?> =
78         sensorProps
79             .map { it.firstOrNull() }
80             .map { it?.let { FaceSensorInfo(it.sensorId, it.sensorStrength.toSensorStrength()) } }
81 }
82