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.biometrics.domain.interactor
18
19 import android.app.ActivityTaskManager
20 import android.util.Log
21 import com.android.systemui.biometrics.data.repository.BiometricStatusRepository
22 import com.android.systemui.biometrics.data.repository.FingerprintPropertyRepository
23 import com.android.systemui.biometrics.shared.model.AuthenticationReason
24 import com.android.systemui.biometrics.shared.model.AuthenticationReason.SettingsOperations
25 import com.android.systemui.keyguard.shared.model.FingerprintAuthenticationStatus
26 import javax.inject.Inject
27 import kotlinx.coroutines.flow.Flow
28 import kotlinx.coroutines.flow.combine
29 import kotlinx.coroutines.flow.distinctUntilChanged
30 import kotlinx.coroutines.flow.onEach
31
32 /** Encapsulates business logic for interacting with biometric authentication state. */
33 interface BiometricStatusInteractor {
34 /**
35 * The logical reason for the current side fingerprint sensor auth operation if one is on-going,
36 * filtered for when the overlay should be shown, otherwise [NotRunning].
37 */
38 val sfpsAuthenticationReason: Flow<AuthenticationReason>
39
40 /** The current status of an acquired fingerprint. */
41 val fingerprintAcquiredStatus: Flow<FingerprintAuthenticationStatus>
42 }
43
44 class BiometricStatusInteractorImpl
45 @Inject
46 constructor(
47 private val activityTaskManager: ActivityTaskManager,
48 biometricStatusRepository: BiometricStatusRepository,
49 fingerprintPropertyRepository: FingerprintPropertyRepository,
50 ) : BiometricStatusInteractor {
51
52 override val sfpsAuthenticationReason: Flow<AuthenticationReason> =
53 combine(
54 biometricStatusRepository.fingerprintAuthenticationReason,
55 fingerprintPropertyRepository.sensorType
reasonnull56 ) { reason: AuthenticationReason, sensorType ->
57 if (
58 sensorType.isPowerButton() &&
59 reason.isReasonToAlwaysUpdateSfpsOverlay(activityTaskManager)
60 ) {
61 reason
62 } else {
63 AuthenticationReason.NotRunning
64 }
65 }
66 .distinctUntilChanged()
<lambda>null67 .onEach { Log.d(TAG, "sfpsAuthenticationReason updated: $it") }
68
69 override val fingerprintAcquiredStatus: Flow<FingerprintAuthenticationStatus> =
70 biometricStatusRepository.fingerprintAcquiredStatus
71
72 companion object {
73 private const val TAG = "BiometricStatusInteractor"
74 }
75 }
76
77 /** True if the sfps overlay should always be updated for this request source, false otherwise. */
isReasonToAlwaysUpdateSfpsOverlaynull78 private fun AuthenticationReason.isReasonToAlwaysUpdateSfpsOverlay(
79 activityTaskManager: ActivityTaskManager
80 ): Boolean =
81 when (this) {
82 AuthenticationReason.DeviceEntryAuthentication -> false
83 AuthenticationReason.SettingsAuthentication(SettingsOperations.OTHER) ->
84 when (activityTaskManager.topClass()) {
85 // TODO(b/186176653): exclude fingerprint overlays from this list view
86 "com.android.settings.biometrics.fingerprint.FingerprintSettings" -> false
87 else -> true
88 }
89 else -> true
90 }
91
topClassnull92 internal fun ActivityTaskManager.topClass(): String =
93 getTasks(1).firstOrNull()?.topActivity?.className ?: ""
94