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