Loading packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt +14 −0 Original line number Diff line number Diff line Loading @@ -76,6 +76,8 @@ import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobi import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository import com.android.systemui.statusbar.policy.data.repository.fakeDeviceProvisioningRepository import com.android.systemui.statusbar.policy.domain.interactor.deviceProvisioningInteractor import com.android.systemui.telephony.data.repository.fakeTelephonyRepository import com.android.systemui.testKosmos import com.android.systemui.util.mockito.any Loading Loading @@ -262,6 +264,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() { simBouncerInteractor = dagger.Lazy { kosmos.simBouncerInteractor }, authenticationInteractor = dagger.Lazy { kosmos.authenticationInteractor }, windowController = mock(), deviceProvisioningInteractor = kosmos.deviceProvisioningInteractor, ) startable.start() Loading Loading @@ -518,6 +521,17 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() { assertCurrentScene(SceneKey.Lockscreen) } @Test fun factoryResetProtectionActive_isNotVisible() = testScope.runTest { val isVisible by collectLastValue(sceneContainerViewModel.isVisible) assertThat(isVisible).isTrue() kosmos.fakeDeviceProvisioningRepository.setFactoryResetProtectionActive(isActive = true) assertThat(isVisible).isFalse() } /** * Asserts that the current scene in the view-model matches what's expected. * Loading packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt +2 −0 Original line number Diff line number Diff line Loading @@ -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.domain.interactor.deviceProvisioningInteractor import com.android.systemui.testKosmos import com.android.systemui.util.mockito.mock import com.google.common.truth.Truth.assertThat Loading Loading @@ -112,6 +113,7 @@ class SceneContainerStartableTest : SysuiTestCase() { simBouncerInteractor = dagger.Lazy { kosmos.simBouncerInteractor }, authenticationInteractor = dagger.Lazy { authenticationInteractor }, windowController = windowController, deviceProvisioningInteractor = kosmos.deviceProvisioningInteractor, ) } Loading packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt +27 −17 Original line number Diff line number Diff line Loading @@ -42,6 +42,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.notification.stack.shared.flexiNotifsEnabled import com.android.systemui.statusbar.policy.domain.interactor.DeviceProvisioningInteractor import com.android.systemui.util.asIndenting import com.android.systemui.util.printSection import com.android.systemui.util.println Loading @@ -55,6 +56,7 @@ import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChangedBy import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.mapNotNull import kotlinx.coroutines.launch Loading @@ -81,6 +83,7 @@ constructor( private val simBouncerInteractor: Lazy<SimBouncerInteractor>, private val authenticationInteractor: Lazy<AuthenticationInteractor>, private val windowController: NotificationShadeWindowController, private val deviceProvisioningInteractor: DeviceProvisioningInteractor, ) : CoreStartable { override fun start() { Loading Loading @@ -112,6 +115,11 @@ 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 { sceneInteractor.transitionState .mapNotNull { state -> when (state) { Loading @@ -132,6 +140,8 @@ constructor( } } .distinctUntilChanged() } } .collect { (isVisible, loggingReason) -> sceneInteractor.setVisible(isVisible, loggingReason) } Loading packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImpl.kt +6 −5 Original line number Diff line number Diff line Loading @@ -25,9 +25,10 @@ import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.power.domain.interactor.PowerInteractor import com.android.systemui.statusbar.disableflags.data.repository.DisableFlagsRepository import com.android.systemui.statusbar.phone.DozeParameters import com.android.systemui.statusbar.policy.data.repository.DeviceProvisioningRepository import com.android.systemui.statusbar.policy.data.repository.UserSetupRepository import com.android.systemui.statusbar.policy.domain.interactor.DeviceProvisioningInteractor import com.android.systemui.user.domain.interactor.UserSwitcherInteractor import com.android.systemui.util.kotlin.combine import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow Loading @@ -44,7 +45,7 @@ class ShadeInteractorImpl @Inject constructor( @Application val scope: CoroutineScope, deviceProvisioningRepository: DeviceProvisioningRepository, deviceProvisioningInteractor: DeviceProvisioningInteractor, disableFlagsRepository: DisableFlagsRepository, dozeParams: DozeParameters, keyguardRepository: KeyguardRepository, Loading @@ -56,7 +57,7 @@ constructor( ) : ShadeInteractor, BaseShadeInteractor by baseShadeInteractor { override val isShadeEnabled: StateFlow<Boolean> = combine( deviceProvisioningRepository.isFactoryResetProtectionActive, deviceProvisioningInteractor.isFactoryResetProtectionActive, disableFlagsRepository.disableFlags, ) { isFrpActive, isDisabledByFlags -> isDisabledByFlags.isShadeEnabled() && !isFrpActive Loading @@ -83,7 +84,7 @@ constructor( powerInteractor.isAsleep, keyguardTransitionInteractor.isInTransitionToStateWhere { it == KeyguardState.AOD }, keyguardRepository.dozeTransitionModel.map { it.to == DozeStateModel.DOZE_PULSING }, deviceProvisioningRepository.isFactoryResetProtectionActive, deviceProvisioningInteractor.isFactoryResetProtectionActive, ) { isAsleep, goingToSleep, isPulsing, isFrpActive -> when { // Touches are disabled when Factory Reset Protection is active Loading @@ -103,7 +104,7 @@ constructor( isShadeEnabled, keyguardRepository.isDozing, userSetupRepository.isUserSetUp, deviceProvisioningRepository.isDeviceProvisioned, deviceProvisioningInteractor.isDeviceProvisioned, ) { disableFlags, isShadeEnabled, isDozing, isUserSetup, isDeviceProvisioned -> isDeviceProvisioned && // Disallow QS during setup if it's a simple user switcher. (The user intends to Loading packages/SystemUI/src/com/android/systemui/statusbar/policy/domain/interactor/DeviceProvisioningInteractor.kt 0 → 100644 +40 −0 Original line number Diff line number Diff line /* * 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.statusbar.policy.domain.interactor import com.android.systemui.dagger.SysUISingleton import com.android.systemui.statusbar.policy.data.repository.DeviceProvisioningRepository import javax.inject.Inject import kotlinx.coroutines.flow.Flow /** Encapsulates device-provisioning related business logic. */ @SysUISingleton class DeviceProvisioningInteractor @Inject constructor( repository: DeviceProvisioningRepository, ) { /** * Whether this device has been provisioned. * * @see android.provider.Settings.Global.DEVICE_PROVISIONED */ val isDeviceProvisioned: Flow<Boolean> = repository.isDeviceProvisioned /** Whether Factory Reset Protection (FRP) is currently active, locking the device. */ val isFactoryResetProtectionActive: Flow<Boolean> = repository.isFactoryResetProtectionActive } Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt +14 −0 Original line number Diff line number Diff line Loading @@ -76,6 +76,8 @@ import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobi import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository import com.android.systemui.statusbar.policy.data.repository.fakeDeviceProvisioningRepository import com.android.systemui.statusbar.policy.domain.interactor.deviceProvisioningInteractor import com.android.systemui.telephony.data.repository.fakeTelephonyRepository import com.android.systemui.testKosmos import com.android.systemui.util.mockito.any Loading Loading @@ -262,6 +264,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() { simBouncerInteractor = dagger.Lazy { kosmos.simBouncerInteractor }, authenticationInteractor = dagger.Lazy { kosmos.authenticationInteractor }, windowController = mock(), deviceProvisioningInteractor = kosmos.deviceProvisioningInteractor, ) startable.start() Loading Loading @@ -518,6 +521,17 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() { assertCurrentScene(SceneKey.Lockscreen) } @Test fun factoryResetProtectionActive_isNotVisible() = testScope.runTest { val isVisible by collectLastValue(sceneContainerViewModel.isVisible) assertThat(isVisible).isTrue() kosmos.fakeDeviceProvisioningRepository.setFactoryResetProtectionActive(isActive = true) assertThat(isVisible).isFalse() } /** * Asserts that the current scene in the view-model matches what's expected. * Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt +2 −0 Original line number Diff line number Diff line Loading @@ -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.domain.interactor.deviceProvisioningInteractor import com.android.systemui.testKosmos import com.android.systemui.util.mockito.mock import com.google.common.truth.Truth.assertThat Loading Loading @@ -112,6 +113,7 @@ class SceneContainerStartableTest : SysuiTestCase() { simBouncerInteractor = dagger.Lazy { kosmos.simBouncerInteractor }, authenticationInteractor = dagger.Lazy { authenticationInteractor }, windowController = windowController, deviceProvisioningInteractor = kosmos.deviceProvisioningInteractor, ) } Loading
packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt +27 −17 Original line number Diff line number Diff line Loading @@ -42,6 +42,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.notification.stack.shared.flexiNotifsEnabled import com.android.systemui.statusbar.policy.domain.interactor.DeviceProvisioningInteractor import com.android.systemui.util.asIndenting import com.android.systemui.util.printSection import com.android.systemui.util.println Loading @@ -55,6 +56,7 @@ import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChangedBy import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.mapNotNull import kotlinx.coroutines.launch Loading @@ -81,6 +83,7 @@ constructor( private val simBouncerInteractor: Lazy<SimBouncerInteractor>, private val authenticationInteractor: Lazy<AuthenticationInteractor>, private val windowController: NotificationShadeWindowController, private val deviceProvisioningInteractor: DeviceProvisioningInteractor, ) : CoreStartable { override fun start() { Loading Loading @@ -112,6 +115,11 @@ 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 { sceneInteractor.transitionState .mapNotNull { state -> when (state) { Loading @@ -132,6 +140,8 @@ constructor( } } .distinctUntilChanged() } } .collect { (isVisible, loggingReason) -> sceneInteractor.setVisible(isVisible, loggingReason) } Loading
packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImpl.kt +6 −5 Original line number Diff line number Diff line Loading @@ -25,9 +25,10 @@ import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.power.domain.interactor.PowerInteractor import com.android.systemui.statusbar.disableflags.data.repository.DisableFlagsRepository import com.android.systemui.statusbar.phone.DozeParameters import com.android.systemui.statusbar.policy.data.repository.DeviceProvisioningRepository import com.android.systemui.statusbar.policy.data.repository.UserSetupRepository import com.android.systemui.statusbar.policy.domain.interactor.DeviceProvisioningInteractor import com.android.systemui.user.domain.interactor.UserSwitcherInteractor import com.android.systemui.util.kotlin.combine import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow Loading @@ -44,7 +45,7 @@ class ShadeInteractorImpl @Inject constructor( @Application val scope: CoroutineScope, deviceProvisioningRepository: DeviceProvisioningRepository, deviceProvisioningInteractor: DeviceProvisioningInteractor, disableFlagsRepository: DisableFlagsRepository, dozeParams: DozeParameters, keyguardRepository: KeyguardRepository, Loading @@ -56,7 +57,7 @@ constructor( ) : ShadeInteractor, BaseShadeInteractor by baseShadeInteractor { override val isShadeEnabled: StateFlow<Boolean> = combine( deviceProvisioningRepository.isFactoryResetProtectionActive, deviceProvisioningInteractor.isFactoryResetProtectionActive, disableFlagsRepository.disableFlags, ) { isFrpActive, isDisabledByFlags -> isDisabledByFlags.isShadeEnabled() && !isFrpActive Loading @@ -83,7 +84,7 @@ constructor( powerInteractor.isAsleep, keyguardTransitionInteractor.isInTransitionToStateWhere { it == KeyguardState.AOD }, keyguardRepository.dozeTransitionModel.map { it.to == DozeStateModel.DOZE_PULSING }, deviceProvisioningRepository.isFactoryResetProtectionActive, deviceProvisioningInteractor.isFactoryResetProtectionActive, ) { isAsleep, goingToSleep, isPulsing, isFrpActive -> when { // Touches are disabled when Factory Reset Protection is active Loading @@ -103,7 +104,7 @@ constructor( isShadeEnabled, keyguardRepository.isDozing, userSetupRepository.isUserSetUp, deviceProvisioningRepository.isDeviceProvisioned, deviceProvisioningInteractor.isDeviceProvisioned, ) { disableFlags, isShadeEnabled, isDozing, isUserSetup, isDeviceProvisioned -> isDeviceProvisioned && // Disallow QS during setup if it's a simple user switcher. (The user intends to Loading
packages/SystemUI/src/com/android/systemui/statusbar/policy/domain/interactor/DeviceProvisioningInteractor.kt 0 → 100644 +40 −0 Original line number Diff line number Diff line /* * 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.statusbar.policy.domain.interactor import com.android.systemui.dagger.SysUISingleton import com.android.systemui.statusbar.policy.data.repository.DeviceProvisioningRepository import javax.inject.Inject import kotlinx.coroutines.flow.Flow /** Encapsulates device-provisioning related business logic. */ @SysUISingleton class DeviceProvisioningInteractor @Inject constructor( repository: DeviceProvisioningRepository, ) { /** * Whether this device has been provisioned. * * @see android.provider.Settings.Global.DEVICE_PROVISIONED */ val isDeviceProvisioned: Flow<Boolean> = repository.isDeviceProvisioned /** Whether Factory Reset Protection (FRP) is currently active, locking the device. */ val isFactoryResetProtectionActive: Flow<Boolean> = repository.isFactoryResetProtectionActive }