Loading packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt +1 −1 Original line number Diff line number Diff line Loading @@ -42,7 +42,7 @@ interface ShadeRepository { /** * The amount the lockscreen shade has dragged down by the user, [0-1]. 0 means fully collapsed, * 1 means fully expanded. * 1 means fully expanded. Value resets to 0 when the user finishes dragging. */ val lockscreenShadeExpansion: StateFlow<Float> Loading packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt +66 −16 Original line number Diff line number Diff line Loading @@ -20,6 +20,10 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.keyguard.data.repository.KeyguardRepository import com.android.systemui.keyguard.shared.model.StatusBarState import com.android.systemui.scene.domain.interactor.SceneInteractor import com.android.systemui.scene.shared.flag.SceneContainerFlags import com.android.systemui.scene.shared.model.ObservableTransitionState import com.android.systemui.scene.shared.model.SceneKey import com.android.systemui.shade.data.repository.ShadeRepository import com.android.systemui.statusbar.disableflags.data.repository.DisableFlagsRepository import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor Loading @@ -28,22 +32,29 @@ import com.android.systemui.statusbar.policy.DeviceProvisionedController import com.android.systemui.user.domain.interactor.UserInteractor import com.android.systemui.util.kotlin.pairwise import javax.inject.Inject import javax.inject.Provider import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn /** Business logic for shade interactions. */ @OptIn(ExperimentalCoroutinesApi::class) @SysUISingleton class ShadeInteractor @Inject constructor( @Application scope: CoroutineScope, disableFlagsRepository: DisableFlagsRepository, sceneContainerFlags: SceneContainerFlags, sceneInteractorProvider: Provider<SceneInteractor>, keyguardRepository: KeyguardRepository, userSetupRepository: UserSetupRepository, deviceProvisionedController: DeviceProvisionedController, Loading @@ -68,28 +79,45 @@ constructor( /** The amount [0-1] that the shade has been opened */ val shadeExpansion: Flow<Float> = if (sceneContainerFlags.isEnabled()) { sceneBasedExpansion(sceneInteractorProvider.get(), SceneKey.Shade) } else { combine( repository.lockscreenShadeExpansion, keyguardRepository.statusBarState, repository.legacyShadeExpansion, repository.qsExpansion, splitShadeEnabled ) { dragDownAmount, statusBarState, legacyShadeExpansion, qsExpansion, splitShadeEnabled -> ) { lockscreenShadeExpansion, statusBarState, legacyShadeExpansion, qsExpansion, splitShadeEnabled -> when (statusBarState) { // legacyShadeExpansion is 1 instead of 0 when QS is expanded StatusBarState.SHADE -> if (!splitShadeEnabled && qsExpansion > 0f) 0f else legacyShadeExpansion StatusBarState.KEYGUARD -> dragDownAmount // This is required, as shadeExpansion gets reset to 0f even with the shade open StatusBarState.KEYGUARD -> lockscreenShadeExpansion // dragDownAmount, which drives lockscreenShadeExpansion resets to 0f when // the pointer is lifted and the lockscreen shade is fully expanded StatusBarState.SHADE_LOCKED -> 1f } } .distinctUntilChanged() } /** * The amount [0-1] QS has been opened. Normal shade with notifications (QQS) visible will * report 0f. */ val qsExpansion: StateFlow<Float> = repository.qsExpansion val qsExpansion: StateFlow<Float> = if (sceneContainerFlags.isEnabled()) { sceneBasedExpansion(sceneInteractorProvider.get(), SceneKey.QuickSettings) .stateIn(scope, SharingStarted.Eagerly, 0f) } else { repository.qsExpansion } /** The amount [0-1] either QS or the shade has been opened */ val anyExpansion: StateFlow<Float> = Loading Loading @@ -119,4 +147,26 @@ constructor( disableFlags.isQuickSettingsEnabled() && !isDozing } fun sceneBasedExpansion(sceneInteractor: SceneInteractor, sceneKey: SceneKey) = sceneInteractor.transitionState .flatMapLatest { state -> when (state) { is ObservableTransitionState.Idle -> if (state.scene == sceneKey) { flowOf(1f) } else { flowOf(0f) } is ObservableTransitionState.Transition -> if (state.toScene == sceneKey) { state.progress } else if (state.fromScene == sceneKey) { state.progress.map { progress -> 1 - progress } } else { flowOf(0f) } } } .distinctUntilChanged() } packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthDialogPanelInteractionDetectorTest.kt +9 −4 Original line number Diff line number Diff line Loading @@ -28,6 +28,8 @@ import com.android.systemui.flags.Flags import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory import com.android.systemui.plugins.ActivityStarter import com.android.systemui.scene.SceneTestUtils import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags import com.android.systemui.shade.data.repository.FakeShadeRepository import com.android.systemui.shade.domain.interactor.ShadeInteractor import com.android.systemui.statusbar.disableflags.data.repository.FakeDisableFlagsRepository Loading @@ -42,8 +44,6 @@ import com.android.systemui.user.domain.interactor.HeadlessSystemUserMode import com.android.systemui.user.domain.interactor.RefreshUsersScheduler import com.android.systemui.user.domain.interactor.UserInteractor import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before Loading @@ -56,12 +56,15 @@ import org.mockito.MockitoAnnotations @SmallTest @OptIn(ExperimentalCoroutinesApi::class) class AuthDialogPanelInteractionDetectorTest : SysuiTestCase() { private val utils = SceneTestUtils(this) private val testScope = utils.testScope private val testDispatcher = utils.testDispatcher private val disableFlagsRepository = FakeDisableFlagsRepository() private val featureFlags = FakeFeatureFlags() private val keyguardRepository = FakeKeyguardRepository() private val shadeRepository = FakeShadeRepository() private val testDispatcher = StandardTestDispatcher() private val testScope = TestScope(testDispatcher) private val sceneContainerFlags = FakeSceneContainerFlags() private val sceneInteractor = utils.sceneInteractor() private val userSetupRepository = FakeUserSetupRepository() private val userRepository = FakeUserRepository() private val configurationRepository = FakeConfigurationRepository() Loading Loading @@ -126,6 +129,8 @@ class AuthDialogPanelInteractionDetectorTest : SysuiTestCase() { ShadeInteractor( testScope.backgroundScope, disableFlagsRepository, sceneContainerFlags, { sceneInteractor }, keyguardRepository, userSetupRepository, deviceProvisionedController, Loading packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java +6 −2 Original line number Diff line number Diff line Loading @@ -34,7 +34,6 @@ import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.UiEventLogger; import com.android.keyguard.KeyguardStatusView; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.TestScopeProvider; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository; Loading @@ -48,6 +47,8 @@ import com.android.systemui.media.controls.ui.MediaHierarchyManager; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QS; import com.android.systemui.qs.QSFragment; import com.android.systemui.scene.SceneTestUtils; import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags; import com.android.systemui.screenrecord.RecordingController; import com.android.systemui.shade.data.repository.FakeShadeRepository; import com.android.systemui.shade.domain.interactor.ShadeInteractor; Loading Loading @@ -99,7 +100,8 @@ public class QuickSettingsControllerBaseTest extends SysuiTestCase { protected QuickSettingsController mQsController; protected TestScope mTestScope = TestScopeProvider.getTestScope(); protected SceneTestUtils mUtils = new SceneTestUtils(this); protected TestScope mTestScope = mUtils.getTestScope(); @Mock protected Resources mResources; Loading Loading @@ -172,6 +174,8 @@ public class QuickSettingsControllerBaseTest extends SysuiTestCase { new ShadeInteractor( mTestScope.getBackgroundScope(), mDisableFlagsRepository, new FakeSceneContainerFlags(), () -> mUtils.sceneInteractor(), mKeyguardRepository, new FakeUserSetupRepository(), mDeviceProvisionedController, Loading packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeInteractorTest.kt +155 −6 Original line number Diff line number Diff line Loading @@ -35,6 +35,10 @@ import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory import com.android.systemui.keyguard.shared.model.StatusBarState import com.android.systemui.plugins.ActivityStarter import com.android.systemui.scene.SceneTestUtils import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags import com.android.systemui.scene.shared.model.ObservableTransitionState import com.android.systemui.scene.shared.model.SceneKey import com.android.systemui.shade.domain.interactor.ShadeInteractor import com.android.systemui.statusbar.disableflags.data.model.DisableFlagsModel import com.android.systemui.statusbar.disableflags.data.repository.FakeDisableFlagsRepository Loading @@ -52,9 +56,8 @@ import com.android.systemui.user.domain.interactor.UserInteractor import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before Loading @@ -67,9 +70,11 @@ import org.mockito.MockitoAnnotations class ShadeInteractorTest : SysuiTestCase() { private lateinit var underTest: ShadeInteractor private val testDispatcher = StandardTestDispatcher() private val testScope = TestScope(testDispatcher) private val utils = SceneTestUtils(this) private val testScope = utils.testScope private val featureFlags = FakeFeatureFlags() private val sceneContainerFlags = FakeSceneContainerFlags() private val sceneInteractor = utils.sceneInteractor() private val userSetupRepository = FakeUserSetupRepository() private val userRepository = FakeUserRepository() private val disableFlagsRepository = FakeDisableFlagsRepository() Loading Loading @@ -103,7 +108,7 @@ class ShadeInteractorTest : SysuiTestCase() { val refreshUsersScheduler = RefreshUsersScheduler( applicationScope = testScope.backgroundScope, mainDispatcher = testDispatcher, mainDispatcher = utils.testDispatcher, repository = userRepository, ) Loading Loading @@ -141,7 +146,7 @@ class ShadeInteractorTest : SysuiTestCase() { ), broadcastDispatcher = fakeBroadcastDispatcher, keyguardUpdateMonitor = keyguardUpdateMonitor, backgroundDispatcher = testDispatcher, backgroundDispatcher = utils.testDispatcher, activityManager = activityManager, refreshUsersScheduler = refreshUsersScheduler, guestUserInteractor = guestInteractor, Loading @@ -151,6 +156,8 @@ class ShadeInteractorTest : SysuiTestCase() { ShadeInteractor( testScope.backgroundScope, disableFlagsRepository, sceneContainerFlags, { sceneInteractor }, keyguardRepository, userSetupRepository, deviceProvisionedController, Loading Loading @@ -557,4 +564,146 @@ class ShadeInteractorTest : SysuiTestCase() { // THEN anyExpanding is false assertThat(actual).isFalse() } @Test fun lockscreenShadeExpansion_idle_onScene() = testScope.runTest() { // GIVEN an expansion flow based on transitions to and from a scene val key = SceneKey.Shade val expansion = underTest.sceneBasedExpansion(sceneInteractor, key) val expansionAmount by collectLastValue(expansion) // WHEN transition state is idle on the scene val transitionState = MutableStateFlow<ObservableTransitionState>(ObservableTransitionState.Idle(key)) sceneInteractor.setTransitionState(transitionState) // THEN expansion is 1 assertThat(expansionAmount).isEqualTo(1f) } @Test fun lockscreenShadeExpansion_idle_onDifferentScene() = testScope.runTest() { // GIVEN an expansion flow based on transitions to and from a scene val expansion = underTest.sceneBasedExpansion(sceneInteractor, SceneKey.Shade) val expansionAmount by collectLastValue(expansion) // WHEN transition state is idle on a different scene val transitionState = MutableStateFlow<ObservableTransitionState>( ObservableTransitionState.Idle(SceneKey.Lockscreen) ) sceneInteractor.setTransitionState(transitionState) // THEN expansion is 0 assertThat(expansionAmount).isEqualTo(0f) } @Test fun lockscreenShadeExpansion_transitioning_toScene() = testScope.runTest() { // GIVEN an expansion flow based on transitions to and from a scene val key = SceneKey.QuickSettings val expansion = underTest.sceneBasedExpansion(sceneInteractor, key) val expansionAmount by collectLastValue(expansion) // WHEN transition state is starting to move to the scene val progress = MutableStateFlow(0f) val transitionState = MutableStateFlow<ObservableTransitionState>( ObservableTransitionState.Transition( fromScene = SceneKey.Lockscreen, toScene = key, progress = progress, ) ) sceneInteractor.setTransitionState(transitionState) // THEN expansion is 0 assertThat(expansionAmount).isEqualTo(0f) // WHEN transition state is partially to the scene progress.value = .4f // THEN expansion matches the progress assertThat(expansionAmount).isEqualTo(.4f) // WHEN transition completes progress.value = 1f // THEN expansion is 1 assertThat(expansionAmount).isEqualTo(1f) } @Test fun lockscreenShadeExpansion_transitioning_fromScene() = testScope.runTest() { // GIVEN an expansion flow based on transitions to and from a scene val key = SceneKey.QuickSettings val expansion = underTest.sceneBasedExpansion(sceneInteractor, key) val expansionAmount by collectLastValue(expansion) // WHEN transition state is starting to move to the scene val progress = MutableStateFlow(0f) val transitionState = MutableStateFlow<ObservableTransitionState>( ObservableTransitionState.Transition( fromScene = key, toScene = SceneKey.Lockscreen, progress = progress, ) ) sceneInteractor.setTransitionState(transitionState) // THEN expansion is 1 assertThat(expansionAmount).isEqualTo(1f) // WHEN transition state is partially to the scene progress.value = .4f // THEN expansion reflects the progress assertThat(expansionAmount).isEqualTo(.6f) // WHEN transition completes progress.value = 1f // THEN expansion is 0 assertThat(expansionAmount).isEqualTo(0f) } @Test fun lockscreenShadeExpansion_transitioning_toAndFromDifferentScenes() = testScope.runTest() { // GIVEN an expansion flow based on transitions to and from a scene val expansion = underTest.sceneBasedExpansion(sceneInteractor, SceneKey.QuickSettings) val expansionAmount by collectLastValue(expansion) // WHEN transition state is starting to between different scenes val progress = MutableStateFlow(0f) val transitionState = MutableStateFlow<ObservableTransitionState>( ObservableTransitionState.Transition( fromScene = SceneKey.Lockscreen, toScene = SceneKey.Shade, progress = progress, ) ) sceneInteractor.setTransitionState(transitionState) // THEN expansion is 0 assertThat(expansionAmount).isEqualTo(0f) // WHEN transition state is partially complete progress.value = .4f // THEN expansion is still 0 assertThat(expansionAmount).isEqualTo(0f) // WHEN transition completes progress.value = 1f // THEN expansion is still 0 assertThat(expansionAmount).isEqualTo(0f) } } Loading
packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt +1 −1 Original line number Diff line number Diff line Loading @@ -42,7 +42,7 @@ interface ShadeRepository { /** * The amount the lockscreen shade has dragged down by the user, [0-1]. 0 means fully collapsed, * 1 means fully expanded. * 1 means fully expanded. Value resets to 0 when the user finishes dragging. */ val lockscreenShadeExpansion: StateFlow<Float> Loading
packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt +66 −16 Original line number Diff line number Diff line Loading @@ -20,6 +20,10 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.keyguard.data.repository.KeyguardRepository import com.android.systemui.keyguard.shared.model.StatusBarState import com.android.systemui.scene.domain.interactor.SceneInteractor import com.android.systemui.scene.shared.flag.SceneContainerFlags import com.android.systemui.scene.shared.model.ObservableTransitionState import com.android.systemui.scene.shared.model.SceneKey import com.android.systemui.shade.data.repository.ShadeRepository import com.android.systemui.statusbar.disableflags.data.repository.DisableFlagsRepository import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor Loading @@ -28,22 +32,29 @@ import com.android.systemui.statusbar.policy.DeviceProvisionedController import com.android.systemui.user.domain.interactor.UserInteractor import com.android.systemui.util.kotlin.pairwise import javax.inject.Inject import javax.inject.Provider import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn /** Business logic for shade interactions. */ @OptIn(ExperimentalCoroutinesApi::class) @SysUISingleton class ShadeInteractor @Inject constructor( @Application scope: CoroutineScope, disableFlagsRepository: DisableFlagsRepository, sceneContainerFlags: SceneContainerFlags, sceneInteractorProvider: Provider<SceneInteractor>, keyguardRepository: KeyguardRepository, userSetupRepository: UserSetupRepository, deviceProvisionedController: DeviceProvisionedController, Loading @@ -68,28 +79,45 @@ constructor( /** The amount [0-1] that the shade has been opened */ val shadeExpansion: Flow<Float> = if (sceneContainerFlags.isEnabled()) { sceneBasedExpansion(sceneInteractorProvider.get(), SceneKey.Shade) } else { combine( repository.lockscreenShadeExpansion, keyguardRepository.statusBarState, repository.legacyShadeExpansion, repository.qsExpansion, splitShadeEnabled ) { dragDownAmount, statusBarState, legacyShadeExpansion, qsExpansion, splitShadeEnabled -> ) { lockscreenShadeExpansion, statusBarState, legacyShadeExpansion, qsExpansion, splitShadeEnabled -> when (statusBarState) { // legacyShadeExpansion is 1 instead of 0 when QS is expanded StatusBarState.SHADE -> if (!splitShadeEnabled && qsExpansion > 0f) 0f else legacyShadeExpansion StatusBarState.KEYGUARD -> dragDownAmount // This is required, as shadeExpansion gets reset to 0f even with the shade open StatusBarState.KEYGUARD -> lockscreenShadeExpansion // dragDownAmount, which drives lockscreenShadeExpansion resets to 0f when // the pointer is lifted and the lockscreen shade is fully expanded StatusBarState.SHADE_LOCKED -> 1f } } .distinctUntilChanged() } /** * The amount [0-1] QS has been opened. Normal shade with notifications (QQS) visible will * report 0f. */ val qsExpansion: StateFlow<Float> = repository.qsExpansion val qsExpansion: StateFlow<Float> = if (sceneContainerFlags.isEnabled()) { sceneBasedExpansion(sceneInteractorProvider.get(), SceneKey.QuickSettings) .stateIn(scope, SharingStarted.Eagerly, 0f) } else { repository.qsExpansion } /** The amount [0-1] either QS or the shade has been opened */ val anyExpansion: StateFlow<Float> = Loading Loading @@ -119,4 +147,26 @@ constructor( disableFlags.isQuickSettingsEnabled() && !isDozing } fun sceneBasedExpansion(sceneInteractor: SceneInteractor, sceneKey: SceneKey) = sceneInteractor.transitionState .flatMapLatest { state -> when (state) { is ObservableTransitionState.Idle -> if (state.scene == sceneKey) { flowOf(1f) } else { flowOf(0f) } is ObservableTransitionState.Transition -> if (state.toScene == sceneKey) { state.progress } else if (state.fromScene == sceneKey) { state.progress.map { progress -> 1 - progress } } else { flowOf(0f) } } } .distinctUntilChanged() }
packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthDialogPanelInteractionDetectorTest.kt +9 −4 Original line number Diff line number Diff line Loading @@ -28,6 +28,8 @@ import com.android.systemui.flags.Flags import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory import com.android.systemui.plugins.ActivityStarter import com.android.systemui.scene.SceneTestUtils import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags import com.android.systemui.shade.data.repository.FakeShadeRepository import com.android.systemui.shade.domain.interactor.ShadeInteractor import com.android.systemui.statusbar.disableflags.data.repository.FakeDisableFlagsRepository Loading @@ -42,8 +44,6 @@ import com.android.systemui.user.domain.interactor.HeadlessSystemUserMode import com.android.systemui.user.domain.interactor.RefreshUsersScheduler import com.android.systemui.user.domain.interactor.UserInteractor import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before Loading @@ -56,12 +56,15 @@ import org.mockito.MockitoAnnotations @SmallTest @OptIn(ExperimentalCoroutinesApi::class) class AuthDialogPanelInteractionDetectorTest : SysuiTestCase() { private val utils = SceneTestUtils(this) private val testScope = utils.testScope private val testDispatcher = utils.testDispatcher private val disableFlagsRepository = FakeDisableFlagsRepository() private val featureFlags = FakeFeatureFlags() private val keyguardRepository = FakeKeyguardRepository() private val shadeRepository = FakeShadeRepository() private val testDispatcher = StandardTestDispatcher() private val testScope = TestScope(testDispatcher) private val sceneContainerFlags = FakeSceneContainerFlags() private val sceneInteractor = utils.sceneInteractor() private val userSetupRepository = FakeUserSetupRepository() private val userRepository = FakeUserRepository() private val configurationRepository = FakeConfigurationRepository() Loading Loading @@ -126,6 +129,8 @@ class AuthDialogPanelInteractionDetectorTest : SysuiTestCase() { ShadeInteractor( testScope.backgroundScope, disableFlagsRepository, sceneContainerFlags, { sceneInteractor }, keyguardRepository, userSetupRepository, deviceProvisionedController, Loading
packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java +6 −2 Original line number Diff line number Diff line Loading @@ -34,7 +34,6 @@ import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.UiEventLogger; import com.android.keyguard.KeyguardStatusView; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.TestScopeProvider; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository; Loading @@ -48,6 +47,8 @@ import com.android.systemui.media.controls.ui.MediaHierarchyManager; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QS; import com.android.systemui.qs.QSFragment; import com.android.systemui.scene.SceneTestUtils; import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags; import com.android.systemui.screenrecord.RecordingController; import com.android.systemui.shade.data.repository.FakeShadeRepository; import com.android.systemui.shade.domain.interactor.ShadeInteractor; Loading Loading @@ -99,7 +100,8 @@ public class QuickSettingsControllerBaseTest extends SysuiTestCase { protected QuickSettingsController mQsController; protected TestScope mTestScope = TestScopeProvider.getTestScope(); protected SceneTestUtils mUtils = new SceneTestUtils(this); protected TestScope mTestScope = mUtils.getTestScope(); @Mock protected Resources mResources; Loading Loading @@ -172,6 +174,8 @@ public class QuickSettingsControllerBaseTest extends SysuiTestCase { new ShadeInteractor( mTestScope.getBackgroundScope(), mDisableFlagsRepository, new FakeSceneContainerFlags(), () -> mUtils.sceneInteractor(), mKeyguardRepository, new FakeUserSetupRepository(), mDeviceProvisionedController, Loading
packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeInteractorTest.kt +155 −6 Original line number Diff line number Diff line Loading @@ -35,6 +35,10 @@ import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory import com.android.systemui.keyguard.shared.model.StatusBarState import com.android.systemui.plugins.ActivityStarter import com.android.systemui.scene.SceneTestUtils import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags import com.android.systemui.scene.shared.model.ObservableTransitionState import com.android.systemui.scene.shared.model.SceneKey import com.android.systemui.shade.domain.interactor.ShadeInteractor import com.android.systemui.statusbar.disableflags.data.model.DisableFlagsModel import com.android.systemui.statusbar.disableflags.data.repository.FakeDisableFlagsRepository Loading @@ -52,9 +56,8 @@ import com.android.systemui.user.domain.interactor.UserInteractor import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before Loading @@ -67,9 +70,11 @@ import org.mockito.MockitoAnnotations class ShadeInteractorTest : SysuiTestCase() { private lateinit var underTest: ShadeInteractor private val testDispatcher = StandardTestDispatcher() private val testScope = TestScope(testDispatcher) private val utils = SceneTestUtils(this) private val testScope = utils.testScope private val featureFlags = FakeFeatureFlags() private val sceneContainerFlags = FakeSceneContainerFlags() private val sceneInteractor = utils.sceneInteractor() private val userSetupRepository = FakeUserSetupRepository() private val userRepository = FakeUserRepository() private val disableFlagsRepository = FakeDisableFlagsRepository() Loading Loading @@ -103,7 +108,7 @@ class ShadeInteractorTest : SysuiTestCase() { val refreshUsersScheduler = RefreshUsersScheduler( applicationScope = testScope.backgroundScope, mainDispatcher = testDispatcher, mainDispatcher = utils.testDispatcher, repository = userRepository, ) Loading Loading @@ -141,7 +146,7 @@ class ShadeInteractorTest : SysuiTestCase() { ), broadcastDispatcher = fakeBroadcastDispatcher, keyguardUpdateMonitor = keyguardUpdateMonitor, backgroundDispatcher = testDispatcher, backgroundDispatcher = utils.testDispatcher, activityManager = activityManager, refreshUsersScheduler = refreshUsersScheduler, guestUserInteractor = guestInteractor, Loading @@ -151,6 +156,8 @@ class ShadeInteractorTest : SysuiTestCase() { ShadeInteractor( testScope.backgroundScope, disableFlagsRepository, sceneContainerFlags, { sceneInteractor }, keyguardRepository, userSetupRepository, deviceProvisionedController, Loading Loading @@ -557,4 +564,146 @@ class ShadeInteractorTest : SysuiTestCase() { // THEN anyExpanding is false assertThat(actual).isFalse() } @Test fun lockscreenShadeExpansion_idle_onScene() = testScope.runTest() { // GIVEN an expansion flow based on transitions to and from a scene val key = SceneKey.Shade val expansion = underTest.sceneBasedExpansion(sceneInteractor, key) val expansionAmount by collectLastValue(expansion) // WHEN transition state is idle on the scene val transitionState = MutableStateFlow<ObservableTransitionState>(ObservableTransitionState.Idle(key)) sceneInteractor.setTransitionState(transitionState) // THEN expansion is 1 assertThat(expansionAmount).isEqualTo(1f) } @Test fun lockscreenShadeExpansion_idle_onDifferentScene() = testScope.runTest() { // GIVEN an expansion flow based on transitions to and from a scene val expansion = underTest.sceneBasedExpansion(sceneInteractor, SceneKey.Shade) val expansionAmount by collectLastValue(expansion) // WHEN transition state is idle on a different scene val transitionState = MutableStateFlow<ObservableTransitionState>( ObservableTransitionState.Idle(SceneKey.Lockscreen) ) sceneInteractor.setTransitionState(transitionState) // THEN expansion is 0 assertThat(expansionAmount).isEqualTo(0f) } @Test fun lockscreenShadeExpansion_transitioning_toScene() = testScope.runTest() { // GIVEN an expansion flow based on transitions to and from a scene val key = SceneKey.QuickSettings val expansion = underTest.sceneBasedExpansion(sceneInteractor, key) val expansionAmount by collectLastValue(expansion) // WHEN transition state is starting to move to the scene val progress = MutableStateFlow(0f) val transitionState = MutableStateFlow<ObservableTransitionState>( ObservableTransitionState.Transition( fromScene = SceneKey.Lockscreen, toScene = key, progress = progress, ) ) sceneInteractor.setTransitionState(transitionState) // THEN expansion is 0 assertThat(expansionAmount).isEqualTo(0f) // WHEN transition state is partially to the scene progress.value = .4f // THEN expansion matches the progress assertThat(expansionAmount).isEqualTo(.4f) // WHEN transition completes progress.value = 1f // THEN expansion is 1 assertThat(expansionAmount).isEqualTo(1f) } @Test fun lockscreenShadeExpansion_transitioning_fromScene() = testScope.runTest() { // GIVEN an expansion flow based on transitions to and from a scene val key = SceneKey.QuickSettings val expansion = underTest.sceneBasedExpansion(sceneInteractor, key) val expansionAmount by collectLastValue(expansion) // WHEN transition state is starting to move to the scene val progress = MutableStateFlow(0f) val transitionState = MutableStateFlow<ObservableTransitionState>( ObservableTransitionState.Transition( fromScene = key, toScene = SceneKey.Lockscreen, progress = progress, ) ) sceneInteractor.setTransitionState(transitionState) // THEN expansion is 1 assertThat(expansionAmount).isEqualTo(1f) // WHEN transition state is partially to the scene progress.value = .4f // THEN expansion reflects the progress assertThat(expansionAmount).isEqualTo(.6f) // WHEN transition completes progress.value = 1f // THEN expansion is 0 assertThat(expansionAmount).isEqualTo(0f) } @Test fun lockscreenShadeExpansion_transitioning_toAndFromDifferentScenes() = testScope.runTest() { // GIVEN an expansion flow based on transitions to and from a scene val expansion = underTest.sceneBasedExpansion(sceneInteractor, SceneKey.QuickSettings) val expansionAmount by collectLastValue(expansion) // WHEN transition state is starting to between different scenes val progress = MutableStateFlow(0f) val transitionState = MutableStateFlow<ObservableTransitionState>( ObservableTransitionState.Transition( fromScene = SceneKey.Lockscreen, toScene = SceneKey.Shade, progress = progress, ) ) sceneInteractor.setTransitionState(transitionState) // THEN expansion is 0 assertThat(expansionAmount).isEqualTo(0f) // WHEN transition state is partially complete progress.value = .4f // THEN expansion is still 0 assertThat(expansionAmount).isEqualTo(0f) // WHEN transition completes progress.value = 1f // THEN expansion is still 0 assertThat(expansionAmount).isEqualTo(0f) } }