1 /* 2 * 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.settings.biometrics.fingerprint2.data.repository 18 19 import android.annotation.SuppressLint 20 import android.hardware.biometrics.ComponentInfoInternal 21 import android.hardware.biometrics.SensorLocationInternal 22 import android.hardware.biometrics.SensorProperties 23 import android.hardware.fingerprint.FingerprintManager 24 import android.hardware.fingerprint.FingerprintSensorProperties 25 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal 26 import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback 27 import android.util.Log 28 import com.android.systemui.biometrics.shared.model.FingerprintSensor 29 import com.android.systemui.biometrics.shared.model.toFingerprintSensor 30 import kotlinx.coroutines.CoroutineDispatcher 31 import kotlinx.coroutines.CoroutineScope 32 import kotlinx.coroutines.channels.awaitClose 33 import kotlinx.coroutines.flow.Flow 34 import kotlinx.coroutines.flow.MutableSharedFlow 35 import kotlinx.coroutines.flow.SharedFlow 36 import kotlinx.coroutines.flow.SharingStarted 37 import kotlinx.coroutines.flow.asSharedFlow 38 import kotlinx.coroutines.flow.callbackFlow 39 import kotlinx.coroutines.flow.flatMapLatest 40 import kotlinx.coroutines.flow.flow 41 import kotlinx.coroutines.flow.shareIn 42 import kotlinx.coroutines.flow.stateIn 43 import kotlinx.coroutines.flow.transform 44 import kotlinx.coroutines.launch 45 import kotlinx.coroutines.withContext 46 47 /** 48 * Provides the [FingerprintSensor] 49 * 50 * TODO(b/313493336): Move this to systemui 51 */ 52 interface FingerprintSensorRepository { 53 /** Get the [FingerprintSensor] */ 54 val fingerprintSensor: Flow<FingerprintSensor> 55 56 /** Indicates if this device supports the side fingerprint sensor */ 57 val hasSideFps: Flow<Boolean> 58 } 59 60 class FingerprintSensorRepositoryImpl( 61 private val fingerprintManager: FingerprintManager, 62 backgroundDispatcher: CoroutineDispatcher, 63 activityScope: CoroutineScope, 64 ) : FingerprintSensorRepository { 65 66 private val _fingerprintSensor = MutableSharedFlow<FingerprintSensor>(replay = 1) 67 override val fingerprintSensor: Flow<FingerprintSensor> 68 get() = _fingerprintSensor.asSharedFlow() 69 70 init { <lambda>null71 activityScope.launch { 72 callbackFlow{ 73 val callback = 74 object : IFingerprintAuthenticatorsRegisteredCallback.Stub() { 75 @SuppressLint("LongLogTag") 76 override fun onAllAuthenticatorsRegistered( 77 sensors: List<FingerprintSensorPropertiesInternal> 78 ) { 79 if (sensors.isEmpty()) { 80 Log.e(TAG, "empty sensors from onAllAuthenticatorsRegistered") 81 } else { 82 trySend(sensors[0]) 83 channel.close() 84 } 85 } 86 } 87 withContext(backgroundDispatcher) { 88 fingerprintManager.addAuthenticatorsRegisteredCallback(callback) 89 } 90 awaitClose {} 91 }.collect { 92 _fingerprintSensor.emit(it.toFingerprintSensor()) 93 } 94 } 95 } 96 97 override val hasSideFps: Flow<Boolean> = <lambda>null98 fingerprintSensor.flatMapLatest { flow { emit(fingerprintManager.isPowerbuttonFps()) } } 99 100 private companion object { 101 const val TAG = "FingerprintSensorRepository" 102 } 103 } 104