• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2024 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 android.annotation.SuppressLint
20 import com.android.systemui.dagger.SysUISingleton
21 import com.android.systemui.dagger.qualifiers.Background
22 import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
23 import com.android.systemui.util.kotlin.sample
24 import javax.inject.Inject
25 import kotlinx.coroutines.CoroutineScope
26 import kotlinx.coroutines.flow.Flow
27 import kotlinx.coroutines.flow.MutableSharedFlow
28 import kotlinx.coroutines.flow.distinctUntilChanged
29 import kotlinx.coroutines.flow.filter
30 import kotlinx.coroutines.flow.map
31 import kotlinx.coroutines.flow.merge
32 import kotlinx.coroutines.launch
33 
34 /** The reason we're showing lockscreen while awake, used for logging. */
35 enum class ShowWhileAwakeReason(private val logReason: String) {
36     FOLDED_WITH_SWIPE_UP_TO_CONTINUE(
37         "Folded with continue using apps on fold set to 'swipe up to continue'."
38     ),
39     LOCKDOWN("Lockdown initiated."),
40     KEYGUARD_REENABLED(
41         "Keyguard was re-enabled. We weren't unlocked when it was disabled, " +
42             "so we're returning to the lockscreen."
43     ),
44     KEYGUARD_TIMEOUT_WHILE_SCREEN_ON(
45         "Timed out while the screen was kept on, or WM#lockNow() was called."
46     ),
47     SWITCHED_TO_SECURE_USER_WHILE_GOING_AWAY(
48         "User switch to secure user occurred during keyguardGoingAway sequence, so we're locking."
49     );
50 
51     override fun toString(): String {
52         return logReason
53     }
54 }
55 
56 /**
57  * Logic around cases where the we show the lockscreen while still awake (transition from GONE ->
58  * LOCKSCREEN), vs. the more common cases of a power button press or screen timeout, which result in
59  * the device going to sleep.
60  *
61  * This does not necessarily mean we lock the device (which does not happen if showing the
62  * lockscreen is triggered by [KeyguardService.showDismissibleKeyguard]). We'll show keyguard here
63  * and authentication logic will decide if that keyguard is dismissible or not.
64  *
65  * This is possible in the following situations:
66  * - The user initiates lockdown from the power menu.
67  * - Theft detection, etc. has requested lockdown.
68  * - The keyguard was disabled while visible, and has now been re-enabled, so it's re-showing.
69  * - Someone called WM#lockNow().
70  * - The screen timed out, but an activity with FLAG_ALLOW_LOCK_WHILE_SCREEN_ON is on top.
71  * - A foldable is folded with "Continue using apps on fold" set to "Swipe up to continue" (if set
72  *   to "never", then lockscreen will be shown when the device goes to sleep, which is not tnohe
73  *   concern of this interactor).
74  */
75 @SysUISingleton
76 class KeyguardShowWhileAwakeInteractor
77 @Inject
78 constructor(
79     @Background val backgroundScope: CoroutineScope,
80     biometricSettingsRepository: BiometricSettingsRepository,
81     keyguardEnabledInteractor: KeyguardEnabledInteractor,
82     keyguardServiceShowLockscreenInteractor: KeyguardServiceShowLockscreenInteractor,
83 ) {
84 
85     /** Emits whenever the current user is in lockdown mode. */
86     private val inLockdown: Flow<ShowWhileAwakeReason> =
87         biometricSettingsRepository.isCurrentUserInLockdown
88             .distinctUntilChanged()
inLockdownnull89             .filter { inLockdown -> inLockdown }
<lambda>null90             .map { ShowWhileAwakeReason.LOCKDOWN }
91 
92     /**
93      * Emits whenever the keyguard is re-enabled, and we need to return to lockscreen due to the
94      * device being locked when the keyguard was originally disabled.
95      */
96     private val keyguardReenabled: Flow<ShowWhileAwakeReason> =
97         keyguardEnabledInteractor.isKeyguardEnabled
enablednull98             .filter { enabled -> enabled }
99             .sample(keyguardEnabledInteractor.showKeyguardWhenReenabled)
reshownull100             .filter { reshow -> reshow }
<lambda>null101             .map { ShowWhileAwakeReason.KEYGUARD_REENABLED }
102 
103     /**
104      * Emits whenever a user switch to a secure user occurs during keyguard going away.
105      *
106      * This is an event flow, hence the SharedFlow.
107      */
108     @SuppressLint("SharedFlowCreation")
109     val switchedToSecureUserDuringGoingAway: MutableSharedFlow<ShowWhileAwakeReason> =
110         MutableSharedFlow()
111 
112     /** Emits whenever we should show lockscreen while the screen is on, for any reason. */
113     val showWhileAwakeEvents: Flow<ShowWhileAwakeReason> =
114         merge(
115             // We're in lockdown, and the keyguard is enabled. If the keyguard is disabled, the
116             // lockdown button is hidden in the UI, but it's still possible to trigger lockdown in
117             // tests.
118             inLockdown
<lambda>null119                 .filter { keyguardEnabledInteractor.isKeyguardEnabledAndNotSuppressed() }
<lambda>null120                 .map { ShowWhileAwakeReason.LOCKDOWN },
121             // The keyguard was re-enabled, and it was showing when it was originally disabled.
122             // Tests currently expect that if the keyguard is re-enabled, it will show even if it's
123             // suppressed, so we don't check for isKeyguardEnabledAndNotSuppressed() on this flow.
<lambda>null124             keyguardReenabled.map { ShowWhileAwakeReason.KEYGUARD_REENABLED },
125             // KeyguardService says we need to show now, and the lockscreen is enabled.
<lambda>null126             keyguardServiceShowLockscreenInteractor.showNowEvents.filter {
127                 keyguardEnabledInteractor.isKeyguardEnabledAndNotSuppressed()
128             },
129             switchedToSecureUserDuringGoingAway,
130         )
131 
132     /** A user switch to a secure user occurred while we were going away. We need to re-lock. */
onSwitchedToSecureUserWhileKeyguardGoingAwaynull133     fun onSwitchedToSecureUserWhileKeyguardGoingAway() {
134         backgroundScope.launch {
135             switchedToSecureUserDuringGoingAway.emit(
136                 ShowWhileAwakeReason.SWITCHED_TO_SECURE_USER_WHILE_GOING_AWAY
137             )
138         }
139     }
140 }
141