Loading packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorSceneContainerImplTest.kt +32 −0 Original line number Diff line number Diff line Loading @@ -124,4 +124,36 @@ class ShadeAnimationInteractorSceneContainerImplTest : SysuiTestCase() { underTest.setIsLaunchingActivity(true) Truth.assertThat(underTest.isLaunchingActivity.value).isEqualTo(true) } @Test fun isAnyFlingAnimationRunning() = testScope.runTest() { val actual by collectLastValue(underTest.isAnyFlingAnimationRunning) // WHEN transitioning from QS to Gone with user input ongoing val userInputOngoing = MutableStateFlow(true) val transitionState = MutableStateFlow<ObservableTransitionState>( ObservableTransitionState.Transition( fromScene = Scenes.QuickSettings, toScene = Scenes.Gone, currentScene = flowOf(Scenes.QuickSettings), progress = MutableStateFlow(.1f), isInitiatedByUserInput = true, isUserInputOngoing = userInputOngoing, ) ) sceneInteractor.setTransitionState(transitionState) runCurrent() // THEN qs is not flinging Truth.assertThat(actual).isFalse() // WHEN user input ends userInputOngoing.value = false runCurrent() // THEN qs is flinging Truth.assertThat(actual).isTrue() } } packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractor.kt +4 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.systemui.shade.domain.interactor import com.android.systemui.shade.data.repository.ShadeAnimationRepository import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow Loading @@ -38,4 +39,7 @@ abstract class ShadeAnimationInteractor( * that is not considered "closing". */ abstract val isAnyCloseAnimationRunning: StateFlow<Boolean> /** Whether a short animation to expand or collapse is running after user input has ended. */ abstract val isAnyFlingAnimationRunning: Flow<Boolean> } packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorEmptyImpl.kt +2 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.shade.data.repository.ShadeAnimationRepository import javax.inject.Inject import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.flowOf /** Implementation of ShadeAnimationInteractor for shadeless SysUI variants. */ @SysUISingleton Loading @@ -29,4 +30,5 @@ constructor( shadeAnimationRepository: ShadeAnimationRepository, ) : ShadeAnimationInteractor(shadeAnimationRepository) { override val isAnyCloseAnimationRunning = MutableStateFlow(false) override val isAnyFlingAnimationRunning = flowOf(false) } packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorLegacyImpl.kt +2 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.shade.data.repository.ShadeAnimationRepository import com.android.systemui.shade.data.repository.ShadeRepository import javax.inject.Inject import kotlinx.coroutines.flow.map /** Implementation of ShadeAnimationInteractor compatible with NPVC. */ @SysUISingleton Loading @@ -30,4 +31,5 @@ constructor( shadeRepository: ShadeRepository, ) : ShadeAnimationInteractor(shadeAnimationRepository) { override val isAnyCloseAnimationRunning = shadeRepository.legacyIsClosing override val isAnyFlingAnimationRunning = shadeRepository.currentFling.map { it != null } } packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorSceneContainerImpl.kt +23 −1 Original line number Diff line number Diff line Loading @@ -36,12 +36,12 @@ import kotlinx.coroutines.flow.stateIn @SysUISingleton class ShadeAnimationInteractorSceneContainerImpl @Inject @OptIn(ExperimentalCoroutinesApi::class) constructor( @Background scope: CoroutineScope, shadeAnimationRepository: ShadeAnimationRepository, sceneInteractor: SceneInteractor, ) : ShadeAnimationInteractor(shadeAnimationRepository) { @OptIn(ExperimentalCoroutinesApi::class) override val isAnyCloseAnimationRunning = sceneInteractor.transitionState .flatMapLatest { state -> Loading @@ -62,4 +62,26 @@ constructor( } .distinctUntilChanged() .stateIn(scope, SharingStarted.Eagerly, false) override val isAnyFlingAnimationRunning = sceneInteractor.transitionState .flatMapLatest { state -> when (state) { is ObservableTransitionState.Idle -> flowOf(false) is ObservableTransitionState.Transition -> if ( state.isInitiatedByUserInput && (state.fromScene == Scenes.Shade || state.toScene == Scenes.Shade || state.fromScene == Scenes.QuickSettings || state.toScene == Scenes.QuickSettings) ) { state.isUserInputOngoing.map { !it } } else { flowOf(false) } } } .distinctUntilChanged() .stateIn(scope, SharingStarted.Eagerly, false) } Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorSceneContainerImplTest.kt +32 −0 Original line number Diff line number Diff line Loading @@ -124,4 +124,36 @@ class ShadeAnimationInteractorSceneContainerImplTest : SysuiTestCase() { underTest.setIsLaunchingActivity(true) Truth.assertThat(underTest.isLaunchingActivity.value).isEqualTo(true) } @Test fun isAnyFlingAnimationRunning() = testScope.runTest() { val actual by collectLastValue(underTest.isAnyFlingAnimationRunning) // WHEN transitioning from QS to Gone with user input ongoing val userInputOngoing = MutableStateFlow(true) val transitionState = MutableStateFlow<ObservableTransitionState>( ObservableTransitionState.Transition( fromScene = Scenes.QuickSettings, toScene = Scenes.Gone, currentScene = flowOf(Scenes.QuickSettings), progress = MutableStateFlow(.1f), isInitiatedByUserInput = true, isUserInputOngoing = userInputOngoing, ) ) sceneInteractor.setTransitionState(transitionState) runCurrent() // THEN qs is not flinging Truth.assertThat(actual).isFalse() // WHEN user input ends userInputOngoing.value = false runCurrent() // THEN qs is flinging Truth.assertThat(actual).isTrue() } }
packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractor.kt +4 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.systemui.shade.domain.interactor import com.android.systemui.shade.data.repository.ShadeAnimationRepository import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow Loading @@ -38,4 +39,7 @@ abstract class ShadeAnimationInteractor( * that is not considered "closing". */ abstract val isAnyCloseAnimationRunning: StateFlow<Boolean> /** Whether a short animation to expand or collapse is running after user input has ended. */ abstract val isAnyFlingAnimationRunning: Flow<Boolean> }
packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorEmptyImpl.kt +2 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.shade.data.repository.ShadeAnimationRepository import javax.inject.Inject import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.flowOf /** Implementation of ShadeAnimationInteractor for shadeless SysUI variants. */ @SysUISingleton Loading @@ -29,4 +30,5 @@ constructor( shadeAnimationRepository: ShadeAnimationRepository, ) : ShadeAnimationInteractor(shadeAnimationRepository) { override val isAnyCloseAnimationRunning = MutableStateFlow(false) override val isAnyFlingAnimationRunning = flowOf(false) }
packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorLegacyImpl.kt +2 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.shade.data.repository.ShadeAnimationRepository import com.android.systemui.shade.data.repository.ShadeRepository import javax.inject.Inject import kotlinx.coroutines.flow.map /** Implementation of ShadeAnimationInteractor compatible with NPVC. */ @SysUISingleton Loading @@ -30,4 +31,5 @@ constructor( shadeRepository: ShadeRepository, ) : ShadeAnimationInteractor(shadeAnimationRepository) { override val isAnyCloseAnimationRunning = shadeRepository.legacyIsClosing override val isAnyFlingAnimationRunning = shadeRepository.currentFling.map { it != null } }
packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorSceneContainerImpl.kt +23 −1 Original line number Diff line number Diff line Loading @@ -36,12 +36,12 @@ import kotlinx.coroutines.flow.stateIn @SysUISingleton class ShadeAnimationInteractorSceneContainerImpl @Inject @OptIn(ExperimentalCoroutinesApi::class) constructor( @Background scope: CoroutineScope, shadeAnimationRepository: ShadeAnimationRepository, sceneInteractor: SceneInteractor, ) : ShadeAnimationInteractor(shadeAnimationRepository) { @OptIn(ExperimentalCoroutinesApi::class) override val isAnyCloseAnimationRunning = sceneInteractor.transitionState .flatMapLatest { state -> Loading @@ -62,4 +62,26 @@ constructor( } .distinctUntilChanged() .stateIn(scope, SharingStarted.Eagerly, false) override val isAnyFlingAnimationRunning = sceneInteractor.transitionState .flatMapLatest { state -> when (state) { is ObservableTransitionState.Idle -> flowOf(false) is ObservableTransitionState.Transition -> if ( state.isInitiatedByUserInput && (state.fromScene == Scenes.Shade || state.toScene == Scenes.Shade || state.fromScene == Scenes.QuickSettings || state.toScene == Scenes.QuickSettings) ) { state.isUserInputOngoing.map { !it } } else { flowOf(false) } } } .distinctUntilChanged() .stateIn(scope, SharingStarted.Eagerly, false) }