summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt6
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/data/repository/SceneContainerRepository.kt70
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt141
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt71
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt21
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneTransitionModel.kt25
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt10
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt53
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt18
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt25
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt25
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt60
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt135
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt192
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt125
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt4
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt2
22 files changed, 643 insertions, 383 deletions
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
index 3dfdbbaaee77..f91baf298347 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
@@ -77,7 +77,7 @@ fun SceneContainer(
SceneTransitionLayout(
currentScene = currentSceneKey.toTransitionSceneKey(),
- onChangeScene = { sceneKey -> viewModel.setCurrentScene(sceneKey.toModel()) },
+ onChangeScene = viewModel::onSceneChanged,
transitions = transitions {},
state = state,
modifier = modifier.fillMaxSize(),
@@ -154,3 +154,7 @@ private fun UserAction.toTransitionUserAction(): SceneTransitionUserAction {
is UserAction.Back -> Back
}
}
+
+private fun SceneContainerViewModel.onSceneChanged(sceneKey: SceneTransitionSceneKey) {
+ onSceneChanged(sceneKey.toModel())
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index aff25914ec36..57a859126db2 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -476,18 +476,16 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
if (mFeatureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
// When the scene framework transitions from bouncer to gone, we dismiss the keyguard.
mSceneTransitionCollectionJob = mJavaAdapter.get().alwaysCollectFlow(
- mSceneInteractor.get().getTransitions(),
- sceneTransitionModel -> {
- if (sceneTransitionModel != null
- && sceneTransitionModel.getFrom() == SceneKey.Bouncer.INSTANCE
- && sceneTransitionModel.getTo() == SceneKey.Gone.INSTANCE) {
- final int selectedUserId = mUserInteractor.getSelectedUserId();
- showNextSecurityScreenOrFinish(
- /* authenticated= */ true,
- selectedUserId,
- /* bypassSecondaryLockScreen= */ true,
- mSecurityModel.getSecurityMode(selectedUserId));
- }
+ mSceneInteractor.get().finishedSceneTransitions(
+ /* from= */ SceneKey.Bouncer.INSTANCE,
+ /* to= */ SceneKey.Gone.INSTANCE),
+ unused -> {
+ final int selectedUserId = mUserInteractor.getSelectedUserId();
+ showNextSecurityScreenOrFinish(
+ /* authenticated= */ true,
+ selectedUserId,
+ /* bypassSecondaryLockScreen= */ true,
+ mSecurityModel.getSecurityMode(selectedUserId));
});
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
index ffcae1cacb00..1bf3a9ead08e 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
@@ -116,12 +116,12 @@ constructor(
repository.setMessage(
message ?: promptMessage(authenticationInteractor.getAuthenticationMethod())
)
- sceneInteractor.setCurrentScene(
+ sceneInteractor.changeScene(
scene = SceneModel(SceneKey.Bouncer),
loggingReason = "request to unlock device while authentication required",
)
} else {
- sceneInteractor.setCurrentScene(
+ sceneInteractor.changeScene(
scene = SceneModel(SceneKey.Gone),
loggingReason = "request to unlock device while authentication isn't required",
)
@@ -169,7 +169,7 @@ constructor(
authenticationInteractor.authenticate(input, tryAutoConfirm) ?: return null
if (isAuthenticated) {
- sceneInteractor.setCurrentScene(
+ sceneInteractor.changeScene(
scene = SceneModel(SceneKey.Gone),
loggingReason = "successful authentication",
)
diff --git a/packages/SystemUI/src/com/android/systemui/scene/data/repository/SceneContainerRepository.kt b/packages/SystemUI/src/com/android/systemui/scene/data/repository/SceneContainerRepository.kt
index fee3960ff0e1..350fa38f2052 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/data/repository/SceneContainerRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/data/repository/SceneContainerRepository.kt
@@ -18,50 +18,49 @@
package com.android.systemui.scene.data.repository
+import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.scene.shared.model.ObservableTransitionState
import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.shared.model.SceneModel
-import com.android.systemui.scene.shared.model.SceneTransitionModel
import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.stateIn
/** Source of truth for scene framework application state. */
class SceneContainerRepository
@Inject
constructor(
+ @Application applicationScope: CoroutineScope,
private val config: SceneContainerConfig,
) {
+ private val _desiredScene = MutableStateFlow(SceneModel(config.initialSceneKey))
+ val desiredScene: StateFlow<SceneModel> = _desiredScene.asStateFlow()
private val _isVisible = MutableStateFlow(true)
val isVisible: StateFlow<Boolean> = _isVisible.asStateFlow()
- private val _currentScene = MutableStateFlow(SceneModel(config.initialSceneKey))
- val currentScene: StateFlow<SceneModel> = _currentScene.asStateFlow()
-
- private val transitionState = MutableStateFlow<Flow<ObservableTransitionState>?>(null)
- val transitionProgress: Flow<Float> =
- transitionState.flatMapLatest { observableTransitionStateFlow ->
- observableTransitionStateFlow?.flatMapLatest { observableTransitionState ->
- when (observableTransitionState) {
- is ObservableTransitionState.Idle -> flowOf(1f)
- is ObservableTransitionState.Transition -> observableTransitionState.progress
- }
- }
- ?: flowOf(1f)
- }
-
- private val _transitions = MutableStateFlow<SceneTransitionModel?>(null)
- val transitions: StateFlow<SceneTransitionModel?> = _transitions.asStateFlow()
+ private val defaultTransitionState = ObservableTransitionState.Idle(config.initialSceneKey)
+ private val _transitionState = MutableStateFlow<Flow<ObservableTransitionState>?>(null)
+ val transitionState: StateFlow<ObservableTransitionState> =
+ _transitionState
+ .flatMapLatest { innerFlowOrNull -> innerFlowOrNull ?: flowOf(defaultTransitionState) }
+ .stateIn(
+ scope = applicationScope,
+ started = SharingStarted.Eagerly,
+ initialValue = defaultTransitionState,
+ )
/**
- * Returns the keys to all scenes in the container with the given name.
+ * Returns the keys to all scenes in the container.
*
* The scenes will be sorted in z-order such that the last one is the one that should be
* rendered on top of all previous ones.
@@ -70,40 +69,19 @@ constructor(
return config.sceneKeys
}
- /** Sets the current scene in the container with the given name. */
- fun setCurrentScene(scene: SceneModel) {
+ fun setDesiredScene(scene: SceneModel) {
check(allSceneKeys().contains(scene.key)) {
"""
- Cannot set current scene key to "${scene.key}". The configuration does not contain a
- scene with that key.
- """
- .trimIndent()
- }
-
- _currentScene.value = scene
- }
-
- /** Sets the scene transition in the container with the given name. */
- fun setSceneTransition(from: SceneKey, to: SceneKey) {
- check(allSceneKeys().contains(from)) {
- """
- Cannot set current scene key to "$from". The configuration does not contain a scene
- with that key.
- """
- .trimIndent()
- }
- check(allSceneKeys().contains(to)) {
- """
- Cannot set current scene key to "$to". The configuration does not contain a scene
- with that key.
+ Cannot set the desired scene key to "${scene.key}". The configuration does not
+ contain a scene with that key.
"""
.trimIndent()
}
- _transitions.value = SceneTransitionModel(from = from, to = to)
+ _desiredScene.value = scene
}
- /** Sets whether the container with the given name is visible. */
+ /** Sets whether the container is visible. */
fun setVisible(isVisible: Boolean) {
_isVisible.value = isVisible
}
@@ -114,6 +92,6 @@ constructor(
* Note that you must call is with `null` when the UI is done or risk a memory leak.
*/
fun setTransitionState(transitionState: Flow<ObservableTransitionState>?) {
- this.transitionState.value = transitionState
+ _transitionState.value = transitionState
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt
index 64715bc26674..cf7abdd34b70 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt
@@ -23,12 +23,15 @@ import com.android.systemui.scene.shared.model.ObservableTransitionState
import com.android.systemui.scene.shared.model.RemoteUserInput
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.shared.model.SceneModel
-import com.android.systemui.scene.shared.model.SceneTransitionModel
+import com.android.systemui.util.kotlin.pairwise
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.mapNotNull
/**
* Generic business logic and app state accessors for the scene framework.
@@ -46,7 +49,54 @@ constructor(
) {
/**
- * Returns the keys of all scenes in the container with the given name.
+ * The currently *desired* scene.
+ *
+ * **Important:** this value will _commonly be different_ from what is being rendered in the UI,
+ * by design.
+ *
+ * There are two intended sources for this value:
+ * 1. Programmatic requests to transition to another scene (calls to [changeScene]).
+ * 2. Reports from the UI about completing a transition to another scene (calls to
+ * [onSceneChanged]).
+ *
+ * Both the sources above cause the value of this flow to change; however, they cause mismatches
+ * in different ways.
+ *
+ * **Updates from programmatic transitions**
+ *
+ * When an external bit of code asks the framework to switch to another scene, the value here
+ * will update immediately. Downstream, the UI will detect this change and initiate the
+ * transition animation. As the transition animation progresses, a threshold will be reached, at
+ * which point the UI and the state here will match each other.
+ *
+ * **Updates from the UI**
+ *
+ * When the user interacts with the UI, the UI runs a transition animation that tracks the user
+ * pointer (for example, the user's finger). During this time, the state value here and what the
+ * UI shows will likely not match. Once/if a threshold is met, the UI reports it and commits the
+ * change, making the value here match the UI again.
+ */
+ val desiredScene: StateFlow<SceneModel> = repository.desiredScene
+
+ /**
+ * The current state of the transition.
+ *
+ * Consumers should use this state to know:
+ * 1. Whether there is an ongoing transition or if the system is at rest.
+ * 2. When transitioning, which scenes are being transitioned between.
+ * 3. When transitioning, what the progress of the transition is.
+ */
+ val transitionState: StateFlow<ObservableTransitionState> = repository.transitionState
+
+ /** Whether the scene container is visible. */
+ val isVisible: StateFlow<Boolean> = repository.isVisible
+
+ private val _remoteUserInput: MutableStateFlow<RemoteUserInput?> = MutableStateFlow(null)
+ /** A flow of motion events originating from outside of the scene framework. */
+ val remoteUserInput: StateFlow<RemoteUserInput?> = _remoteUserInput.asStateFlow()
+
+ /**
+ * Returns the keys of all scenes in the container.
*
* The scenes will be sorted in z-order such that the last one is the one that should be
* rendered on top of all previous ones.
@@ -55,26 +105,20 @@ constructor(
return repository.allSceneKeys()
}
- /** Sets the scene in the container with the given name. */
- fun setCurrentScene(scene: SceneModel, loggingReason: String) {
- val currentSceneKey = repository.currentScene.value.key
- if (currentSceneKey == scene.key) {
- return
- }
-
- logger.logSceneChange(
- from = currentSceneKey,
- to = scene.key,
- reason = loggingReason,
- )
- repository.setCurrentScene(scene)
- repository.setSceneTransition(from = currentSceneKey, to = scene.key)
+ /**
+ * Requests a scene change to the given scene.
+ *
+ * The change is animated. Therefore, while the value in [desiredScene] will update immediately,
+ * it will be some time before the UI will switch to the desired scene. The scene change
+ * requested is remembered here but served by the UI layer, which will start a transition
+ * animation. Once enough of the transition has occurred, the system will come into agreement
+ * between the [desiredScene] and the UI.
+ */
+ fun changeScene(scene: SceneModel, loggingReason: String) {
+ updateDesiredScene(scene, loggingReason, logger::logSceneChangeRequested)
}
- /** The current scene in the container with the given name. */
- val currentScene: StateFlow<SceneModel> = repository.currentScene
-
- /** Sets the visibility of the container with the given name. */
+ /** Sets the visibility of the container. */
fun setVisible(isVisible: Boolean, loggingReason: String) {
val wasVisible = repository.isVisible.value
if (wasVisible == isVisible) {
@@ -89,9 +133,6 @@ constructor(
return repository.setVisible(isVisible)
}
- /** Whether the container with the given name is visible. */
- val isVisible: StateFlow<Boolean> = repository.isVisible
-
/**
* Binds the given flow so the system remembers it.
*
@@ -101,23 +142,53 @@ constructor(
repository.setTransitionState(transitionState)
}
- /** Progress of the transition into the current scene in the container with the given name. */
- val transitionProgress: Flow<Float> = repository.transitionProgress
-
/**
- * Scene transitions as pairs of keys. A new value is emitted exactly once, each time a scene
- * transition occurs. The flow begins with a `null` value at first, because the initial scene is
- * not something that we transition to from another scene.
+ * Returns a stream of events that emits one [Unit] every time the framework transitions from
+ * [from] to [to].
*/
- val transitions: StateFlow<SceneTransitionModel?> = repository.transitions
-
- private val _remoteUserInput: MutableStateFlow<RemoteUserInput?> = MutableStateFlow(null)
-
- /** A flow of motion events originating from outside of the scene framework. */
- val remoteUserInput: StateFlow<RemoteUserInput?> = _remoteUserInput.asStateFlow()
+ fun finishedSceneTransitions(from: SceneKey, to: SceneKey): Flow<Unit> {
+ return transitionState
+ .mapNotNull { it as? ObservableTransitionState.Idle }
+ .map { idleState -> idleState.scene }
+ .distinctUntilChanged()
+ .pairwise()
+ .mapNotNull { (previousSceneKey, currentSceneKey) ->
+ Unit.takeIf { previousSceneKey == from && currentSceneKey == to }
+ }
+ }
/** Handles a remote user input. */
fun onRemoteUserInput(input: RemoteUserInput) {
_remoteUserInput.value = input
}
+
+ /**
+ * Notifies that the UI has transitioned sufficiently to the given scene.
+ *
+ * *Not intended for external use!*
+ *
+ * Once a transition between one scene and another passes a threshold, the UI invokes this
+ * method to report it, updating the value in [desiredScene] to match what the UI shows.
+ */
+ internal fun onSceneChanged(scene: SceneModel, loggingReason: String) {
+ updateDesiredScene(scene, loggingReason, logger::logSceneChangeCommitted)
+ }
+
+ private fun updateDesiredScene(
+ scene: SceneModel,
+ loggingReason: String,
+ log: (from: SceneKey, to: SceneKey, loggingReason: String) -> Unit,
+ ) {
+ val currentSceneKey = desiredScene.value.key
+ if (currentSceneKey == scene.key) {
+ return
+ }
+
+ log(
+ /* from= */ currentSceneKey,
+ /* to= */ scene.key,
+ /* loggingReason= */ loggingReason,
+ )
+ repository.setDesiredScene(scene)
+ }
}
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 bd233f80b47b..afefccb27214 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
@@ -30,6 +30,7 @@ import com.android.systemui.model.SysUiState
import com.android.systemui.model.updateFlags
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.logger.SceneLogger
+import com.android.systemui.scene.shared.model.ObservableTransitionState
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.shared.model.SceneModel
import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING
@@ -40,8 +41,8 @@ import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_B
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.distinctUntilChanged
-import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.launch
/**
@@ -73,14 +74,31 @@ constructor(
}
}
- /** Updates the visibility of the scene container based on the current scene. */
+ /** Updates the visibility of the scene container. */
private fun hydrateVisibility() {
applicationScope.launch {
- sceneInteractor.currentScene
- .map { it.key }
+ sceneInteractor.transitionState
+ .mapNotNull { state ->
+ when (state) {
+ is ObservableTransitionState.Idle -> {
+ if (state.scene != SceneKey.Gone) {
+ true to "scene is not Gone"
+ } else {
+ false to "scene is Gone"
+ }
+ }
+ is ObservableTransitionState.Transition -> {
+ if (state.fromScene == SceneKey.Gone) {
+ true to "scene transitioning away from Gone"
+ } else {
+ null
+ }
+ }
+ }
+ }
.distinctUntilChanged()
- .collect { sceneKey ->
- sceneInteractor.setVisible(sceneKey != SceneKey.Gone, "scene is $sceneKey")
+ .collect { (isVisible, loggingReason) ->
+ sceneInteractor.setVisible(isVisible, loggingReason)
}
}
}
@@ -89,43 +107,55 @@ constructor(
private fun automaticallySwitchScenes() {
applicationScope.launch {
authenticationInteractor.isUnlocked
- .map { isUnlocked ->
- val currentSceneKey = sceneInteractor.currentScene.value.key
+ .mapNotNull { isUnlocked ->
+ val renderedScenes =
+ when (val transitionState = sceneInteractor.transitionState.value) {
+ is ObservableTransitionState.Idle -> setOf(transitionState.scene)
+ is ObservableTransitionState.Transition ->
+ setOf(
+ transitionState.progress,
+ transitionState.toScene,
+ )
+ }
val isBypassEnabled = authenticationInteractor.isBypassEnabled()
when {
isUnlocked ->
- when (currentSceneKey) {
+ when {
// When the device becomes unlocked in Bouncer, go to Gone.
- is SceneKey.Bouncer ->
+ renderedScenes.contains(SceneKey.Bouncer) ->
SceneKey.Gone to "device unlocked in Bouncer scene"
+
// When the device becomes unlocked in Lockscreen, go to Gone if
// bypass is enabled.
- is SceneKey.Lockscreen ->
+ renderedScenes.contains(SceneKey.Lockscreen) ->
if (isBypassEnabled) {
SceneKey.Gone to
"device unlocked in Lockscreen scene with bypass"
} else {
null
}
+
// We got unlocked while on a scene that's not Lockscreen or
// Bouncer, no need to change scenes.
else -> null
}
+
// When the device becomes locked, to Lockscreen.
!isUnlocked ->
- when (currentSceneKey) {
+ when {
// Already on lockscreen or bouncer, no need to change scenes.
- is SceneKey.Lockscreen,
- is SceneKey.Bouncer -> null
+ renderedScenes.contains(SceneKey.Lockscreen) ||
+ renderedScenes.contains(SceneKey.Bouncer) -> null
+
// We got locked while on a scene that's not Lockscreen or Bouncer,
// go to Lockscreen.
else ->
- SceneKey.Lockscreen to "device locked in $currentSceneKey scene"
+ SceneKey.Lockscreen to
+ "device locked in non-Lockscreen and non-Bouncer scene"
}
else -> null
}
}
- .filterNotNull()
.collect { (targetSceneKey, loggingReason) ->
switchToScene(
targetSceneKey = targetSceneKey,
@@ -143,7 +173,7 @@ constructor(
WakefulnessState.STARTING_TO_SLEEP -> {
switchToScene(
targetSceneKey = SceneKey.Lockscreen,
- loggingReason = "device is asleep",
+ loggingReason = "device is starting to sleep",
)
}
WakefulnessState.STARTING_TO_WAKE -> {
@@ -165,8 +195,9 @@ constructor(
/** Keeps [SysUiState] up-to-date */
private fun hydrateSystemUiState() {
applicationScope.launch {
- sceneInteractor.currentScene
- .map { it.key }
+ sceneInteractor.transitionState
+ .mapNotNull { it as? ObservableTransitionState.Idle }
+ .map { it.scene }
.distinctUntilChanged()
.collect { sceneKey ->
sysUiState.updateFlags(
@@ -183,7 +214,7 @@ constructor(
}
private fun switchToScene(targetSceneKey: SceneKey, loggingReason: String) {
- sceneInteractor.setCurrentScene(
+ sceneInteractor.changeScene(
scene = SceneModel(targetSceneKey),
loggingReason = loggingReason,
)
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt
index 0adbd5ad19a7..62136dcd8e1d 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt
@@ -37,7 +37,7 @@ class SceneLogger @Inject constructor(@SceneFrameworkLog private val logBuffer:
)
}
- fun logSceneChange(
+ fun logSceneChangeRequested(
from: SceneKey,
to: SceneKey,
reason: String,
@@ -50,7 +50,24 @@ class SceneLogger @Inject constructor(@SceneFrameworkLog private val logBuffer:
str2 = to.toString()
str3 = reason
},
- messagePrinter = { "$str1 → $str2, reason: $str3" },
+ messagePrinter = { "Scene change requested: $str1 → $str2, reason: $str3" },
+ )
+ }
+
+ fun logSceneChangeCommitted(
+ from: SceneKey,
+ to: SceneKey,
+ reason: String,
+ ) {
+ logBuffer.log(
+ tag = TAG,
+ level = LogLevel.INFO,
+ messageInitializer = {
+ str1 = from.toString()
+ str2 = to.toString()
+ str3 = reason
+ },
+ messagePrinter = { "Scene change committed: $str1 → $str2, reason: $str3" },
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneTransitionModel.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneTransitionModel.kt
deleted file mode 100644
index c8f46a72d64f..000000000000
--- a/packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneTransitionModel.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2023 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.scene.shared.model
-
-/** Models a transition between two scenes. */
-data class SceneTransitionModel(
- /** The scene we transitioned away from. */
- val from: SceneKey,
- /** The scene we transitioned into. */
- val to: SceneKey,
-)
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
index b4ebaece21f1..3e9bbe464e2c 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
@@ -45,15 +45,15 @@ constructor(
*/
val allSceneKeys: List<SceneKey> = interactor.allSceneKeys()
- /** The current scene. */
- val currentScene: StateFlow<SceneModel> = interactor.currentScene
+ /** The scene that should be rendered. */
+ val currentScene: StateFlow<SceneModel> = interactor.desiredScene
/** Whether the container is visible. */
val isVisible: StateFlow<Boolean> = interactor.isVisible
- /** Requests a transition to the scene with the given key. */
- fun setCurrentScene(scene: SceneModel) {
- interactor.setCurrentScene(
+ /** Notifies that the UI has transitioned sufficiently to the given scene. */
+ fun onSceneChanged(scene: SceneModel) {
+ interactor.onSceneChanged(
scene = scene,
loggingReason = SCENE_TRANSITION_LOGGING_REASON,
)
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
index efb981e5cebb..a6bd9363a08b 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
@@ -50,6 +50,7 @@ import com.android.systemui.plugins.ActivityStarter.OnDismissAction
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.scene.SceneTestUtils
import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.model.ObservableTransitionState
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.shared.model.SceneModel
import com.android.systemui.statusbar.policy.ConfigurationController
@@ -66,6 +67,8 @@ import com.google.common.truth.Truth
import java.util.Optional
import junit.framework.Assert
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -139,6 +142,7 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() {
private lateinit var testableResources: TestableResources
private lateinit var sceneTestUtils: SceneTestUtils
private lateinit var sceneInteractor: SceneInteractor
+ private lateinit var sceneTransitionStateFlow: MutableStateFlow<ObservableTransitionState>
private lateinit var underTest: KeyguardSecurityContainerController
@@ -198,6 +202,9 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() {
whenever(userInteractor.getSelectedUserId()).thenReturn(TARGET_USER_ID)
sceneTestUtils = SceneTestUtils(this)
sceneInteractor = sceneTestUtils.sceneInteractor()
+ sceneTransitionStateFlow =
+ MutableStateFlow(ObservableTransitionState.Idle(SceneKey.Lockscreen))
+ sceneInteractor.setTransitionState(sceneTransitionStateFlow)
underTest =
KeyguardSecurityContainerController(
@@ -733,20 +740,39 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() {
// is
// not enough to trigger a dismissal of the keyguard.
underTest.onViewAttached()
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer, null), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer, null), "reason")
+ sceneTransitionStateFlow.value =
+ ObservableTransitionState.Transition(
+ SceneKey.Lockscreen,
+ SceneKey.Bouncer,
+ flowOf(.5f)
+ )
+ runCurrent()
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer, null), "reason")
+ sceneTransitionStateFlow.value = ObservableTransitionState.Idle(SceneKey.Bouncer)
runCurrent()
verify(viewMediatorCallback, never()).keyguardDone(anyBoolean(), anyInt())
// While listening, going from the bouncer scene to the gone scene, does dismiss the
// keyguard.
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Gone, null), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Gone, null), "reason")
+ sceneTransitionStateFlow.value =
+ ObservableTransitionState.Transition(SceneKey.Bouncer, SceneKey.Gone, flowOf(.5f))
+ runCurrent()
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Gone, null), "reason")
+ sceneTransitionStateFlow.value = ObservableTransitionState.Idle(SceneKey.Gone)
runCurrent()
verify(viewMediatorCallback).keyguardDone(anyBoolean(), anyInt())
// While listening, moving back to the bouncer scene does not dismiss the keyguard
// again.
clearInvocations(viewMediatorCallback)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer, null), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer, null), "reason")
+ sceneTransitionStateFlow.value =
+ ObservableTransitionState.Transition(SceneKey.Gone, SceneKey.Bouncer, flowOf(.5f))
+ runCurrent()
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer, null), "reason")
+ sceneTransitionStateFlow.value = ObservableTransitionState.Idle(SceneKey.Bouncer)
runCurrent()
verify(viewMediatorCallback, never()).keyguardDone(anyBoolean(), anyInt())
@@ -754,12 +780,22 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() {
// scene
// does not dismiss the keyguard while we're not listening.
underTest.onViewDetached()
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Gone, null), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Gone, null), "reason")
+ sceneTransitionStateFlow.value =
+ ObservableTransitionState.Transition(SceneKey.Bouncer, SceneKey.Gone, flowOf(.5f))
+ runCurrent()
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Gone, null), "reason")
+ sceneTransitionStateFlow.value = ObservableTransitionState.Idle(SceneKey.Gone)
runCurrent()
verify(viewMediatorCallback, never()).keyguardDone(anyBoolean(), anyInt())
// While not listening, moving back to the bouncer does not dismiss the keyguard.
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer, null), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer, null), "reason")
+ sceneTransitionStateFlow.value =
+ ObservableTransitionState.Transition(SceneKey.Gone, SceneKey.Bouncer, flowOf(.5f))
+ runCurrent()
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer, null), "reason")
+ sceneTransitionStateFlow.value = ObservableTransitionState.Idle(SceneKey.Bouncer)
runCurrent()
verify(viewMediatorCallback, never()).keyguardDone(anyBoolean(), anyInt())
@@ -767,7 +803,12 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() {
// gone
// scene now does dismiss the keyguard again.
underTest.onViewAttached()
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Gone, null), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Gone, null), "reason")
+ sceneTransitionStateFlow.value =
+ ObservableTransitionState.Transition(SceneKey.Bouncer, SceneKey.Gone, flowOf(.5f))
+ runCurrent()
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Gone, null), "reason")
+ sceneTransitionStateFlow.value = ObservableTransitionState.Idle(SceneKey.Gone)
runCurrent()
verify(viewMediatorCallback).keyguardDone(anyBoolean(), anyInt())
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt
index df4d2225f459..86e0c751085b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt
@@ -70,7 +70,7 @@ class BouncerInteractorTest : SysuiTestCase() {
@Test
fun pinAuthMethod() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(underTest.message)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
@@ -102,7 +102,7 @@ class BouncerInteractorTest : SysuiTestCase() {
@Test
fun pinAuthMethod_tryAutoConfirm_withAutoConfirmPin() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(underTest.message)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
@@ -139,7 +139,7 @@ class BouncerInteractorTest : SysuiTestCase() {
@Test
fun pinAuthMethod_tryAutoConfirm_withoutAutoConfirmPin() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(underTest.message)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
@@ -169,7 +169,7 @@ class BouncerInteractorTest : SysuiTestCase() {
@Test
fun passwordAuthMethod() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(underTest.message)
utils.authenticationRepository.setAuthenticationMethod(
AuthenticationMethodModel.Password
@@ -202,7 +202,7 @@ class BouncerInteractorTest : SysuiTestCase() {
@Test
fun patternAuthMethod() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(underTest.message)
utils.authenticationRepository.setAuthenticationMethod(
AuthenticationMethodModel.Pattern
@@ -236,7 +236,7 @@ class BouncerInteractorTest : SysuiTestCase() {
@Test
fun showOrUnlockDevice_notLocked_switchesToGoneScene() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(true)
runCurrent()
@@ -249,7 +249,7 @@ class BouncerInteractorTest : SysuiTestCase() {
@Test
fun showOrUnlockDevice_authMethodNotSecure_switchesToGoneScene() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.None)
utils.authenticationRepository.setLockscreenEnabled(true)
utils.authenticationRepository.setUnlocked(false)
@@ -262,7 +262,7 @@ class BouncerInteractorTest : SysuiTestCase() {
@Test
fun showOrUnlockDevice_customMessageShown() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(underTest.message)
utils.authenticationRepository.setAuthenticationMethod(
AuthenticationMethodModel.Password
@@ -283,7 +283,7 @@ class BouncerInteractorTest : SysuiTestCase() {
val isThrottled by collectLastValue(underTest.isThrottled)
val throttling by collectLastValue(underTest.throttling)
val message by collectLastValue(underTest.message)
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
runCurrent()
underTest.showOrUnlockDevice()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt
index 4e9fe8d91da1..4380af80efbd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt
@@ -73,14 +73,15 @@ class PasswordBouncerViewModelTest : SysuiTestCase() {
@Test
fun onShown() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(bouncerViewModel.message)
val password by collectLastValue(underTest.password)
utils.authenticationRepository.setAuthenticationMethod(
AuthenticationMethodModel.Password
)
utils.authenticationRepository.setUnlocked(false)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
@@ -93,14 +94,15 @@ class PasswordBouncerViewModelTest : SysuiTestCase() {
@Test
fun onPasswordInputChanged() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(bouncerViewModel.message)
val password by collectLastValue(underTest.password)
utils.authenticationRepository.setAuthenticationMethod(
AuthenticationMethodModel.Password
)
utils.authenticationRepository.setUnlocked(false)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
runCurrent()
@@ -115,12 +117,13 @@ class PasswordBouncerViewModelTest : SysuiTestCase() {
@Test
fun onAuthenticateKeyPressed_whenCorrect() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
utils.authenticationRepository.setAuthenticationMethod(
AuthenticationMethodModel.Password
)
utils.authenticationRepository.setUnlocked(false)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
underTest.onPasswordInputChanged("password")
@@ -133,14 +136,15 @@ class PasswordBouncerViewModelTest : SysuiTestCase() {
@Test
fun onAuthenticateKeyPressed_whenWrong() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(bouncerViewModel.message)
val password by collectLastValue(underTest.password)
utils.authenticationRepository.setAuthenticationMethod(
AuthenticationMethodModel.Password
)
utils.authenticationRepository.setUnlocked(false)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
underTest.onPasswordInputChanged("wrong")
@@ -155,14 +159,15 @@ class PasswordBouncerViewModelTest : SysuiTestCase() {
@Test
fun onAuthenticateKeyPressed_correctAfterWrong() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(bouncerViewModel.message)
val password by collectLastValue(underTest.password)
utils.authenticationRepository.setAuthenticationMethod(
AuthenticationMethodModel.Password
)
utils.authenticationRepository.setUnlocked(false)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
underTest.onPasswordInputChanged("wrong")
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt
index 000200c606b3..ea2cad2ab517 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt
@@ -76,7 +76,7 @@ class PatternBouncerViewModelTest : SysuiTestCase() {
@Test
fun onShown() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(bouncerViewModel.message)
val selectedDots by collectLastValue(underTest.selectedDots)
val currentDot by collectLastValue(underTest.currentDot)
@@ -84,7 +84,8 @@ class PatternBouncerViewModelTest : SysuiTestCase() {
AuthenticationMethodModel.Pattern
)
utils.authenticationRepository.setUnlocked(false)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
@@ -98,7 +99,7 @@ class PatternBouncerViewModelTest : SysuiTestCase() {
@Test
fun onDragStart() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(bouncerViewModel.message)
val selectedDots by collectLastValue(underTest.selectedDots)
val currentDot by collectLastValue(underTest.currentDot)
@@ -106,7 +107,8 @@ class PatternBouncerViewModelTest : SysuiTestCase() {
AuthenticationMethodModel.Pattern
)
utils.authenticationRepository.setUnlocked(false)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
runCurrent()
@@ -122,14 +124,15 @@ class PatternBouncerViewModelTest : SysuiTestCase() {
@Test
fun onDragEnd_whenCorrect() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val selectedDots by collectLastValue(underTest.selectedDots)
val currentDot by collectLastValue(underTest.currentDot)
utils.authenticationRepository.setAuthenticationMethod(
AuthenticationMethodModel.Pattern
)
utils.authenticationRepository.setUnlocked(false)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
underTest.onDragStart()
@@ -169,7 +172,7 @@ class PatternBouncerViewModelTest : SysuiTestCase() {
@Test
fun onDragEnd_whenWrong() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(bouncerViewModel.message)
val selectedDots by collectLastValue(underTest.selectedDots)
val currentDot by collectLastValue(underTest.currentDot)
@@ -177,7 +180,8 @@ class PatternBouncerViewModelTest : SysuiTestCase() {
AuthenticationMethodModel.Pattern
)
utils.authenticationRepository.setUnlocked(false)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
underTest.onDragStart()
@@ -201,7 +205,7 @@ class PatternBouncerViewModelTest : SysuiTestCase() {
@Test
fun onDragEnd_correctAfterWrong() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(bouncerViewModel.message)
val selectedDots by collectLastValue(underTest.selectedDots)
val currentDot by collectLastValue(underTest.currentDot)
@@ -209,7 +213,8 @@ class PatternBouncerViewModelTest : SysuiTestCase() {
AuthenticationMethodModel.Pattern
)
utils.authenticationRepository.setUnlocked(false)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
underTest.onDragStart()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt
index 4b667c393b62..531f86abdfbc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt
@@ -76,11 +76,13 @@ class PinBouncerViewModelTest : SysuiTestCase() {
@Test
fun onShown() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(bouncerViewModel.message)
val pin by collectLastValue(underTest.pinInput.map { it.getPin() })
utils.authenticationRepository.setUnlocked(false)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
+
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
@@ -93,12 +95,14 @@ class PinBouncerViewModelTest : SysuiTestCase() {
@Test
fun onPinButtonClicked() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(bouncerViewModel.message)
val pin by collectLastValue(underTest.pinInput.map { it.getPin() })
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
+
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
runCurrent()
@@ -113,12 +117,14 @@ class PinBouncerViewModelTest : SysuiTestCase() {
@Test
fun onBackspaceButtonClicked() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(bouncerViewModel.message)
val pin by collectLastValue(underTest.pinInput.map { it.getPin() })
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
+
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
runCurrent()
@@ -135,11 +141,13 @@ class PinBouncerViewModelTest : SysuiTestCase() {
@Test
fun onPinEdit() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val pin by collectLastValue(underTest.pinInput.map { it.getPin() })
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
+
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
@@ -157,12 +165,14 @@ class PinBouncerViewModelTest : SysuiTestCase() {
@Test
fun onBackspaceButtonLongPressed() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(bouncerViewModel.message)
val pin by collectLastValue(underTest.pinInput.map { it.getPin() })
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
+
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
runCurrent()
@@ -181,10 +191,12 @@ class PinBouncerViewModelTest : SysuiTestCase() {
@Test
fun onAuthenticateButtonClicked_whenCorrect() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
+
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
FakeAuthenticationRepository.DEFAULT_PIN.forEach { digit ->
@@ -199,12 +211,14 @@ class PinBouncerViewModelTest : SysuiTestCase() {
@Test
fun onAuthenticateButtonClicked_whenWrong() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(bouncerViewModel.message)
val pin by collectLastValue(underTest.pinInput.map { it.getPin() })
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
+
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
underTest.onPinButtonClicked(1)
@@ -223,12 +237,14 @@ class PinBouncerViewModelTest : SysuiTestCase() {
@Test
fun onAuthenticateButtonClicked_correctAfterWrong() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(bouncerViewModel.message)
val pin by collectLastValue(underTest.pinInput.map { it.getPin() })
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
+
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
underTest.onPinButtonClicked(1)
@@ -255,11 +271,13 @@ class PinBouncerViewModelTest : SysuiTestCase() {
@Test
fun onAutoConfirm_whenCorrect() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
utils.authenticationRepository.setAutoConfirmEnabled(true)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
+
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
FakeAuthenticationRepository.DEFAULT_PIN.forEach { digit ->
@@ -272,13 +290,15 @@ class PinBouncerViewModelTest : SysuiTestCase() {
@Test
fun onAutoConfirm_whenWrong() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(bouncerViewModel.message)
val pin by collectLastValue(underTest.pinInput.map { it.getPin() })
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
utils.authenticationRepository.setAutoConfirmEnabled(true)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
+
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
FakeAuthenticationRepository.DEFAULT_PIN.dropLast(1).forEach { digit ->
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt
index 834b9c526669..45d7a5ebb60a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt
@@ -107,7 +107,7 @@ class LockscreenSceneViewModelTest : SysuiTestCase() {
@Test
fun onLockButtonClicked_deviceLockedSecurely_switchesToBouncer() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
runCurrent()
@@ -120,7 +120,7 @@ class LockscreenSceneViewModelTest : SysuiTestCase() {
@Test
fun onContentClicked_deviceUnlocked_switchesToGone() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(true)
runCurrent()
@@ -133,7 +133,7 @@ class LockscreenSceneViewModelTest : SysuiTestCase() {
@Test
fun onContentClicked_deviceLockedSecurely_switchesToBouncer() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
runCurrent()
@@ -146,7 +146,7 @@ class LockscreenSceneViewModelTest : SysuiTestCase() {
@Test
fun onLockButtonClicked_deviceUnlocked_switchesToGone() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(true)
runCurrent()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
index bb365d05e9e2..2cb02058ab03 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
@@ -56,7 +56,7 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() {
@Test
fun onContentClicked_deviceUnlocked_switchesToGone() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(true)
runCurrent()
@@ -69,7 +69,7 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() {
@Test
fun onContentClicked_deviceLockedSecurely_switchesToBouncer() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
runCurrent()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt
index 56e3e9649fe7..181f8a7e3003 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt
@@ -25,7 +25,6 @@ import com.android.systemui.scene.SceneTestUtils
import com.android.systemui.scene.shared.model.ObservableTransitionState
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.shared.model.SceneModel
-import com.android.systemui.scene.shared.model.SceneTransitionModel
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
@@ -39,6 +38,7 @@ import org.junit.runners.JUnit4
class SceneContainerRepositoryTest : SysuiTestCase() {
private val utils = SceneTestUtils(this)
+ private val testScope = utils.testScope
@Test
fun allSceneKeys() {
@@ -56,97 +56,82 @@ class SceneContainerRepositoryTest : SysuiTestCase() {
}
@Test
- fun currentScene() = runTest {
- val underTest = utils.fakeSceneContainerRepository()
- val currentScene by collectLastValue(underTest.currentScene)
- assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Lockscreen))
+ fun desiredScene() =
+ testScope.runTest {
+ val underTest = utils.fakeSceneContainerRepository()
+ val currentScene by collectLastValue(underTest.desiredScene)
+ assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Lockscreen))
- underTest.setCurrentScene(SceneModel(SceneKey.Shade))
- assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Shade))
- }
+ underTest.setDesiredScene(SceneModel(SceneKey.Shade))
+ assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Shade))
+ }
@Test(expected = IllegalStateException::class)
- fun setCurrentScene_noSuchSceneInContainer_throws() {
+ fun setDesiredScene_noSuchSceneInContainer_throws() {
val underTest =
utils.fakeSceneContainerRepository(
utils.fakeSceneContainerConfig(listOf(SceneKey.QuickSettings, SceneKey.Lockscreen)),
)
- underTest.setCurrentScene(SceneModel(SceneKey.Shade))
+ underTest.setDesiredScene(SceneModel(SceneKey.Shade))
}
@Test
- fun isVisible() = runTest {
- val underTest = utils.fakeSceneContainerRepository()
- val isVisible by collectLastValue(underTest.isVisible)
- assertThat(isVisible).isTrue()
+ fun isVisible() =
+ testScope.runTest {
+ val underTest = utils.fakeSceneContainerRepository()
+ val isVisible by collectLastValue(underTest.isVisible)
+ assertThat(isVisible).isTrue()
- underTest.setVisible(false)
- assertThat(isVisible).isFalse()
+ underTest.setVisible(false)
+ assertThat(isVisible).isFalse()
- underTest.setVisible(true)
- assertThat(isVisible).isTrue()
- }
+ underTest.setVisible(true)
+ assertThat(isVisible).isTrue()
+ }
@Test
- fun transitionProgress() = runTest {
- val underTest = utils.fakeSceneContainerRepository()
- val sceneTransitionProgress by collectLastValue(underTest.transitionProgress)
- assertThat(sceneTransitionProgress).isEqualTo(1f)
-
- val transitionState =
- MutableStateFlow<ObservableTransitionState>(
- ObservableTransitionState.Idle(SceneKey.Lockscreen)
- )
- underTest.setTransitionState(transitionState)
- assertThat(sceneTransitionProgress).isEqualTo(1f)
-
- val progress = MutableStateFlow(1f)
- transitionState.value =
- ObservableTransitionState.Transition(
- fromScene = SceneKey.Lockscreen,
- toScene = SceneKey.Shade,
- progress = progress,
- )
- assertThat(sceneTransitionProgress).isEqualTo(1f)
-
- progress.value = 0.1f
- assertThat(sceneTransitionProgress).isEqualTo(0.1f)
-
- progress.value = 0.9f
- assertThat(sceneTransitionProgress).isEqualTo(0.9f)
-
- underTest.setTransitionState(null)
- assertThat(sceneTransitionProgress).isEqualTo(1f)
- }
+ fun transitionState_defaultsToIdle() =
+ testScope.runTest {
+ val underTest = utils.fakeSceneContainerRepository()
+ val transitionState by collectLastValue(underTest.transitionState)
+
+ assertThat(transitionState)
+ .isEqualTo(
+ ObservableTransitionState.Idle(utils.fakeSceneContainerConfig().initialSceneKey)
+ )
+ }
@Test
- fun setSceneTransition() = runTest {
- val underTest = utils.fakeSceneContainerRepository()
- val sceneTransition by collectLastValue(underTest.transitions)
- assertThat(sceneTransition).isNull()
+ fun transitionState_reflectsUpdates() =
+ testScope.runTest {
+ val underTest = utils.fakeSceneContainerRepository()
+ val transitionState =
+ MutableStateFlow<ObservableTransitionState>(
+ ObservableTransitionState.Idle(SceneKey.Lockscreen)
+ )
+ underTest.setTransitionState(transitionState)
+ val reflectedTransitionState by collectLastValue(underTest.transitionState)
+ assertThat(reflectedTransitionState).isEqualTo(transitionState.value)
+
+ val progress = MutableStateFlow(1f)
+ transitionState.value =
+ ObservableTransitionState.Transition(
+ fromScene = SceneKey.Lockscreen,
+ toScene = SceneKey.Shade,
+ progress = progress,
+ )
+ assertThat(reflectedTransitionState).isEqualTo(transitionState.value)
- underTest.setSceneTransition(SceneKey.Lockscreen, SceneKey.QuickSettings)
- assertThat(sceneTransition)
- .isEqualTo(
- SceneTransitionModel(from = SceneKey.Lockscreen, to = SceneKey.QuickSettings)
- )
- }
+ progress.value = 0.1f
+ assertThat(reflectedTransitionState).isEqualTo(transitionState.value)
- @Test(expected = IllegalStateException::class)
- fun setSceneTransition_noFromSceneInContainer_throws() {
- val underTest =
- utils.fakeSceneContainerRepository(
- utils.fakeSceneContainerConfig(listOf(SceneKey.QuickSettings, SceneKey.Lockscreen)),
- )
- underTest.setSceneTransition(SceneKey.Shade, SceneKey.Lockscreen)
- }
+ progress.value = 0.9f
+ assertThat(reflectedTransitionState).isEqualTo(transitionState.value)
- @Test(expected = IllegalStateException::class)
- fun setSceneTransition_noToSceneInContainer_throws() {
- val underTest =
- utils.fakeSceneContainerRepository(
- utils.fakeSceneContainerConfig(listOf(SceneKey.QuickSettings, SceneKey.Lockscreen)),
- )
- underTest.setSceneTransition(SceneKey.Shade, SceneKey.Lockscreen)
- }
+ underTest.setTransitionState(null)
+ assertThat(reflectedTransitionState)
+ .isEqualTo(
+ ObservableTransitionState.Idle(utils.fakeSceneContainerConfig().initialSceneKey)
+ )
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt
index 4facc7a6a36d..0a93a7ca465f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt
@@ -25,10 +25,12 @@ import com.android.systemui.scene.SceneTestUtils
import com.android.systemui.scene.shared.model.ObservableTransitionState
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.shared.model.SceneModel
-import com.android.systemui.scene.shared.model.SceneTransitionModel
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.runner.RunWith
@@ -39,6 +41,7 @@ import org.junit.runners.JUnit4
class SceneInteractorTest : SysuiTestCase() {
private val utils = SceneTestUtils(this)
+ private val testScope = utils.testScope
private val repository = utils.fakeSceneContainerRepository()
private val underTest = utils.sceneInteractor(repository = repository)
@@ -48,77 +51,156 @@ class SceneInteractorTest : SysuiTestCase() {
}
@Test
- fun currentScene() = runTest {
- val currentScene by collectLastValue(underTest.currentScene)
- assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Lockscreen))
+ fun changeScene() =
+ testScope.runTest {
+ val desiredScene by collectLastValue(underTest.desiredScene)
+ assertThat(desiredScene).isEqualTo(SceneModel(SceneKey.Lockscreen))
- underTest.setCurrentScene(SceneModel(SceneKey.Shade), "reason")
- assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Shade))
- }
+ underTest.changeScene(SceneModel(SceneKey.Shade), "reason")
+ assertThat(desiredScene).isEqualTo(SceneModel(SceneKey.Shade))
+ }
+
+ @Test
+ fun onSceneChanged() =
+ testScope.runTest {
+ val desiredScene by collectLastValue(underTest.desiredScene)
+ assertThat(desiredScene).isEqualTo(SceneModel(SceneKey.Lockscreen))
+
+ underTest.onSceneChanged(SceneModel(SceneKey.Shade), "reason")
+ assertThat(desiredScene).isEqualTo(SceneModel(SceneKey.Shade))
+ }
@Test
- fun sceneTransitionProgress() = runTest {
- val transitionProgress by collectLastValue(underTest.transitionProgress)
- assertThat(transitionProgress).isEqualTo(1f)
+ fun transitionState() =
+ testScope.runTest {
+ val underTest = utils.fakeSceneContainerRepository()
+ val transitionState =
+ MutableStateFlow<ObservableTransitionState>(
+ ObservableTransitionState.Idle(SceneKey.Lockscreen)
+ )
+ underTest.setTransitionState(transitionState)
+ val reflectedTransitionState by collectLastValue(underTest.transitionState)
+ assertThat(reflectedTransitionState).isEqualTo(transitionState.value)
- val progress = MutableStateFlow(0.55f)
- repository.setTransitionState(
- MutableStateFlow(
+ val progress = MutableStateFlow(1f)
+ transitionState.value =
ObservableTransitionState.Transition(
fromScene = SceneKey.Lockscreen,
toScene = SceneKey.Shade,
progress = progress,
- ),
- )
- )
- assertThat(transitionProgress).isEqualTo(0.55f)
- }
+ )
+ assertThat(reflectedTransitionState).isEqualTo(transitionState.value)
+
+ progress.value = 0.1f
+ assertThat(reflectedTransitionState).isEqualTo(transitionState.value)
+
+ progress.value = 0.9f
+ assertThat(reflectedTransitionState).isEqualTo(transitionState.value)
+
+ underTest.setTransitionState(null)
+ assertThat(reflectedTransitionState)
+ .isEqualTo(
+ ObservableTransitionState.Idle(utils.fakeSceneContainerConfig().initialSceneKey)
+ )
+ }
@Test
- fun isVisible() = runTest {
- val isVisible by collectLastValue(underTest.isVisible)
- assertThat(isVisible).isTrue()
+ fun isVisible() =
+ testScope.runTest {
+ val isVisible by collectLastValue(underTest.isVisible)
+ assertThat(isVisible).isTrue()
- underTest.setVisible(false, "reason")
- assertThat(isVisible).isFalse()
+ underTest.setVisible(false, "reason")
+ assertThat(isVisible).isFalse()
- underTest.setVisible(true, "reason")
- assertThat(isVisible).isTrue()
- }
+ underTest.setVisible(true, "reason")
+ assertThat(isVisible).isTrue()
+ }
@Test
- fun sceneTransitions() = runTest {
- val transitions by collectLastValue(underTest.transitions)
- assertThat(transitions).isNull()
-
- val initialSceneKey = underTest.currentScene.value.key
- underTest.setCurrentScene(SceneModel(SceneKey.Shade), "reason")
- assertThat(transitions)
- .isEqualTo(
- SceneTransitionModel(
- from = initialSceneKey,
- to = SceneKey.Shade,
+ fun finishedSceneTransitions() =
+ testScope.runTest {
+ val transitionState =
+ MutableStateFlow<ObservableTransitionState>(
+ ObservableTransitionState.Idle(SceneKey.Lockscreen)
)
- )
-
- underTest.setCurrentScene(SceneModel(SceneKey.QuickSettings), "reason")
- assertThat(transitions)
- .isEqualTo(
- SceneTransitionModel(
- from = SceneKey.Shade,
- to = SceneKey.QuickSettings,
+ underTest.setTransitionState(transitionState)
+ var transitionCount = 0
+ val job = launch {
+ underTest
+ .finishedSceneTransitions(
+ from = SceneKey.Shade,
+ to = SceneKey.QuickSettings,
+ )
+ .collect { transitionCount++ }
+ }
+
+ assertThat(transitionCount).isEqualTo(0)
+
+ underTest.changeScene(SceneModel(SceneKey.Shade), "reason")
+ transitionState.value =
+ ObservableTransitionState.Transition(
+ fromScene = SceneKey.Lockscreen,
+ toScene = SceneKey.Shade,
+ progress = flowOf(0.5f),
)
- )
- }
+ runCurrent()
+ underTest.onSceneChanged(SceneModel(SceneKey.Shade), "reason")
+ transitionState.value = ObservableTransitionState.Idle(SceneKey.Shade)
+ runCurrent()
+ assertThat(transitionCount).isEqualTo(0)
+
+ underTest.changeScene(SceneModel(SceneKey.QuickSettings), "reason")
+ transitionState.value =
+ ObservableTransitionState.Transition(
+ fromScene = SceneKey.Shade,
+ toScene = SceneKey.QuickSettings,
+ progress = flowOf(0.5f),
+ )
+ runCurrent()
+ underTest.onSceneChanged(SceneModel(SceneKey.QuickSettings), "reason")
+ transitionState.value = ObservableTransitionState.Idle(SceneKey.QuickSettings)
+ runCurrent()
+ assertThat(transitionCount).isEqualTo(1)
+
+ underTest.changeScene(SceneModel(SceneKey.Shade), "reason")
+ transitionState.value =
+ ObservableTransitionState.Transition(
+ fromScene = SceneKey.QuickSettings,
+ toScene = SceneKey.Shade,
+ progress = flowOf(0.5f),
+ )
+ runCurrent()
+ underTest.onSceneChanged(SceneModel(SceneKey.Shade), "reason")
+ transitionState.value = ObservableTransitionState.Idle(SceneKey.Shade)
+ runCurrent()
+ assertThat(transitionCount).isEqualTo(1)
+
+ underTest.changeScene(SceneModel(SceneKey.QuickSettings), "reason")
+ transitionState.value =
+ ObservableTransitionState.Transition(
+ fromScene = SceneKey.Shade,
+ toScene = SceneKey.QuickSettings,
+ progress = flowOf(0.5f),
+ )
+ runCurrent()
+ underTest.onSceneChanged(SceneModel(SceneKey.QuickSettings), "reason")
+ transitionState.value = ObservableTransitionState.Idle(SceneKey.QuickSettings)
+ runCurrent()
+ assertThat(transitionCount).isEqualTo(2)
- @Test
- fun remoteUserInput() = runTest {
- val remoteUserInput by collectLastValue(underTest.remoteUserInput)
- assertThat(remoteUserInput).isNull()
+ job.cancel()
+ }
- for (input in SceneTestUtils.REMOTE_INPUT_DOWN_GESTURE) {
- underTest.onRemoteUserInput(input)
- assertThat(remoteUserInput).isEqualTo(input)
+ @Test
+ fun remoteUserInput() =
+ testScope.runTest {
+ val remoteUserInput by collectLastValue(underTest.remoteUserInput)
+ assertThat(remoteUserInput).isNull()
+
+ for (input in SceneTestUtils.REMOTE_INPUT_DOWN_GESTURE) {
+ underTest.onRemoteUserInput(input)
+ assertThat(remoteUserInput).isEqualTo(input)
+ }
}
- }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
index bec0b77e6480..45db7a0b17f1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
@@ -29,15 +29,17 @@ import com.android.systemui.keyguard.shared.model.WakefulnessModel
import com.android.systemui.keyguard.shared.model.WakefulnessState
import com.android.systemui.model.SysUiState
import com.android.systemui.scene.SceneTestUtils
+import com.android.systemui.scene.shared.model.ObservableTransitionState
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.shared.model.SceneModel
import com.android.systemui.util.mockito.mock
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
-import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
@@ -77,59 +79,86 @@ class SceneContainerStartableTest : SysuiTestCase() {
sceneLogger = mock(),
)
- @Before
- fun setUp() {
- prepareState()
- }
-
@Test
fun hydrateVisibility_featureEnabled() =
testScope.runTest {
- val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
+ val currentDesiredSceneKey by
+ collectLastValue(sceneInteractor.desiredScene.map { it.key })
val isVisible by collectLastValue(sceneInteractor.isVisible)
- prepareState(
- isFeatureEnabled = true,
- isDeviceUnlocked = true,
- initialSceneKey = SceneKey.Gone,
- )
- assertThat(currentSceneKey).isEqualTo(SceneKey.Gone)
+ val transitionStateFlow =
+ prepareState(
+ isFeatureEnabled = true,
+ isDeviceUnlocked = true,
+ initialSceneKey = SceneKey.Gone,
+ )
+ assertThat(currentDesiredSceneKey).isEqualTo(SceneKey.Gone)
assertThat(isVisible).isTrue()
underTest.start()
-
assertThat(isVisible).isFalse()
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Shade), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Shade), "reason")
+ transitionStateFlow.value =
+ ObservableTransitionState.Transition(
+ fromScene = SceneKey.Gone,
+ toScene = SceneKey.Shade,
+ progress = flowOf(0.5f),
+ )
+ assertThat(isVisible).isTrue()
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Shade), "reason")
+ transitionStateFlow.value = ObservableTransitionState.Idle(SceneKey.Shade)
+ assertThat(isVisible).isTrue()
+
+ sceneInteractor.changeScene(SceneModel(SceneKey.Gone), "reason")
+ transitionStateFlow.value =
+ ObservableTransitionState.Transition(
+ fromScene = SceneKey.Shade,
+ toScene = SceneKey.Gone,
+ progress = flowOf(0.5f),
+ )
assertThat(isVisible).isTrue()
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Gone), "reason")
+ transitionStateFlow.value = ObservableTransitionState.Idle(SceneKey.Gone)
+ assertThat(isVisible).isFalse()
}
@Test
fun hydrateVisibility_featureDisabled() =
testScope.runTest {
- val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
+ val currentDesiredSceneKey by
+ collectLastValue(sceneInteractor.desiredScene.map { it.key })
val isVisible by collectLastValue(sceneInteractor.isVisible)
- prepareState(
- isFeatureEnabled = false,
- isDeviceUnlocked = true,
- initialSceneKey = SceneKey.Lockscreen,
- )
- assertThat(currentSceneKey).isEqualTo(SceneKey.Lockscreen)
+ val transitionStateFlow =
+ prepareState(
+ isFeatureEnabled = false,
+ isDeviceUnlocked = true,
+ initialSceneKey = SceneKey.Gone,
+ )
+ assertThat(currentDesiredSceneKey).isEqualTo(SceneKey.Gone)
assertThat(isVisible).isTrue()
underTest.start()
+
assertThat(isVisible).isTrue()
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Gone), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Shade), "reason")
+ transitionStateFlow.value =
+ ObservableTransitionState.Transition(
+ fromScene = SceneKey.Gone,
+ toScene = SceneKey.Shade,
+ progress = flowOf(0.5f),
+ )
assertThat(isVisible).isTrue()
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Shade), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Shade), "reason")
+ transitionStateFlow.value = ObservableTransitionState.Idle(SceneKey.Shade)
assertThat(isVisible).isTrue()
}
@Test
fun switchToLockscreenWhenDeviceLocks_featureEnabled() =
testScope.runTest {
- val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
+ val currentSceneKey by collectLastValue(sceneInteractor.desiredScene.map { it.key })
prepareState(
isFeatureEnabled = true,
isDeviceUnlocked = true,
@@ -146,7 +175,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
@Test
fun switchToLockscreenWhenDeviceLocks_featureDisabled() =
testScope.runTest {
- val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
+ val currentSceneKey by collectLastValue(sceneInteractor.desiredScene.map { it.key })
prepareState(
isFeatureEnabled = false,
isDeviceUnlocked = false,
@@ -163,7 +192,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
@Test
fun switchFromBouncerToGoneWhenDeviceUnlocked_featureEnabled() =
testScope.runTest {
- val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
+ val currentSceneKey by collectLastValue(sceneInteractor.desiredScene.map { it.key })
prepareState(
isFeatureEnabled = true,
isDeviceUnlocked = false,
@@ -180,7 +209,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
@Test
fun switchFromBouncerToGoneWhenDeviceUnlocked_featureDisabled() =
testScope.runTest {
- val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
+ val currentSceneKey by collectLastValue(sceneInteractor.desiredScene.map { it.key })
prepareState(
isFeatureEnabled = false,
isDeviceUnlocked = false,
@@ -197,7 +226,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
@Test
fun switchFromLockscreenToGoneWhenDeviceUnlocksWithBypassOn_featureOn_bypassOn() =
testScope.runTest {
- val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
+ val currentSceneKey by collectLastValue(sceneInteractor.desiredScene.map { it.key })
prepareState(
isFeatureEnabled = true,
isBypassEnabled = true,
@@ -214,7 +243,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
@Test
fun switchFromLockscreenToGoneWhenDeviceUnlocksWithBypassOn_featureOn_bypassOff() =
testScope.runTest {
- val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
+ val currentSceneKey by collectLastValue(sceneInteractor.desiredScene.map { it.key })
prepareState(
isFeatureEnabled = true,
isBypassEnabled = false,
@@ -231,7 +260,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
@Test
fun switchFromLockscreenToGoneWhenDeviceUnlocksWithBypassOn_featureOff_bypassOn() =
testScope.runTest {
- val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
+ val currentSceneKey by collectLastValue(sceneInteractor.desiredScene.map { it.key })
prepareState(
isFeatureEnabled = false,
isBypassEnabled = true,
@@ -248,7 +277,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
@Test
fun switchToLockscreenWhenDeviceSleepsLocked_featureEnabled() =
testScope.runTest {
- val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
+ val currentSceneKey by collectLastValue(sceneInteractor.desiredScene.map { it.key })
prepareState(
isFeatureEnabled = true,
isDeviceUnlocked = false,
@@ -265,7 +294,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
@Test
fun switchToLockscreenWhenDeviceSleepsLocked_featureDisabled() =
testScope.runTest {
- val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
+ val currentSceneKey by collectLastValue(sceneInteractor.desiredScene.map { it.key })
prepareState(
isFeatureEnabled = false,
isDeviceUnlocked = false,
@@ -282,6 +311,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
@Test
fun hydrateSystemUiState() =
testScope.runTest {
+ val transitionStateFlow = prepareState()
underTest.start()
runCurrent()
clearInvocations(sysUiState)
@@ -294,9 +324,16 @@ class SceneContainerStartableTest : SysuiTestCase() {
SceneKey.QuickSettings,
)
.forEachIndexed { index, sceneKey ->
- sceneInteractor.setCurrentScene(SceneModel(sceneKey), "reason")
+ sceneInteractor.changeScene(SceneModel(sceneKey), "reason")
+ runCurrent()
+ verify(sysUiState, times(index)).commitUpdate(Display.DEFAULT_DISPLAY)
+
+ sceneInteractor.onSceneChanged(SceneModel(sceneKey), "reason")
runCurrent()
+ verify(sysUiState, times(index)).commitUpdate(Display.DEFAULT_DISPLAY)
+ transitionStateFlow.value = ObservableTransitionState.Idle(sceneKey)
+ runCurrent()
verify(sysUiState, times(index + 1)).commitUpdate(Display.DEFAULT_DISPLAY)
}
}
@@ -304,7 +341,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
@Test
fun switchToGoneWhenDeviceStartsToWakeUp_authMethodNone_featureEnabled() =
testScope.runTest {
- val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
+ val currentSceneKey by collectLastValue(sceneInteractor.desiredScene.map { it.key })
prepareState(
isFeatureEnabled = true,
initialSceneKey = SceneKey.Lockscreen,
@@ -321,7 +358,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
@Test
fun switchToGoneWhenDeviceStartsToWakeUp_authMethodNotNone_featureEnabled() =
testScope.runTest {
- val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
+ val currentSceneKey by collectLastValue(sceneInteractor.desiredScene.map { it.key })
prepareState(
isFeatureEnabled = true,
initialSceneKey = SceneKey.Lockscreen,
@@ -338,7 +375,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
@Test
fun switchToGoneWhenDeviceStartsToWakeUp_authMethodNone_featureDisabled() =
testScope.runTest {
- val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
+ val currentSceneKey by collectLastValue(sceneInteractor.desiredScene.map { it.key })
prepareState(
isFeatureEnabled = false,
initialSceneKey = SceneKey.Lockscreen,
@@ -358,17 +395,27 @@ class SceneContainerStartableTest : SysuiTestCase() {
isBypassEnabled: Boolean = false,
initialSceneKey: SceneKey? = null,
authenticationMethod: AuthenticationMethodModel? = null,
- ) {
+ ): MutableStateFlow<ObservableTransitionState> {
featureFlags.set(Flags.SCENE_CONTAINER, isFeatureEnabled)
authenticationRepository.setUnlocked(isDeviceUnlocked)
keyguardRepository.setBypassEnabled(isBypassEnabled)
- initialSceneKey?.let { sceneInteractor.setCurrentScene(SceneModel(it), "reason") }
+ val transitionStateFlow =
+ MutableStateFlow<ObservableTransitionState>(
+ ObservableTransitionState.Idle(SceneKey.Lockscreen)
+ )
+ sceneInteractor.setTransitionState(transitionStateFlow)
+ initialSceneKey?.let {
+ transitionStateFlow.value = ObservableTransitionState.Idle(it)
+ sceneInteractor.changeScene(SceneModel(it), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(it), "reason")
+ }
authenticationMethod?.let {
authenticationRepository.setAuthenticationMethod(authenticationMethod)
authenticationRepository.setLockscreenEnabled(
authenticationMethod != AuthenticationMethodModel.None
)
}
+ return transitionStateFlow
}
companion object {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt
index 9f3b12bd2042..da6c42694666 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt
@@ -69,7 +69,8 @@ class SceneContainerViewModelTest : SysuiTestCase() {
val currentScene by collectLastValue(underTest.currentScene)
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Lockscreen))
- underTest.setCurrentScene(SceneModel(SceneKey.Shade))
+ underTest.onSceneChanged(SceneModel(SceneKey.Shade))
+
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Shade))
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
index d9301604c67f..7443097a2628 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
@@ -78,7 +78,7 @@ class ShadeSceneViewModelTest : SysuiTestCase() {
@Test
fun onContentClicked_deviceUnlocked_switchesToGone() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(true)
runCurrent()
@@ -91,7 +91,7 @@ class ShadeSceneViewModelTest : SysuiTestCase() {
@Test
fun onContentClicked_deviceLockedSecurely_switchesToBouncer() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
runCurrent()
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
index 62087df8c238..507267e2d185 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
@@ -97,7 +97,7 @@ class SceneTestUtils(
fun fakeSceneContainerRepository(
containerConfig: SceneContainerConfig = fakeSceneContainerConfig(),
): SceneContainerRepository {
- return SceneContainerRepository(containerConfig)
+ return SceneContainerRepository(applicationScope(), containerConfig)
}
fun fakeSceneKeys(): List<SceneKey> {