diff options
6 files changed, 63 insertions, 11 deletions
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 d6d25096ba14..189ba7b1965a 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt @@ -522,14 +522,18 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() { } @Test - fun factoryResetProtectionActive_isNotVisible() = + fun deviceProvisioningAndFactoryResetProtection() = testScope.runTest { val isVisible by collectLastValue(sceneContainerViewModel.isVisible) - assertThat(isVisible).isTrue() - - kosmos.fakeDeviceProvisioningRepository.setFactoryResetProtectionActive(isActive = true) + kosmos.fakeDeviceProvisioningRepository.setDeviceProvisioned(false) + kosmos.fakeDeviceProvisioningRepository.setFactoryResetProtectionActive(true) + assertThat(isVisible).isFalse() + kosmos.fakeDeviceProvisioningRepository.setFactoryResetProtectionActive(false) assertThat(isVisible).isFalse() + + kosmos.fakeDeviceProvisioningRepository.setDeviceProvisioned(true) + assertThat(isVisible).isTrue() } /** 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 1abbc92a539b..12dbf11255b6 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 @@ -49,6 +49,7 @@ import com.android.systemui.scene.shared.model.SceneKey import com.android.systemui.scene.shared.model.SceneModel import com.android.systemui.statusbar.NotificationShadeWindowController import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository +import com.android.systemui.statusbar.policy.data.repository.fakeDeviceProvisioningRepository import com.android.systemui.statusbar.policy.domain.interactor.deviceProvisioningInteractor import com.android.systemui.testKosmos import com.android.systemui.util.mockito.mock @@ -164,6 +165,30 @@ class SceneContainerStartableTest : SysuiTestCase() { } @Test + fun hydrateVisibility_basedOnDeviceProvisioningAndFactoryResetProtection() = + testScope.runTest { + val isVisible by collectLastValue(sceneInteractor.isVisible) + prepareState( + isDeviceUnlocked = true, + initialSceneKey = SceneKey.Lockscreen, + isDeviceProvisioned = false, + isFrpActive = true, + ) + + underTest.start() + assertThat(isVisible).isFalse() + + kosmos.fakeDeviceProvisioningRepository.setFactoryResetProtectionActive(false) + assertThat(isVisible).isFalse() + + kosmos.fakeDeviceProvisioningRepository.setDeviceProvisioned(true) + assertThat(isVisible).isTrue() + + kosmos.fakeDeviceProvisioningRepository.setFactoryResetProtectionActive(true) + assertThat(isVisible).isFalse() + } + + @Test fun startsInLockscreenScene() = testScope.runTest { val currentSceneKey by collectLastValue(sceneInteractor.desiredScene.map { it.key }) @@ -745,6 +770,8 @@ class SceneContainerStartableTest : SysuiTestCase() { authenticationMethod: AuthenticationMethodModel? = null, isLockscreenEnabled: Boolean = true, startsAwake: Boolean = true, + isDeviceProvisioned: Boolean = true, + isFrpActive: Boolean = false, ): MutableStateFlow<ObservableTransitionState> { if (authenticationMethod?.isSecure == true) { assert(isLockscreenEnabled) { @@ -781,6 +808,10 @@ class SceneContainerStartableTest : SysuiTestCase() { } else { powerInteractor.setAsleepForTest() } + + kosmos.fakeDeviceProvisioningRepository.setDeviceProvisioned(isDeviceProvisioned) + kosmos.fakeDeviceProvisioningRepository.setFactoryResetProtectionActive(isFrpActive) + runCurrent() return transitionStateFlow 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 37abc4066e54..56c0ca910bd7 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 @@ -52,6 +52,7 @@ import javax.inject.Inject 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.distinctUntilChangedBy import kotlinx.coroutines.flow.emptyFlow @@ -115,11 +116,15 @@ constructor( private fun hydrateVisibility() { applicationScope.launch { // TODO(b/296114544): Combine with some global hun state to make it visible! - deviceProvisioningInteractor.isFactoryResetProtectionActive - .flatMapLatest { isFrpActive -> - if (isFrpActive) { - flowOf(false to "Factory Reset Protection is active") - } else { + combine( + deviceProvisioningInteractor.isDeviceProvisioned, + deviceProvisioningInteractor.isFactoryResetProtectionActive, + ) { isDeviceProvisioned, isFrpActive -> + isDeviceProvisioned && !isFrpActive + } + .distinctUntilChanged() + .flatMapLatest { isAllowedToBeVisible -> + if (isAllowedToBeVisible) { sceneInteractor.transitionState .mapNotNull { state -> when (state) { @@ -140,6 +145,8 @@ constructor( } } .distinctUntilChanged() + } else { + flowOf(false to "Device not provisioned or Factory Reset Protection active") } } .collect { (isVisible, loggingReason) -> diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerSceneImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerSceneImpl.kt index 10b9db0a349b..4e8b4039cc79 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerSceneImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerSceneImpl.kt @@ -20,6 +20,7 @@ import android.view.MotionEvent import com.android.systemui.assist.AssistManager import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background +import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor import com.android.systemui.log.LogBuffer import com.android.systemui.log.dagger.ShadeTouchLog @@ -34,11 +35,13 @@ import com.android.systemui.statusbar.notification.stack.NotificationStackScroll import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager import dagger.Lazy import javax.inject.Inject +import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.delay import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext /** * Implementation of ShadeController backed by scenes instead of NPVC. @@ -50,6 +53,7 @@ import kotlinx.coroutines.launch class ShadeControllerSceneImpl @Inject constructor( + @Main private val mainDispatcher: CoroutineDispatcher, @Background private val scope: CoroutineScope, private val shadeInteractor: ShadeInteractor, private val sceneInteractor: SceneInteractor, @@ -193,7 +197,11 @@ constructor( } override fun setVisibilityListener(listener: ShadeVisibilityListener) { - scope.launch { sceneInteractor.isVisible.collect { listener.expandedVisibleChanged(it) } } + scope.launch { + sceneInteractor.isVisible.collect { isVisible -> + withContext(mainDispatcher) { listener.expandedVisibleChanged(isVisible) } + } + } } @ExperimentalCoroutinesApi diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeControllerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeControllerKosmos.kt index e13fa5207b33..82e0b8e83f24 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeControllerKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeControllerKosmos.kt @@ -24,6 +24,7 @@ import com.android.systemui.concurrency.fakeExecutor import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.applicationCoroutineScope +import com.android.systemui.kosmos.testDispatcher import com.android.systemui.log.LogBuffer import com.android.systemui.plugins.statusbar.statusBarStateController import com.android.systemui.scene.domain.interactor.sceneInteractor @@ -44,6 +45,7 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi val Kosmos.shadeControllerSceneImpl by Kosmos.Fixture { ShadeControllerSceneImpl( + mainDispatcher = testDispatcher, scope = applicationCoroutineScope, shadeInteractor = shadeInteractor, sceneInteractor = sceneInteractor, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/data/repository/FakeDeviceProvisioningRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/data/repository/FakeDeviceProvisioningRepository.kt index 300229954044..fc6a800e186c 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/data/repository/FakeDeviceProvisioningRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/data/repository/FakeDeviceProvisioningRepository.kt @@ -24,7 +24,7 @@ import kotlinx.coroutines.flow.MutableStateFlow @SysUISingleton class FakeDeviceProvisioningRepository @Inject constructor() : DeviceProvisioningRepository { - private val _isDeviceProvisioned = MutableStateFlow(false) + private val _isDeviceProvisioned = MutableStateFlow(true) override val isDeviceProvisioned: Flow<Boolean> = _isDeviceProvisioned private val _isFactoryResetProtectionActive = MutableStateFlow(false) override val isFactoryResetProtectionActive: Flow<Boolean> = _isFactoryResetProtectionActive |