Loading packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractorTest.kt +18 −0 Original line number Original line Diff line number Diff line Loading @@ -20,6 +20,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import androidx.test.filters.SmallTest import com.android.compose.animation.scene.ObservableTransitionState import com.android.compose.animation.scene.ObservableTransitionState import com.android.systemui.SysuiTestCase import com.android.systemui.SysuiTestCase import com.android.systemui.animation.ActivityTransitionAnimator import com.android.systemui.communal.data.repository.communalSceneRepository import com.android.systemui.communal.data.repository.communalSceneRepository import com.android.systemui.communal.domain.model.CommunalTransitionProgressModel import com.android.systemui.communal.domain.model.CommunalTransitionProgressModel import com.android.systemui.communal.shared.model.CommunalScenes import com.android.systemui.communal.shared.model.CommunalScenes Loading @@ -27,8 +28,10 @@ import com.android.systemui.coroutines.collectLastValue import com.android.systemui.kosmos.testScope import com.android.systemui.kosmos.testScope import com.android.systemui.testKosmos import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.advanceTimeBy import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest import org.junit.Test import org.junit.Test import org.junit.runner.RunWith import org.junit.runner.RunWith Loading Loading @@ -63,6 +66,21 @@ class CommunalSceneInteractorTest : SysuiTestCase() { assertThat(currentScene).isEqualTo(CommunalScenes.Communal) assertThat(currentScene).isEqualTo(CommunalScenes.Communal) } } @OptIn(ExperimentalCoroutinesApi::class) @Test fun snapToSceneWithDelay() = testScope.runTest { val currentScene by collectLastValue(underTest.currentScene) assertThat(currentScene).isEqualTo(CommunalScenes.Blank) underTest.snapToScene( CommunalScenes.Communal, ActivityTransitionAnimator.TIMINGS.totalDuration ) assertThat(currentScene).isEqualTo(CommunalScenes.Blank) advanceTimeBy(ActivityTransitionAnimator.TIMINGS.totalDuration) assertThat(currentScene).isEqualTo(CommunalScenes.Communal) } @Test @Test fun transitionProgress_fullProgress() = fun transitionProgress_fullProgress() = testScope.runTest { testScope.runTest { Loading packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSceneRepository.kt +4 −2 Original line number Original line Diff line number Diff line Loading @@ -28,6 +28,7 @@ import com.android.systemui.scene.shared.model.SceneDataSource import javax.inject.Inject import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted Loading @@ -51,7 +52,7 @@ interface CommunalSceneRepository { fun changeScene(toScene: SceneKey, transitionKey: TransitionKey? = null) fun changeScene(toScene: SceneKey, transitionKey: TransitionKey? = null) /** Immediately snaps to the desired scene. */ /** Immediately snaps to the desired scene. */ fun snapToScene(toScene: SceneKey) fun snapToScene(toScene: SceneKey, delayMillis: Long = 0) /** /** * Updates the transition state of the hub [SceneTransitionLayout]. * Updates the transition state of the hub [SceneTransitionLayout]. Loading Loading @@ -92,10 +93,11 @@ constructor( } } } } override fun snapToScene(toScene: SceneKey) { override fun snapToScene(toScene: SceneKey, delayMillis: Long) { applicationScope.launch { applicationScope.launch { // SceneTransitionLayout state updates must be triggered on the thread the STL was // SceneTransitionLayout state updates must be triggered on the thread the STL was // created on. // created on. delay(delayMillis) sceneDataSource.snapToScene(toScene) sceneDataSource.snapToScene(toScene) } } } } Loading packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractor.kt +2 −2 Original line number Original line Diff line number Diff line Loading @@ -53,8 +53,8 @@ constructor( } } /** Immediately snaps to the new scene. */ /** Immediately snaps to the new scene. */ fun snapToScene(newScene: SceneKey) { fun snapToScene(newScene: SceneKey, delayMillis: Long = 0) { communalSceneRepository.snapToScene(newScene) communalSceneRepository.snapToScene(newScene, delayMillis) } } /** /** Loading packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImpl.kt +6 −4 Original line number Original line Diff line number Diff line Loading @@ -555,7 +555,12 @@ constructor( override fun onTransitionAnimationStart(isExpandingFullyAbove: Boolean) { override fun onTransitionAnimationStart(isExpandingFullyAbove: Boolean) { super.onTransitionAnimationStart(isExpandingFullyAbove) super.onTransitionAnimationStart(isExpandingFullyAbove) if (communalHub()) { communalSceneInteractor.snapToScene( CommunalScenes.Blank, ActivityTransitionAnimator.TIMINGS.totalDuration ) } // Double check that the keyguard is still showing and not going // Double check that the keyguard is still showing and not going // away, but if so set the keyguard occluded. Typically, WM will let // away, but if so set the keyguard occluded. Typically, WM will let // KeyguardViewMediator know directly, but we're overriding that to // KeyguardViewMediator know directly, but we're overriding that to Loading @@ -581,9 +586,6 @@ constructor( // collapse the shade (or at least run the post collapse runnables) // collapse the shade (or at least run the post collapse runnables) // later on. // later on. centralSurfaces?.setIsLaunchingActivityOverLockscreen(false, false) centralSurfaces?.setIsLaunchingActivityOverLockscreen(false, false) if (communalHub()) { communalSceneInteractor.snapToScene(CommunalScenes.Blank) } delegate.onTransitionAnimationEnd(isExpandingFullyAbove) delegate.onTransitionAnimationEnd(isExpandingFullyAbove) } } Loading packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalSceneRepository.kt +11 −5 Original line number Original line Diff line number Diff line Loading @@ -6,6 +6,7 @@ import com.android.compose.animation.scene.TransitionKey import com.android.systemui.communal.shared.model.CommunalScenes import com.android.systemui.communal.shared.model.CommunalScenes import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted Loading @@ -13,20 +14,25 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch /** Fake implementation of [CommunalSceneRepository]. */ /** Fake implementation of [CommunalSceneRepository]. */ @OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class) class FakeCommunalSceneRepository( class FakeCommunalSceneRepository( applicationScope: CoroutineScope, private val applicationScope: CoroutineScope, override val currentScene: MutableStateFlow<SceneKey> = override val currentScene: MutableStateFlow<SceneKey> = MutableStateFlow(CommunalScenes.Default), MutableStateFlow(CommunalScenes.Default), ) : CommunalSceneRepository { ) : CommunalSceneRepository { override fun changeScene(toScene: SceneKey, transitionKey: TransitionKey?) = override fun changeScene(toScene: SceneKey, transitionKey: TransitionKey?) = snapToScene(toScene) snapToScene(toScene, 0) override fun snapToScene(toScene: SceneKey) { override fun snapToScene(toScene: SceneKey, delayMillis: Long) { this.currentScene.value = toScene applicationScope.launch { this._transitionState.value = flowOf(ObservableTransitionState.Idle(toScene)) delay(delayMillis) currentScene.value = toScene _transitionState.value = flowOf(ObservableTransitionState.Idle(toScene)) } } } private val defaultTransitionState = ObservableTransitionState.Idle(CommunalScenes.Default) private val defaultTransitionState = ObservableTransitionState.Idle(CommunalScenes.Default) Loading Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractorTest.kt +18 −0 Original line number Original line Diff line number Diff line Loading @@ -20,6 +20,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import androidx.test.filters.SmallTest import com.android.compose.animation.scene.ObservableTransitionState import com.android.compose.animation.scene.ObservableTransitionState import com.android.systemui.SysuiTestCase import com.android.systemui.SysuiTestCase import com.android.systemui.animation.ActivityTransitionAnimator import com.android.systemui.communal.data.repository.communalSceneRepository import com.android.systemui.communal.data.repository.communalSceneRepository import com.android.systemui.communal.domain.model.CommunalTransitionProgressModel import com.android.systemui.communal.domain.model.CommunalTransitionProgressModel import com.android.systemui.communal.shared.model.CommunalScenes import com.android.systemui.communal.shared.model.CommunalScenes Loading @@ -27,8 +28,10 @@ import com.android.systemui.coroutines.collectLastValue import com.android.systemui.kosmos.testScope import com.android.systemui.kosmos.testScope import com.android.systemui.testKosmos import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.advanceTimeBy import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest import org.junit.Test import org.junit.Test import org.junit.runner.RunWith import org.junit.runner.RunWith Loading Loading @@ -63,6 +66,21 @@ class CommunalSceneInteractorTest : SysuiTestCase() { assertThat(currentScene).isEqualTo(CommunalScenes.Communal) assertThat(currentScene).isEqualTo(CommunalScenes.Communal) } } @OptIn(ExperimentalCoroutinesApi::class) @Test fun snapToSceneWithDelay() = testScope.runTest { val currentScene by collectLastValue(underTest.currentScene) assertThat(currentScene).isEqualTo(CommunalScenes.Blank) underTest.snapToScene( CommunalScenes.Communal, ActivityTransitionAnimator.TIMINGS.totalDuration ) assertThat(currentScene).isEqualTo(CommunalScenes.Blank) advanceTimeBy(ActivityTransitionAnimator.TIMINGS.totalDuration) assertThat(currentScene).isEqualTo(CommunalScenes.Communal) } @Test @Test fun transitionProgress_fullProgress() = fun transitionProgress_fullProgress() = testScope.runTest { testScope.runTest { Loading
packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSceneRepository.kt +4 −2 Original line number Original line Diff line number Diff line Loading @@ -28,6 +28,7 @@ import com.android.systemui.scene.shared.model.SceneDataSource import javax.inject.Inject import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted Loading @@ -51,7 +52,7 @@ interface CommunalSceneRepository { fun changeScene(toScene: SceneKey, transitionKey: TransitionKey? = null) fun changeScene(toScene: SceneKey, transitionKey: TransitionKey? = null) /** Immediately snaps to the desired scene. */ /** Immediately snaps to the desired scene. */ fun snapToScene(toScene: SceneKey) fun snapToScene(toScene: SceneKey, delayMillis: Long = 0) /** /** * Updates the transition state of the hub [SceneTransitionLayout]. * Updates the transition state of the hub [SceneTransitionLayout]. Loading Loading @@ -92,10 +93,11 @@ constructor( } } } } override fun snapToScene(toScene: SceneKey) { override fun snapToScene(toScene: SceneKey, delayMillis: Long) { applicationScope.launch { applicationScope.launch { // SceneTransitionLayout state updates must be triggered on the thread the STL was // SceneTransitionLayout state updates must be triggered on the thread the STL was // created on. // created on. delay(delayMillis) sceneDataSource.snapToScene(toScene) sceneDataSource.snapToScene(toScene) } } } } Loading
packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractor.kt +2 −2 Original line number Original line Diff line number Diff line Loading @@ -53,8 +53,8 @@ constructor( } } /** Immediately snaps to the new scene. */ /** Immediately snaps to the new scene. */ fun snapToScene(newScene: SceneKey) { fun snapToScene(newScene: SceneKey, delayMillis: Long = 0) { communalSceneRepository.snapToScene(newScene) communalSceneRepository.snapToScene(newScene, delayMillis) } } /** /** Loading
packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImpl.kt +6 −4 Original line number Original line Diff line number Diff line Loading @@ -555,7 +555,12 @@ constructor( override fun onTransitionAnimationStart(isExpandingFullyAbove: Boolean) { override fun onTransitionAnimationStart(isExpandingFullyAbove: Boolean) { super.onTransitionAnimationStart(isExpandingFullyAbove) super.onTransitionAnimationStart(isExpandingFullyAbove) if (communalHub()) { communalSceneInteractor.snapToScene( CommunalScenes.Blank, ActivityTransitionAnimator.TIMINGS.totalDuration ) } // Double check that the keyguard is still showing and not going // Double check that the keyguard is still showing and not going // away, but if so set the keyguard occluded. Typically, WM will let // away, but if so set the keyguard occluded. Typically, WM will let // KeyguardViewMediator know directly, but we're overriding that to // KeyguardViewMediator know directly, but we're overriding that to Loading @@ -581,9 +586,6 @@ constructor( // collapse the shade (or at least run the post collapse runnables) // collapse the shade (or at least run the post collapse runnables) // later on. // later on. centralSurfaces?.setIsLaunchingActivityOverLockscreen(false, false) centralSurfaces?.setIsLaunchingActivityOverLockscreen(false, false) if (communalHub()) { communalSceneInteractor.snapToScene(CommunalScenes.Blank) } delegate.onTransitionAnimationEnd(isExpandingFullyAbove) delegate.onTransitionAnimationEnd(isExpandingFullyAbove) } } Loading
packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalSceneRepository.kt +11 −5 Original line number Original line Diff line number Diff line Loading @@ -6,6 +6,7 @@ import com.android.compose.animation.scene.TransitionKey import com.android.systemui.communal.shared.model.CommunalScenes import com.android.systemui.communal.shared.model.CommunalScenes import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted Loading @@ -13,20 +14,25 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch /** Fake implementation of [CommunalSceneRepository]. */ /** Fake implementation of [CommunalSceneRepository]. */ @OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class) class FakeCommunalSceneRepository( class FakeCommunalSceneRepository( applicationScope: CoroutineScope, private val applicationScope: CoroutineScope, override val currentScene: MutableStateFlow<SceneKey> = override val currentScene: MutableStateFlow<SceneKey> = MutableStateFlow(CommunalScenes.Default), MutableStateFlow(CommunalScenes.Default), ) : CommunalSceneRepository { ) : CommunalSceneRepository { override fun changeScene(toScene: SceneKey, transitionKey: TransitionKey?) = override fun changeScene(toScene: SceneKey, transitionKey: TransitionKey?) = snapToScene(toScene) snapToScene(toScene, 0) override fun snapToScene(toScene: SceneKey) { override fun snapToScene(toScene: SceneKey, delayMillis: Long) { this.currentScene.value = toScene applicationScope.launch { this._transitionState.value = flowOf(ObservableTransitionState.Idle(toScene)) delay(delayMillis) currentScene.value = toScene _transitionState.value = flowOf(ObservableTransitionState.Idle(toScene)) } } } private val defaultTransitionState = ObservableTransitionState.Idle(CommunalScenes.Default) private val defaultTransitionState = ObservableTransitionState.Idle(CommunalScenes.Default) Loading