summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt2
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/TrustRepositoryTest.kt19
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt2
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt2
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneBackInteractorTest.kt1
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/KeyguardStateCallbackStartableTest.kt248
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/SimBouncerInteractor.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/repository/TrustRepository.kt28
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/TrustInteractor.kt18
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/domain/startable/KeyguardStateCallbackStartable.kt170
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlag.kt11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/composable/BouncerContentTest.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeTrustRepository.kt12
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/TrustInteractorKosmos.kt8
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/KeyguardStateCallbackStartableKosmos.kt39
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt (renamed from packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneContainerStartableKosmos.kt)6
22 files changed, 587 insertions, 23 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt
index a5acf724dcff..ccddc9c7120f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt
@@ -38,7 +38,7 @@ import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.flags.Flags
import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.kosmos.testScope
-import com.android.systemui.scene.domain.interactor.sceneContainerStartable
+import com.android.systemui.scene.domain.startable.sceneContainerStartable
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.shared.model.fakeSceneDataSource
import com.android.systemui.testKosmos
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/TrustRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/TrustRepositoryTest.kt
index 5f0f24dcca86..2d121502650e 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/TrustRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/TrustRepositoryTest.kt
@@ -30,6 +30,7 @@ import com.android.systemui.user.data.repository.FakeUserRepository
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
@@ -61,7 +62,8 @@ class TrustRepositoryTest : SysuiTestCase() {
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
- testScope = TestScope()
+ val testDispatcher = StandardTestDispatcher()
+ testScope = TestScope(testDispatcher)
userRepository = FakeUserRepository()
userRepository.setUserInfos(users)
val logger =
@@ -69,7 +71,13 @@ class TrustRepositoryTest : SysuiTestCase() {
LogBuffer("TestBuffer", 1, mock(LogcatEchoTracker::class.java), false)
)
underTest =
- TrustRepositoryImpl(testScope.backgroundScope, userRepository, trustManager, logger)
+ TrustRepositoryImpl(
+ testScope.backgroundScope,
+ testDispatcher,
+ userRepository,
+ trustManager,
+ logger,
+ )
}
fun TestScope.init() {
@@ -275,4 +283,11 @@ class TrustRepositoryTest : SysuiTestCase() {
userRepository.setSelectedUserInfo(users[1])
assertThat(trustUsuallyManaged).isFalse()
}
+
+ @Test
+ fun reportKeyguardShowingChanged() =
+ testScope.runTest {
+ underTest.reportKeyguardShowingChanged()
+ verify(trustManager).reportKeyguardShowingChanged()
+ }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
index 5b6fea5a52f0..d43d50ab0dc4 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
@@ -42,9 +42,9 @@ import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
import com.android.systemui.qs.ui.adapter.FakeQSSceneAdapter
import com.android.systemui.res.R
import com.android.systemui.scene.domain.interactor.sceneBackInteractor
-import com.android.systemui.scene.domain.interactor.sceneContainerStartable
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.domain.resolver.homeSceneFamilyResolver
+import com.android.systemui.scene.domain.startable.sceneContainerStartable
import com.android.systemui.scene.shared.model.SceneFamilies
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.settings.brightness.ui.viewmodel.brightnessMirrorViewModel
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
index 4d5d22c11f71..412505d50fc9 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
@@ -58,9 +58,9 @@ import com.android.systemui.power.domain.interactor.powerInteractor
import com.android.systemui.qs.footerActionsController
import com.android.systemui.qs.footerActionsViewModelFactory
import com.android.systemui.qs.ui.adapter.FakeQSSceneAdapter
-import com.android.systemui.scene.domain.interactor.sceneContainerStartable
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.domain.resolver.homeSceneFamilyResolver
+import com.android.systemui.scene.domain.startable.sceneContainerStartable
import com.android.systemui.scene.shared.model.SceneFamilies
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.shared.model.fakeSceneDataSource
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneBackInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneBackInteractorTest.kt
index e3108ad1b8f1..1f3454de14d7 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneBackInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneBackInteractorTest.kt
@@ -28,6 +28,7 @@ import com.android.systemui.authentication.domain.interactor.authenticationInter
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.kosmos.testScope
+import com.android.systemui.scene.domain.startable.sceneContainerStartable
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/KeyguardStateCallbackStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/KeyguardStateCallbackStartableTest.kt
new file mode 100644
index 000000000000..695edafefdf3
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/KeyguardStateCallbackStartableTest.kt
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.scene.domain.startable
+
+import android.content.pm.UserInfo
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.compose.animation.scene.ObservableTransitionState
+import com.android.internal.policy.IKeyguardStateCallback
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.flags.EnableSceneContainer
+import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
+import com.android.systemui.keyguard.data.repository.fakeTrustRepository
+import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.scene.data.repository.setSceneTransition
+import com.android.systemui.scene.domain.interactor.sceneInteractor
+import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
+import com.android.systemui.testKosmos
+import com.android.systemui.user.data.repository.fakeUserRepository
+import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.Truth.assertWithMessage
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.kotlin.argumentCaptor
+import org.mockito.kotlin.atLeastOnce
+import org.mockito.kotlin.eq
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.verify
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+@EnableSceneContainer
+class KeyguardStateCallbackStartableTest : SysuiTestCase() {
+
+ private val kosmos = testKosmos()
+ private val testScope = kosmos.testScope
+
+ private val underTest = kosmos.keyguardStateCallbackStartable
+
+ @Test
+ fun addCallback_hydratesAllWithCurrentState() =
+ testScope.runTest {
+ val testState = setUpTest()
+ val callback = mockCallback()
+
+ underTest.addCallback(callback)
+ runCurrent()
+
+ with(testState) {
+ val captor = argumentCaptor<Boolean>()
+ verify(callback, atLeastOnce()).onShowingStateChanged(captor.capture(), eq(userId))
+ assertThat(captor.lastValue).isEqualTo(isKeyguardShowing)
+ verify(callback, atLeastOnce()).onInputRestrictedStateChanged(captor.capture())
+ assertThat(captor.lastValue).isEqualTo(isInputRestricted)
+ verify(callback, atLeastOnce()).onSimSecureStateChanged(captor.capture())
+ assertThat(captor.lastValue).isEqualTo(isSimSecure)
+ verify(callback, atLeastOnce()).onTrustedChanged(captor.capture())
+ assertThat(captor.lastValue).isEqualTo(isTrusted)
+ }
+ }
+
+ @Test
+ fun hydrateKeyguardShowingState() =
+ testScope.runTest {
+ setUpTest(isKeyguardShowing = true)
+ val callback = mockCallback()
+ underTest.addCallback(callback)
+ runCurrent()
+ verify(callback, atLeastOnce()).onShowingStateChanged(eq(true), anyInt())
+
+ unlockDevice()
+ runCurrent()
+
+ verify(callback).onShowingStateChanged(eq(false), anyInt())
+ }
+
+ @Test
+ fun hydrateInputRestrictedState() =
+ testScope.runTest {
+ setUpTest(isKeyguardShowing = true)
+ val callback = mockCallback()
+ underTest.addCallback(callback)
+ runCurrent()
+ val captor = argumentCaptor<Boolean>()
+ verify(callback, atLeastOnce()).onInputRestrictedStateChanged(captor.capture())
+ assertThat(captor.lastValue).isTrue()
+
+ unlockDevice()
+ runCurrent()
+
+ verify(callback, atLeastOnce()).onInputRestrictedStateChanged(captor.capture())
+ assertThat(captor.lastValue).isFalse()
+ }
+
+ @Test
+ fun hydrateSimSecureState() =
+ testScope.runTest {
+ setUpTest(isSimSecure = false)
+ val callback = mockCallback()
+ underTest.addCallback(callback)
+ runCurrent()
+ val captor = argumentCaptor<Boolean>()
+ verify(callback, atLeastOnce()).onSimSecureStateChanged(captor.capture())
+ assertThat(captor.lastValue).isFalse()
+
+ kosmos.fakeMobileConnectionsRepository.isAnySimSecure.value = true
+ runCurrent()
+
+ verify(callback, atLeastOnce()).onSimSecureStateChanged(captor.capture())
+ assertThat(captor.lastValue).isTrue()
+ }
+
+ @Test
+ fun notifyWhenKeyguardShowingChanged() =
+ testScope.runTest {
+ setUpTest(isKeyguardShowing = true)
+ val callback = mockCallback()
+ underTest.addCallback(callback)
+ runCurrent()
+ assertThat(kosmos.fakeTrustRepository.keyguardShowingChangeEventCount).isEqualTo(1)
+
+ unlockDevice()
+ runCurrent()
+
+ assertThat(kosmos.fakeTrustRepository.keyguardShowingChangeEventCount).isEqualTo(2)
+ }
+
+ @Test
+ fun notifyWhenTrustChanged() =
+ testScope.runTest {
+ setUpTest(isTrusted = false)
+ val callback = mockCallback()
+ underTest.addCallback(callback)
+ runCurrent()
+ val captor = argumentCaptor<Boolean>()
+ verify(callback, atLeastOnce()).onTrustedChanged(captor.capture())
+ assertThat(captor.lastValue).isFalse()
+
+ kosmos.fakeTrustRepository.setCurrentUserTrusted(true)
+ runCurrent()
+
+ verify(callback, atLeastOnce()).onTrustedChanged(captor.capture())
+ assertThat(captor.lastValue).isTrue()
+ }
+
+ private suspend fun TestScope.setUpTest(
+ isKeyguardShowing: Boolean = true,
+ userId: Int = selectedUser.id,
+ isInputRestricted: Boolean = true,
+ isSimSecure: Boolean = false,
+ isTrusted: Boolean = false,
+ ): TestState {
+ val testState =
+ TestState(
+ isKeyguardShowing = isKeyguardShowing,
+ userId = userId,
+ isInputRestricted = isInputRestricted,
+ isSimSecure = isSimSecure,
+ isTrusted = isTrusted,
+ )
+
+ if (isKeyguardShowing) {
+ lockDevice()
+ } else {
+ unlockDevice()
+ }
+
+ kosmos.fakeUserRepository.setUserInfos(listOf(selectedUser))
+ kosmos.fakeUserRepository.setSelectedUserInfo(selectedUser)
+
+ if (isInputRestricted && !isKeyguardShowing) {
+ // TODO(b/348644111): add support for mNeedToReshowWhenReenabled
+ } else if (!isInputRestricted) {
+ assertWithMessage(
+ "If isInputRestricted is false, isKeyguardShowing must also be false!"
+ )
+ .that(isKeyguardShowing)
+ .isFalse()
+ }
+
+ kosmos.fakeMobileConnectionsRepository.isAnySimSecure.value = isSimSecure
+
+ kosmos.fakeTrustRepository.setCurrentUserTrusted(isTrusted)
+
+ runCurrent()
+
+ underTest.start()
+
+ return testState
+ }
+
+ private fun lockDevice() {
+ kosmos.setSceneTransition(ObservableTransitionState.Idle(Scenes.Lockscreen))
+ kosmos.sceneInteractor.changeScene(Scenes.Lockscreen, "")
+ }
+
+ private fun unlockDevice() {
+ kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
+ SuccessFingerprintAuthenticationStatus(0, true)
+ )
+ kosmos.setSceneTransition(ObservableTransitionState.Idle(Scenes.Gone))
+ kosmos.sceneInteractor.changeScene(Scenes.Gone, "")
+ }
+
+ private fun mockCallback(): IKeyguardStateCallback {
+ return mock()
+ }
+
+ private data class TestState(
+ val isKeyguardShowing: Boolean,
+ val userId: Int,
+ val isInputRestricted: Boolean,
+ val isSimSecure: Boolean,
+ val isTrusted: Boolean,
+ )
+
+ companion object {
+ private val selectedUser =
+ UserInfo(
+ /* id= */ 100,
+ /* name= */ "First user",
+ /* flags= */ 0,
+ )
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
index e40c8eecca0f..9edc3af6bb4e 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
@@ -51,7 +51,6 @@ import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.se
import com.android.systemui.power.domain.interactor.powerInteractor
import com.android.systemui.power.shared.model.WakeSleepReason
import com.android.systemui.power.shared.model.WakefulnessState
-import com.android.systemui.scene.domain.interactor.sceneContainerStartable
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.shared.model.fakeSceneDataSource
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/SimBouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/SimBouncerInteractor.kt
index 7d3075a9dd74..ed931bd4e66a 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/SimBouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/SimBouncerInteractor.kt
@@ -43,10 +43,11 @@ import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay
-import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
+import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@@ -68,7 +69,12 @@ constructor(
mobileConnectionsRepository: MobileConnectionsRepository,
) {
val subId: StateFlow<Int> = repository.subscriptionId
- val isAnySimSecure: Flow<Boolean> = mobileConnectionsRepository.isAnySimSecure
+ val isAnySimSecure: StateFlow<Boolean> =
+ mobileConnectionsRepository.isAnySimSecure.stateIn(
+ scope = applicationScope,
+ started = SharingStarted.WhileSubscribed(),
+ initialValue = mobileConnectionsRepository.getIsAnySimSecure(),
+ )
val isLockedEsim: StateFlow<Boolean?> = repository.isLockedEsim
val errorDialogMessage: StateFlow<String?> = repository.errorDialogMessage
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 209bc7adac33..c4b70d8013bf 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -89,6 +89,7 @@ import com.android.systemui.keyguard.ui.viewmodel.WindowManagerLockscreenVisibil
import com.android.systemui.power.domain.interactor.PowerInteractor;
import com.android.systemui.power.shared.model.ScreenPowerState;
import com.android.systemui.scene.domain.interactor.SceneInteractor;
+import com.android.systemui.scene.domain.startable.KeyguardStateCallbackStartable;
import com.android.systemui.scene.shared.flag.SceneContainerFlag;
import com.android.systemui.scene.shared.model.Scenes;
import com.android.systemui.settings.DisplayTracker;
@@ -122,6 +123,7 @@ public class KeyguardService extends Service {
private final KeyguardInteractor mKeyguardInteractor;
private final Lazy<SceneInteractor> mSceneInteractorLazy;
private final Executor mMainExecutor;
+ private final Lazy<KeyguardStateCallbackStartable> mKeyguardStateCallbackStartableLazy;
private static RemoteAnimationTarget[] wrap(TransitionInfo info, boolean wallpapers,
SurfaceControl.Transaction t, ArrayMap<SurfaceControl, SurfaceControl> leashMap,
@@ -341,7 +343,8 @@ public class KeyguardService extends Service {
Lazy<SceneInteractor> sceneInteractorLazy,
@Main Executor mainExecutor,
KeyguardInteractor keyguardInteractor,
- KeyguardEnabledInteractor keyguardEnabledInteractor) {
+ KeyguardEnabledInteractor keyguardEnabledInteractor,
+ Lazy<KeyguardStateCallbackStartable> keyguardStateCallbackStartableLazy) {
super();
mKeyguardViewMediator = keyguardViewMediator;
mKeyguardLifecyclesDispatcher = keyguardLifecyclesDispatcher;
@@ -353,6 +356,7 @@ public class KeyguardService extends Service {
mKeyguardInteractor = keyguardInteractor;
mSceneInteractorLazy = sceneInteractorLazy;
mMainExecutor = mainExecutor;
+ mKeyguardStateCallbackStartableLazy = keyguardStateCallbackStartableLazy;
if (KeyguardWmStateRefactor.isEnabled()) {
WindowManagerLockscreenVisibilityViewBinder.bind(
@@ -440,7 +444,11 @@ public class KeyguardService extends Service {
public void addStateMonitorCallback(IKeyguardStateCallback callback) {
trace("addStateMonitorCallback");
checkPermission();
- mKeyguardViewMediator.addStateMonitorCallback(callback);
+ if (SceneContainerFlag.isEnabled()) {
+ mKeyguardStateCallbackStartableLazy.get().addCallback(callback);
+ } else {
+ mKeyguardViewMediator.addStateMonitorCallback(callback);
+ }
}
@Override // Binder interface
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index b70dbe240ce0..36b7ed26158f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -3801,6 +3801,10 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
}
private void notifyDefaultDisplayCallbacks(boolean showing) {
+ if (SceneContainerFlag.isEnabled()) {
+ return;
+ }
+
// TODO(b/140053364)
whitelistIpcs(() -> {
int size = mKeyguardStateCallbacks.size();
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/TrustRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/TrustRepository.kt
index 6522439460e4..bd5d096b4f6a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/TrustRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/TrustRepository.kt
@@ -23,11 +23,13 @@ import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLoggin
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.keyguard.shared.model.ActiveUnlockModel
import com.android.systemui.keyguard.shared.model.TrustManagedModel
import com.android.systemui.keyguard.shared.model.TrustModel
import com.android.systemui.user.data.repository.UserRepository
import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
@@ -44,6 +46,7 @@ import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.flow.stateIn
+import kotlinx.coroutines.withContext
/** Encapsulates any state relevant to trust agents and trust grants. */
interface TrustRepository {
@@ -51,7 +54,7 @@ interface TrustRepository {
val isCurrentUserTrustUsuallyManaged: StateFlow<Boolean>
/** Flow representing whether the current user is trusted. */
- val isCurrentUserTrusted: Flow<Boolean>
+ val isCurrentUserTrusted: StateFlow<Boolean>
/** Flow representing whether active unlock is running for the current user. */
val isCurrentUserActiveUnlockRunning: Flow<Boolean>
@@ -63,6 +66,9 @@ interface TrustRepository {
/** A trust agent is requesting to dismiss the keyguard from a trust change. */
val trustAgentRequestingToDismissKeyguard: Flow<TrustModel>
+
+ /** Reports a keyguard visibility change. */
+ suspend fun reportKeyguardShowingChanged()
}
@OptIn(ExperimentalCoroutinesApi::class)
@@ -71,6 +77,7 @@ class TrustRepositoryImpl
@Inject
constructor(
@Application private val applicationScope: CoroutineScope,
+ @Background private val backgroundDispatcher: CoroutineDispatcher,
private val userRepository: UserRepository,
private val trustManager: TrustManager,
private val logger: TrustRepositoryLogger,
@@ -191,11 +198,26 @@ constructor(
private fun isUserTrustManaged(userId: Int) =
trustManagedForUser[userId]?.isTrustManaged ?: false
- override val isCurrentUserTrusted: Flow<Boolean>
+ override val isCurrentUserTrusted: StateFlow<Boolean>
get() =
combine(trust, userRepository.selectedUserInfo, ::Pair)
- .map { latestTrustModelForUser[it.second.id]?.isTrusted ?: false }
+ .map { isCurrentUserTrusted(it.second.id) }
.distinctUntilChanged()
.onEach { logger.isCurrentUserTrusted(it) }
.onStart { emit(false) }
+ .stateIn(
+ scope = applicationScope,
+ started = SharingStarted.WhileSubscribed(),
+ initialValue = isCurrentUserTrusted(),
+ )
+
+ private fun isCurrentUserTrusted(
+ selectedUserId: Int = userRepository.getSelectedUserInfo().id
+ ): Boolean {
+ return latestTrustModelForUser[selectedUserId]?.isTrusted ?: false
+ }
+
+ override suspend fun reportKeyguardShowingChanged() {
+ withContext(backgroundDispatcher) { trustManager.reportKeyguardShowingChanged() }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/TrustInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/TrustInteractor.kt
index 2ff6e165293b..73248bbec6ca 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/TrustInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/TrustInteractor.kt
@@ -17,14 +17,21 @@
package com.android.systemui.keyguard.domain.interactor
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.data.repository.TrustRepository
import javax.inject.Inject
-import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.launch
/** Encapsulates any state relevant to trust agents and trust grants. */
@SysUISingleton
-class TrustInteractor @Inject constructor(repository: TrustRepository) {
+class TrustInteractor
+@Inject
+constructor(
+ @Application private val applicationScope: CoroutineScope,
+ private val repository: TrustRepository,
+) {
/**
* Whether the current user has a trust agent enabled. This is true if the user has at least one
* trust agent enabled in settings.
@@ -39,5 +46,10 @@ class TrustInteractor @Inject constructor(repository: TrustRepository) {
val isTrustAgentCurrentlyAllowed: StateFlow<Boolean> = repository.isCurrentUserTrustManaged
/** Whether the current user is trusted by any of the enabled trust agents. */
- val isTrusted: Flow<Boolean> = repository.isCurrentUserTrusted
+ val isTrusted: StateFlow<Boolean> = repository.isCurrentUserTrusted
+
+ /** Reports a keyguard visibility change. */
+ fun reportKeyguardShowingChanged() {
+ applicationScope.launch { repository.reportKeyguardShowingChanged() }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
index 08462d79b2fb..6e8997346fc4 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
@@ -23,6 +23,7 @@ import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInte
import com.android.systemui.scene.domain.resolver.HomeSceneFamilyResolverModule
import com.android.systemui.scene.domain.resolver.NotifShadeSceneFamilyResolverModule
import com.android.systemui.scene.domain.resolver.QuickSettingsSceneFamilyResolverModule
+import com.android.systemui.scene.domain.startable.KeyguardStateCallbackStartable
import com.android.systemui.scene.domain.startable.SceneContainerStartable
import com.android.systemui.scene.domain.startable.ScrimStartable
import com.android.systemui.scene.domain.startable.StatusBarStartable
@@ -72,6 +73,11 @@ interface KeyguardlessSceneContainerFrameworkModule {
@Binds
@IntoMap
+ @ClassKey(KeyguardStateCallbackStartable::class)
+ fun keyguardStateCallbackStartable(impl: KeyguardStateCallbackStartable): CoreStartable
+
+ @Binds
+ @IntoMap
@ClassKey(WindowRootViewVisibilityInteractor::class)
fun bindWindowRootViewVisibilityInteractor(
impl: WindowRootViewVisibilityInteractor
diff --git a/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt
index 17dc9a52f9b7..7d63b4ce0044 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt
@@ -24,6 +24,7 @@ import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInte
import com.android.systemui.scene.domain.resolver.HomeSceneFamilyResolverModule
import com.android.systemui.scene.domain.resolver.NotifShadeSceneFamilyResolverModule
import com.android.systemui.scene.domain.resolver.QuickSettingsSceneFamilyResolverModule
+import com.android.systemui.scene.domain.startable.KeyguardStateCallbackStartable
import com.android.systemui.scene.domain.startable.SceneContainerStartable
import com.android.systemui.scene.domain.startable.ScrimStartable
import com.android.systemui.scene.domain.startable.StatusBarStartable
@@ -78,6 +79,11 @@ interface SceneContainerFrameworkModule {
@Binds
@IntoMap
+ @ClassKey(KeyguardStateCallbackStartable::class)
+ fun keyguardStateCallbackStartable(impl: KeyguardStateCallbackStartable): CoreStartable
+
+ @Binds
+ @IntoMap
@ClassKey(WindowRootViewVisibilityInteractor::class)
fun bindWindowRootViewVisibilityInteractor(
impl: WindowRootViewVisibilityInteractor
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/KeyguardStateCallbackStartable.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/KeyguardStateCallbackStartable.kt
new file mode 100644
index 000000000000..6d1c1a7b5bfe
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/KeyguardStateCallbackStartable.kt
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.scene.domain.startable
+
+import android.os.DeadObjectException
+import android.os.RemoteException
+import com.android.internal.policy.IKeyguardStateCallback
+import com.android.systemui.CoreStartable
+import com.android.systemui.bouncer.domain.interactor.SimBouncerInteractor
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
+import com.android.systemui.keyguard.domain.interactor.TrustInteractor
+import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
+import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.user.domain.interactor.SelectedUserInteractor
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.collectLatest
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+/** Keeps all [IKeyguardStateCallback]s hydrated with the latest state. */
+@SysUISingleton
+class KeyguardStateCallbackStartable
+@Inject
+constructor(
+ @Application private val applicationScope: CoroutineScope,
+ @Background private val backgroundDispatcher: CoroutineDispatcher,
+ private val sceneInteractor: SceneInteractor,
+ private val selectedUserInteractor: SelectedUserInteractor,
+ private val deviceEntryInteractor: DeviceEntryInteractor,
+ private val simBouncerInteractor: SimBouncerInteractor,
+ private val trustInteractor: TrustInteractor,
+) : CoreStartable {
+
+ private val callbacks = mutableListOf<IKeyguardStateCallback>()
+
+ override fun start() {
+ if (!SceneContainerFlag.isEnabled) {
+ return
+ }
+
+ hydrateKeyguardShowingAndInputRestrictionStates()
+ hydrateSimSecureState()
+ notifyWhenKeyguardShowingChanged()
+ notifyWhenTrustChanged()
+ }
+
+ fun addCallback(callback: IKeyguardStateCallback) {
+ SceneContainerFlag.assertInNewMode()
+
+ callbacks.add(callback)
+
+ applicationScope.launch(backgroundDispatcher) {
+ callback.onShowingStateChanged(
+ !deviceEntryInteractor.isDeviceEntered.value,
+ selectedUserInteractor.getSelectedUserId(),
+ )
+ callback.onTrustedChanged(trustInteractor.isTrusted.value)
+ callback.onSimSecureStateChanged(simBouncerInteractor.isAnySimSecure.value)
+ // TODO(b/348644111): add support for mNeedToReshowWhenReenabled
+ callback.onInputRestrictedStateChanged(!deviceEntryInteractor.isDeviceEntered.value)
+ }
+ }
+
+ private fun hydrateKeyguardShowingAndInputRestrictionStates() {
+ applicationScope.launch {
+ combine(
+ selectedUserInteractor.selectedUser,
+ deviceEntryInteractor.isDeviceEntered,
+ ::Pair
+ )
+ .collectLatest { (selectedUserId, isDeviceEntered) ->
+ val iterator = callbacks.iterator()
+ withContext(backgroundDispatcher) {
+ while (iterator.hasNext()) {
+ val callback = iterator.next()
+ try {
+ callback.onShowingStateChanged(!isDeviceEntered, selectedUserId)
+ // TODO(b/348644111): add support for mNeedToReshowWhenReenabled
+ callback.onInputRestrictedStateChanged(!isDeviceEntered)
+ } catch (e: RemoteException) {
+ if (e is DeadObjectException) {
+ iterator.remove()
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private fun hydrateSimSecureState() {
+ applicationScope.launch {
+ simBouncerInteractor.isAnySimSecure.collectLatest { isSimSecured ->
+ val iterator = callbacks.iterator()
+ withContext(backgroundDispatcher) {
+ while (iterator.hasNext()) {
+ val callback = iterator.next()
+ try {
+ callback.onSimSecureStateChanged(isSimSecured)
+ } catch (e: RemoteException) {
+ if (e is DeadObjectException) {
+ iterator.remove()
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private fun notifyWhenKeyguardShowingChanged() {
+ applicationScope.launch {
+ // This is equivalent to isDeviceEntered but it waits for the full transition animation
+ // to finish before emitting a new value and not just for the current scene to be
+ // switched.
+ sceneInteractor.transitionState
+ .filter { it.isIdle(Scenes.Gone) || it.isIdle(Scenes.Lockscreen) }
+ .map { it.isIdle(Scenes.Lockscreen) }
+ .distinctUntilChanged()
+ .collectLatest { trustInteractor.reportKeyguardShowingChanged() }
+ }
+ }
+
+ private fun notifyWhenTrustChanged() {
+ applicationScope.launch {
+ trustInteractor.isTrusted.collectLatest { isTrusted ->
+ val iterator = callbacks.iterator()
+ withContext(backgroundDispatcher) {
+ while (iterator.hasNext()) {
+ val callback = iterator.next()
+ try {
+ callback.onTrustedChanged(isTrusted)
+ } catch (e: RemoteException) {
+ if (e is DeadObjectException) {
+ iterator.remove()
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
index 1e689bd11fa3..218853d7a1fb 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
@@ -22,6 +22,7 @@ import android.app.StatusBarManager
import com.android.compose.animation.scene.ObservableTransitionState
import com.android.compose.animation.scene.SceneKey
import com.android.internal.logging.UiEventLogger
+import com.android.internal.policy.IKeyguardStateCallback
import com.android.systemui.CoreStartable
import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
@@ -127,6 +128,8 @@ constructor(
private val centralSurfaces: CentralSurfaces?
get() = centralSurfacesOptLazy.get().getOrNull()
+ private val keyguardStateCallbacks = mutableListOf<IKeyguardStateCallback>()
+
override fun start() {
if (SceneContainerFlag.isEnabled) {
sceneLogger.logFrameworkEnabled(isEnabled = true)
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlag.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlag.kt
index cf33c4a3fafb..6c63c9762e5e 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlag.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlag.kt
@@ -39,13 +39,14 @@ object SceneContainerFlag {
inline val isEnabled
get() =
sceneContainer() && // mainAconfigFlag
- ComposeLockscreen.isEnabled &&
+ ComposeLockscreen.isEnabled &&
KeyguardBottomAreaRefactor.isEnabled &&
KeyguardWmStateRefactor.isEnabled &&
MigrateClocksToBlueprint.isEnabled &&
NotificationsHeadsUpRefactor.isEnabled &&
PredictiveBackSysUiFlag.isEnabled &&
DeviceEntryUdfpsRefactor.isEnabled
+
// NOTE: Changes should also be made in getSecondaryFlags and @EnableSceneContainer
/** The main aconfig flag. */
@@ -91,6 +92,14 @@ object SceneContainerFlag {
@JvmStatic
inline fun assertInLegacyMode() = RefactorFlagUtils.assertInLegacyMode(isEnabled, DESCRIPTION)
+ /**
+ * Called to ensure the new code is only run when the flag is enabled. This will throw an
+ * exception if the flag is disabled to ensure that the refactor author catches issues in
+ * testing.
+ */
+ @JvmStatic
+ inline fun assertInNewMode() = RefactorFlagUtils.assertInNewMode(isEnabled, DESCRIPTION)
+
/** Returns a developer-readable string that describes the current requirement list. */
@JvmStatic
fun requirementDescription(): String {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/composable/BouncerContentTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/composable/BouncerContentTest.kt
index d32d12c83a8d..a4936e63df8f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/composable/BouncerContentTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/composable/BouncerContentTest.kt
@@ -37,7 +37,7 @@ import com.android.systemui.bouncer.ui.viewmodel.bouncerViewModel
import com.android.systemui.flags.Flags
import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.motion.createSysUiComposeMotionTestRule
-import com.android.systemui.scene.domain.interactor.sceneContainerStartable
+import com.android.systemui.scene.domain.startable.sceneContainerStartable
import com.android.systemui.testKosmos
import org.junit.Before
import org.junit.Rule
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeTrustRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeTrustRepository.kt
index cd83c2fa480c..39a1a639ced9 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeTrustRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeTrustRepository.kt
@@ -33,9 +33,10 @@ class FakeTrustRepository @Inject constructor() : TrustRepository {
private val _isTrustUsuallyManaged = MutableStateFlow(false)
override val isCurrentUserTrustUsuallyManaged: StateFlow<Boolean>
get() = _isTrustUsuallyManaged
+
private val _isCurrentUserTrusted = MutableStateFlow(false)
- override val isCurrentUserTrusted: Flow<Boolean>
- get() = _isCurrentUserTrusted
+ override val isCurrentUserTrusted: StateFlow<Boolean>
+ get() = _isCurrentUserTrusted.asStateFlow()
private val _isCurrentUserActiveUnlockAvailable = MutableStateFlow(false)
override val isCurrentUserActiveUnlockRunning: StateFlow<Boolean> =
@@ -48,6 +49,13 @@ class FakeTrustRepository @Inject constructor() : TrustRepository {
private val _requestDismissKeyguard = MutableStateFlow(TrustModel(false, 0, TrustGrantFlags(0)))
override val trustAgentRequestingToDismissKeyguard: Flow<TrustModel> = _requestDismissKeyguard
+ var keyguardShowingChangeEventCount: Int = 0
+ private set
+
+ override suspend fun reportKeyguardShowingChanged() {
+ keyguardShowingChangeEventCount++
+ }
+
fun setCurrentUserTrusted(trust: Boolean) {
_isCurrentUserTrusted.value = trust
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/TrustInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/TrustInteractorKosmos.kt
index 0ebf1642478e..d60326c6c367 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/TrustInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/TrustInteractorKosmos.kt
@@ -19,5 +19,11 @@ package com.android.systemui.keyguard.domain.interactor
import com.android.systemui.keyguard.data.repository.trustRepository
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.kosmos.applicationCoroutineScope
-val Kosmos.trustInteractor by Fixture { TrustInteractor(repository = trustRepository) }
+val Kosmos.trustInteractor by Fixture {
+ TrustInteractor(
+ applicationScope = applicationCoroutineScope,
+ repository = trustRepository,
+ )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/KeyguardStateCallbackStartableKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/KeyguardStateCallbackStartableKosmos.kt
new file mode 100644
index 000000000000..f9111bfb3dcf
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/KeyguardStateCallbackStartableKosmos.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.scene.domain.startable
+
+import com.android.systemui.bouncer.domain.interactor.simBouncerInteractor
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
+import com.android.systemui.keyguard.domain.interactor.trustInteractor
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.kosmos.testDispatcher
+import com.android.systemui.scene.domain.interactor.sceneInteractor
+import com.android.systemui.user.domain.interactor.selectedUserInteractor
+
+val Kosmos.keyguardStateCallbackStartable by Fixture {
+ KeyguardStateCallbackStartable(
+ applicationScope = applicationCoroutineScope,
+ backgroundDispatcher = testDispatcher,
+ sceneInteractor = sceneInteractor,
+ selectedUserInteractor = selectedUserInteractor,
+ deviceEntryInteractor = deviceEntryInteractor,
+ simBouncerInteractor = simBouncerInteractor,
+ trustInteractor = trustInteractor,
+ )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneContainerStartableKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt
index cf18c0e295ea..8b887d32f3c1 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneContainerStartableKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.scene.domain.interactor
+package com.android.systemui.scene.domain.startable
import com.android.internal.logging.uiEventLogger
import com.android.systemui.authentication.domain.interactor.authenticationInteractor
@@ -32,7 +32,9 @@ import com.android.systemui.kosmos.Kosmos.Fixture
import com.android.systemui.kosmos.testScope
import com.android.systemui.model.sysUiState
import com.android.systemui.power.domain.interactor.powerInteractor
-import com.android.systemui.scene.domain.startable.SceneContainerStartable
+import com.android.systemui.scene.domain.interactor.sceneBackInteractor
+import com.android.systemui.scene.domain.interactor.sceneContainerOcclusionInteractor
+import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.session.shared.shadeSessionStorage
import com.android.systemui.scene.shared.logger.sceneLogger
import com.android.systemui.settings.displayTracker