• 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.app.trust.TrustManager
20 import android.os.DeadObjectException
21 import android.os.RemoteException
22 import com.android.internal.policy.IKeyguardStateCallback
23 import com.android.systemui.CoreStartable
24 import com.android.systemui.bouncer.domain.interactor.SimBouncerInteractor
25 import com.android.systemui.dagger.SysUISingleton
26 import com.android.systemui.dagger.qualifiers.Application
27 import com.android.systemui.dagger.qualifiers.Background
28 import com.android.systemui.keyguard.DismissCallbackRegistry
29 import com.android.systemui.keyguard.KeyguardWmStateRefactor
30 import com.android.systemui.keyguard.shared.model.KeyguardState
31 import com.android.systemui.scene.shared.flag.SceneContainerFlag
32 import com.android.systemui.user.domain.interactor.SelectedUserInteractor
33 import javax.inject.Inject
34 import kotlinx.coroutines.CoroutineDispatcher
35 import kotlinx.coroutines.CoroutineScope
36 import kotlinx.coroutines.flow.collectLatest
37 import com.android.app.tracing.coroutines.launchTraced as launch
38 import kotlinx.coroutines.withContext
39 
40 /**
41  * Updates KeyguardStateCallbacks provided to KeyguardService with KeyguardTransitionInteractor
42  * state.
43  *
44  * This borrows heavily from [KeyguardStateCallbackStartable], which requires Flexiglass. This class
45  * can be removed after Flexiglass launches.
46  */
47 @SysUISingleton
48 class KeyguardStateCallbackInteractor
49 @Inject
50 constructor(
51     @Application private val applicationScope: CoroutineScope,
52     @Background private val backgroundDispatcher: CoroutineDispatcher,
53     private val selectedUserInteractor: SelectedUserInteractor,
54     private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
55     private val trustInteractor: TrustInteractor,
56     private val simBouncerInteractor: SimBouncerInteractor,
57     private val dismissCallbackRegistry: DismissCallbackRegistry,
58     private val wmLockscreenVisibilityInteractor: WindowManagerLockscreenVisibilityInteractor,
59     private val trustManager: TrustManager,
60 ) : CoreStartable {
61     private val callbacks = mutableListOf<IKeyguardStateCallback>()
62 
63     override fun start() {
64         if (!KeyguardWmStateRefactor.isEnabled || SceneContainerFlag.isEnabled) {
65             return
66         }
67 
68         applicationScope.launch {
69             wmLockscreenVisibilityInteractor.lockscreenVisibility.collectLatest { visible ->
70                 val iterator = callbacks.iterator()
71                 withContext(backgroundDispatcher) {
72                     while (iterator.hasNext()) {
73                         val callback = iterator.next()
74                         try {
75                             callback.onShowingStateChanged(
76                                 visible,
77                                 selectedUserInteractor.getSelectedUserId(),
78                             )
79                             callback.onInputRestrictedStateChanged(visible)
80 
81                             trustManager.reportKeyguardShowingChanged()
82 
83                             if (!visible) {
84                                 dismissCallbackRegistry.notifyDismissSucceeded()
85                             }
86                         } catch (e: RemoteException) {
87                             if (e is DeadObjectException) {
88                                 iterator.remove()
89                             }
90                         }
91                     }
92                 }
93             }
94         }
95 
96         applicationScope.launch {
97             trustInteractor.isTrusted.collectLatest { isTrusted ->
98                 val iterator = callbacks.iterator()
99                 withContext(backgroundDispatcher) {
100                     while (iterator.hasNext()) {
101                         val callback = iterator.next()
102                         try {
103                             callback.onTrustedChanged(isTrusted)
104                         } catch (e: RemoteException) {
105                             if (e is DeadObjectException) {
106                                 iterator.remove()
107                             }
108                         }
109                     }
110                 }
111             }
112         }
113 
114         applicationScope.launch {
115             simBouncerInteractor.isAnySimSecure.collectLatest { isSimSecured ->
116                 val iterator = callbacks.iterator()
117                 withContext(backgroundDispatcher) {
118                     while (iterator.hasNext()) {
119                         val callback = iterator.next()
120                         try {
121                             callback.onSimSecureStateChanged(isSimSecured)
122                         } catch (e: RemoteException) {
123                             if (e is DeadObjectException) {
124                                 iterator.remove()
125                             }
126                         }
127                     }
128                 }
129             }
130         }
131     }
132 
133     fun addCallback(callback: IKeyguardStateCallback) {
134         KeyguardWmStateRefactor.isUnexpectedlyInLegacyMode()
135         callbacks.add(callback)
136 
137         // Send initial values to new callbacks.
138         callback.onShowingStateChanged(!isIdleInGone(), selectedUserInteractor.getSelectedUserId())
139         callback.onInputRestrictedStateChanged(!isIdleInGone())
140         callback.onTrustedChanged(trustInteractor.isTrusted.value)
141         callback.onSimSecureStateChanged(simBouncerInteractor.isAnySimSecure.value)
142     }
143 
144     /** Whether we're in KeyguardState.GONE and haven't started a transition to another state. */
145     private fun isIdleInGone(): Boolean {
146         return keyguardTransitionInteractor.getCurrentState() == KeyguardState.GONE &&
147             keyguardTransitionInteractor.getStartedState() == KeyguardState.GONE
148     }
149 }
150