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.domain.interactor
18 
19 import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
20 import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
21 import com.android.systemui.dagger.SysUISingleton
22 import com.android.systemui.keyguard.data.repository.KeyguardRepository
23 import com.android.systemui.keyguard.data.repository.TrustRepository
24 import com.android.systemui.keyguard.shared.model.DismissAction
25 import com.android.systemui.keyguard.shared.model.KeyguardDone
26 import com.android.systemui.power.domain.interactor.PowerInteractor
27 import com.android.systemui.user.domain.interactor.SelectedUserInteractor
28 import com.android.systemui.util.kotlin.Utils.Companion.toQuad
29 import com.android.systemui.util.kotlin.sample
30 import javax.inject.Inject
31 import kotlinx.coroutines.flow.Flow
32 import kotlinx.coroutines.flow.combine
33 import kotlinx.coroutines.flow.filter
34 import kotlinx.coroutines.flow.map
35 import kotlinx.coroutines.flow.merge
36 
37 /** Encapsulates business logic for requesting the keyguard to dismiss/finish/done. */
38 @SysUISingleton
39 class KeyguardDismissInteractor
40 @Inject
41 constructor(
42     trustRepository: TrustRepository,
43     private val keyguardRepository: KeyguardRepository,
44     primaryBouncerInteractor: PrimaryBouncerInteractor,
45     alternateBouncerInteractor: AlternateBouncerInteractor,
46     powerInteractor: PowerInteractor,
47     private val selectedUserInteractor: SelectedUserInteractor,
48 ) {
49     /*
50      * Updates when a biometric has authenticated the device and is requesting to dismiss
51      * the keyguard. When true, a class 3 biometrics has authenticated. Else, a lower class
52      * biometric strength has authenticated and is requesting to dismiss the keyguard.
53      */
54     private val biometricAuthenticatedRequestDismissKeyguard: Flow<Unit> =
55         primaryBouncerInteractor.keyguardAuthenticatedBiometrics.map {} // map to Unit
56 
57     /*
58      * Updates when a trust change is requesting to dismiss the keyguard and is able to do so
59      * in the current device state.
60      */
61     private val onTrustGrantedRequestDismissKeyguard: Flow<Unit> =
62         trustRepository.trustAgentRequestingToDismissKeyguard
63             .sample(
64                 combine(
65                     primaryBouncerInteractor.isShowing,
66                     alternateBouncerInteractor.isVisible,
67                     powerInteractor.isInteractive,
68                     ::Triple
69                 ),
70                 ::toQuad
71             )
72             .filter { (trustModel, primaryBouncerShowing, altBouncerShowing, interactive) ->
73                 val bouncerShowing = primaryBouncerShowing || altBouncerShowing
74                 (interactive || trustModel.flags.temporaryAndRenewable()) &&
75                     (bouncerShowing || trustModel.flags.dismissKeyguardRequested())
76             }
77             .map {} // map to Unit
78 
79     /*
80      * Updates when the current user successfully has authenticated via primary authentication
81      * (pin/pattern/password).
82      */
83     private val primaryAuthenticated: Flow<Unit> =
84         primaryBouncerInteractor.keyguardAuthenticatedPrimaryAuth
85             .filter { authedUserId -> authedUserId == selectedUserInteractor.getSelectedUserId() }
86             .map {} // map to Unit
87 
88     /*
89      * Updates when the current user requests the bouncer after they've already successfully
90      * authenticated (ie: from non-bypass face auth, from a trust agent that didn't immediately
91      * dismiss the keyguard, or if keyguard security is set to SWIPE or NONE).
92      */
93     private val userRequestedBouncerWhenAlreadyAuthenticated: Flow<Unit> =
94         primaryBouncerInteractor.userRequestedBouncerWhenAlreadyAuthenticated
95             .filter { authedUserId -> authedUserId == selectedUserInteractor.getSelectedUserId() }
96             .map {} // map to Unit
97 
98     /** Updates when keyguardDone should be requested. */
99     val keyguardDone: Flow<KeyguardDone> = keyguardRepository.keyguardDone
100 
101     /** Updates when any request to dismiss the current user's keyguard has arrived. */
102     private val dismissKeyguardRequest: Flow<DismissAction> =
103         merge(
104                 biometricAuthenticatedRequestDismissKeyguard,
105                 onTrustGrantedRequestDismissKeyguard,
106                 primaryAuthenticated,
107                 userRequestedBouncerWhenAlreadyAuthenticated,
108             )
109             .sample(keyguardRepository.dismissAction)
110 
111     /**
112      * Updates when a request to dismiss the current user's keyguard has arrived and there's a
113      * dismiss action to run immediately. It's expected that the consumer will request keyguardDone
114      * with or without a deferral.
115      */
116     val dismissKeyguardRequestWithImmediateDismissAction: Flow<Unit> =
117         dismissKeyguardRequest.filter { it is DismissAction.RunImmediately }.map {} // map to Unit
118 
119     /**
120      * Updates when a request to dismiss the current user's keyguard has arrived and there's isn't a
121      * dismiss action to run immediately. There may still be a dismiss action to run after the
122      * keyguard transitions to GONE.
123      */
124     val dismissKeyguardRequestWithoutImmediateDismissAction: Flow<Unit> =
125         dismissKeyguardRequest.filter { it !is DismissAction.RunImmediately }.map {} // map to Unit
126 
127     suspend fun setKeyguardDone(keyguardDoneTiming: KeyguardDone) {
128         keyguardRepository.setKeyguardDone(keyguardDoneTiming)
129     }
130 }
131