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