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 package com.android.systemui.keyguard.data.repository 18 19 import android.hardware.biometrics.BiometricSourceType 20 import com.android.keyguard.KeyguardUpdateMonitor 21 import com.android.keyguard.KeyguardUpdateMonitorCallback 22 import com.android.systemui.Dumpable 23 import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging 24 import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow 25 import com.android.systemui.dagger.SysUISingleton 26 import com.android.systemui.dagger.qualifiers.Application 27 import com.android.systemui.dump.DumpManager 28 import java.io.PrintWriter 29 import javax.inject.Inject 30 import kotlinx.coroutines.CoroutineScope 31 import kotlinx.coroutines.channels.awaitClose 32 import kotlinx.coroutines.flow.SharingStarted 33 import kotlinx.coroutines.flow.StateFlow 34 import kotlinx.coroutines.flow.stateIn 35 36 /** Encapsulates state about device entry fingerprint auth mechanism. */ 37 interface DeviceEntryFingerprintAuthRepository { 38 /** Whether the device entry fingerprint auth is locked out. */ 39 val isLockedOut: StateFlow<Boolean> 40 } 41 42 /** 43 * Implementation of [DeviceEntryFingerprintAuthRepository] that uses [KeyguardUpdateMonitor] as the 44 * source of truth. 45 * 46 * Dependency on [KeyguardUpdateMonitor] will be removed once fingerprint auth state is moved out of 47 * [KeyguardUpdateMonitor] 48 */ 49 @SysUISingleton 50 class DeviceEntryFingerprintAuthRepositoryImpl 51 @Inject 52 constructor( 53 val keyguardUpdateMonitor: KeyguardUpdateMonitor, 54 @Application scope: CoroutineScope, 55 dumpManager: DumpManager, 56 ) : DeviceEntryFingerprintAuthRepository, Dumpable { 57 58 init { 59 dumpManager.registerDumpable(this) 60 } 61 dumpnull62 override fun dump(pw: PrintWriter, args: Array<String?>) { 63 pw.println("isLockedOut=${isLockedOut.value}") 64 } 65 66 override val isLockedOut: StateFlow<Boolean> = <lambda>null67 conflatedCallbackFlow { 68 val sendLockoutUpdate = 69 fun() { 70 trySendWithFailureLogging( 71 keyguardUpdateMonitor.isFingerprintLockedOut, 72 TAG, 73 "onLockedOutStateChanged" 74 ) 75 } 76 val callback = 77 object : KeyguardUpdateMonitorCallback() { 78 override fun onLockedOutStateChanged( 79 biometricSourceType: BiometricSourceType? 80 ) { 81 if (biometricSourceType == BiometricSourceType.FINGERPRINT) { 82 sendLockoutUpdate() 83 } 84 } 85 } 86 keyguardUpdateMonitor.registerCallback(callback) 87 sendLockoutUpdate() 88 awaitClose { keyguardUpdateMonitor.removeCallback(callback) } 89 } 90 .stateIn(scope, started = SharingStarted.Eagerly, initialValue = false) 91 92 companion object { 93 const val TAG = "DeviceEntryFingerprintAuthRepositoryImpl" 94 } 95 } 96