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.keyguard.ui.viewmodel
18 
19 import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
20 import com.android.systemui.deviceentry.domain.interactor.BiometricMessageInteractor
21 import com.android.systemui.deviceentry.shared.model.BiometricMessage
22 import com.android.systemui.deviceentry.shared.model.FaceMessage
23 import com.android.systemui.deviceentry.shared.model.FaceTimeoutMessage
24 import com.android.systemui.deviceentry.shared.model.FingerprintLockoutMessage
25 import com.android.systemui.deviceentry.shared.model.FingerprintMessage
26 import com.android.systemui.statusbar.KeyguardIndicationController.DEFAULT_MESSAGE_TIME
27 import com.android.systemui.util.kotlin.sample
28 import javax.inject.Inject
29 import kotlinx.coroutines.ExperimentalCoroutinesApi
30 import kotlinx.coroutines.flow.Flow
31 import kotlinx.coroutines.flow.filter
32 import kotlinx.coroutines.flow.filterIsInstance
33 import kotlinx.coroutines.flow.filterNot
34 import kotlinx.coroutines.flow.flatMapLatest
35 import kotlinx.coroutines.flow.flowOf
36 import kotlinx.coroutines.flow.map
37 import kotlinx.coroutines.flow.merge
38 import kotlinx.coroutines.flow.onStart
39 
40 /** View model for the alternate bouncer message area. */
41 @ExperimentalCoroutinesApi
42 class AlternateBouncerMessageAreaViewModel
43 @Inject
44 constructor(
45     biometricMessageInteractor: BiometricMessageInteractor,
46     alternateBouncerInteractor: AlternateBouncerInteractor,
47     systemClock: com.android.systemui.util.time.SystemClock,
48 ) {
49     private val fingerprintMessageWithTimestamp: Flow<Pair<FingerprintMessage?, Long>> =
50         biometricMessageInteractor.fingerprintMessage
51             .filterNot { it is FingerprintLockoutMessage }
52             .map { Pair(it, systemClock.uptimeMillis()) }
53             .filterIsInstance<Pair<FingerprintMessage?, Long>>()
54             .onStart { emit(Pair(null, -3500L)) }
55     private val fingerprintMessage: Flow<FingerprintMessage> =
56         fingerprintMessageWithTimestamp.filter { it.first != null }.map { it.first!! }
57     private val faceMessage: Flow<FaceMessage> =
58         biometricMessageInteractor.faceMessage
59             .filterNot { it is FaceTimeoutMessage }
60             // Don't show face messages if within the default message time for fp messages to show
61             .sample(fingerprintMessageWithTimestamp, ::Pair)
62             .filter { (_, fpMessage) ->
63                 (systemClock.uptimeMillis() - fpMessage.second) >= DEFAULT_MESSAGE_TIME
64             }
65             .map { (faceMsg, _) -> faceMsg }
66 
67     val message: Flow<BiometricMessage?> =
68         alternateBouncerInteractor.isVisible.flatMapLatest { isVisible ->
69             if (isVisible) {
70                 merge(
71                     fingerprintMessage,
72                     faceMessage,
73                 )
74             } else {
75                 flowOf(null)
76             }
77         }
78 }
79