summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneTransitionLayoutDataSource.kt6
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt10
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt65
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/data/repository/SceneContainerRepository.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt73
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneDataSource.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneDataSourceDelegator.kt8
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/model/FakeSceneDataSource.kt4
9 files changed, 183 insertions, 10 deletions
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneTransitionLayoutDataSource.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneTransitionLayoutDataSource.kt
index 05f8f4b38176..4b4b7ed33458 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneTransitionLayoutDataSource.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneTransitionLayoutDataSource.kt
@@ -62,4 +62,10 @@ class SceneTransitionLayoutDataSource(
coroutineScope = coroutineScope,
)
}
+
+ override fun snapToScene(toScene: SceneKey) {
+ state.snapToScene(
+ scene = toScene,
+ )
+ }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt
index 883760c67310..df30c4bf1b5a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt
@@ -70,6 +70,9 @@ class SceneContainerRepositoryTest : SysuiTestCase() {
underTest.changeScene(Scenes.Shade)
assertThat(currentScene).isEqualTo(Scenes.Shade)
+
+ underTest.snapToScene(Scenes.QuickSettings)
+ assertThat(currentScene).isEqualTo(Scenes.QuickSettings)
}
@Test(expected = IllegalStateException::class)
@@ -79,6 +82,13 @@ class SceneContainerRepositoryTest : SysuiTestCase() {
underTest.changeScene(Scenes.Shade)
}
+ @Test(expected = IllegalStateException::class)
+ fun snapToScene_noSuchSceneInContainer_throws() {
+ kosmos.sceneKeys = listOf(Scenes.QuickSettings, Scenes.Lockscreen)
+ val underTest = kosmos.sceneContainerRepository
+ underTest.snapToScene(Scenes.Shade)
+ }
+
@Test
fun isVisible() =
testScope.runTest {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt
index c16d5224e0ba..2fa94effdbd4 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt
@@ -126,6 +126,71 @@ class SceneInteractorTest : SysuiTestCase() {
}
@Test
+ fun snapToScene_toUnknownScene_doesNothing() =
+ testScope.runTest {
+ val sceneKeys =
+ listOf(
+ Scenes.QuickSettings,
+ Scenes.Shade,
+ Scenes.Lockscreen,
+ Scenes.Gone,
+ Scenes.Communal,
+ )
+ val navigationDistances =
+ mapOf(
+ Scenes.Gone to 0,
+ Scenes.Lockscreen to 0,
+ Scenes.Communal to 1,
+ Scenes.Shade to 2,
+ Scenes.QuickSettings to 3,
+ )
+ kosmos.sceneContainerConfig =
+ SceneContainerConfig(sceneKeys, Scenes.Lockscreen, navigationDistances)
+ underTest = kosmos.sceneInteractor
+ val currentScene by collectLastValue(underTest.currentScene)
+ val previousScene = currentScene
+ assertThat(previousScene).isNotEqualTo(Scenes.Bouncer)
+ underTest.snapToScene(Scenes.Bouncer, "reason")
+ assertThat(currentScene).isEqualTo(previousScene)
+ }
+
+ @Test
+ fun snapToScene() =
+ testScope.runTest {
+ underTest = kosmos.sceneInteractor
+
+ val currentScene by collectLastValue(underTest.currentScene)
+ assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
+
+ underTest.snapToScene(Scenes.Shade, "reason")
+ assertThat(currentScene).isEqualTo(Scenes.Shade)
+ }
+
+ @Test
+ fun snapToScene_toGoneWhenUnl_doesNotThrow() =
+ testScope.runTest {
+ underTest = kosmos.sceneInteractor
+
+ val currentScene by collectLastValue(underTest.currentScene)
+ assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
+
+ kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
+ SuccessFingerprintAuthenticationStatus(0, true)
+ )
+ runCurrent()
+
+ underTest.snapToScene(Scenes.Gone, "reason")
+ assertThat(currentScene).isEqualTo(Scenes.Gone)
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun snapToScene_toGoneWhenStillLocked_throws() =
+ testScope.runTest {
+ underTest = kosmos.sceneInteractor
+ underTest.snapToScene(Scenes.Gone, "reason")
+ }
+
+ @Test
fun sceneChanged_inDataSource() =
testScope.runTest {
underTest = kosmos.sceneInteractor
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 5748ad459ed6..eabc42b02665 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
@@ -87,6 +87,14 @@ constructor(
)
}
+ fun snapToScene(
+ toScene: SceneKey,
+ ) {
+ dataSource.snapToScene(
+ toScene = toScene,
+ )
+ }
+
/** Sets whether the container is visible. */
fun setVisible(isVisible: Boolean) {
_isVisible.value = isVisible
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 93cef61d9dae..08efe39d7674 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
@@ -162,19 +162,45 @@ constructor(
loggingReason: String,
transitionKey: TransitionKey? = null,
) {
- if (!repository.allSceneKeys().contains(toScene)) {
+ val currentSceneKey = currentScene.value
+ if (
+ !validateSceneChange(
+ from = currentSceneKey,
+ to = toScene,
+ loggingReason = loggingReason,
+ )
+ ) {
return
}
- check(
- toScene != Scenes.Gone || deviceUnlockedInteractor.deviceUnlockStatus.value.isUnlocked
- ) {
- "Cannot change to the Gone scene while the device is locked. Logging reason for scene" +
- " change was: $loggingReason"
- }
+ logger.logSceneChangeRequested(
+ from = currentSceneKey,
+ to = toScene,
+ reason = loggingReason,
+ isInstant = false,
+ )
+
+ repository.changeScene(toScene, transitionKey)
+ }
+ /**
+ * Requests a scene change to the given scene.
+ *
+ * The change is instantaneous and not animated; it will be observable in the next frame and
+ * there will be no transition animation.
+ */
+ fun snapToScene(
+ toScene: SceneKey,
+ loggingReason: String,
+ ) {
val currentSceneKey = currentScene.value
- if (currentSceneKey == toScene) {
+ if (
+ !validateSceneChange(
+ from = currentSceneKey,
+ to = toScene,
+ loggingReason = loggingReason,
+ )
+ ) {
return
}
@@ -182,9 +208,10 @@ constructor(
from = currentSceneKey,
to = toScene,
reason = loggingReason,
+ isInstant = true,
)
- repository.changeScene(toScene, transitionKey)
+ repository.snapToScene(toScene)
}
/**
@@ -249,4 +276,32 @@ constructor(
): Boolean {
return raw || isRemoteUserInteractionOngoing
}
+
+ /**
+ * Validates that the given scene change is allowed.
+ *
+ * Will throw a runtime exception for illegal states (for example, attempting to change to a
+ * scene that's not part of the current scene framework configuration).
+ *
+ * @param from The current scene being transitioned away from
+ * @param to The desired destination scene to transition to
+ * @param loggingReason The reason why the transition is requested, for logging purposes
+ * @return `true` if the scene change is valid; `false` if it shouldn't happen
+ */
+ private fun validateSceneChange(
+ from: SceneKey,
+ to: SceneKey,
+ loggingReason: String,
+ ): Boolean {
+ if (!repository.allSceneKeys().contains(to)) {
+ return false
+ }
+
+ check(to != Scenes.Gone || deviceUnlockedInteractor.deviceUnlockStatus.value.isUnlocked) {
+ "Cannot change to the Gone scene while the device is locked. Logging reason for scene" +
+ " change was: $loggingReason"
+ }
+
+ return from != to
+ }
}
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 5ebdd8698656..812141928e3c 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
@@ -47,6 +47,7 @@ class SceneLogger @Inject constructor(@SceneFrameworkLog private val logBuffer:
from: SceneKey,
to: SceneKey,
reason: String,
+ isInstant: Boolean,
) {
logBuffer.log(
tag = TAG,
@@ -55,8 +56,17 @@ class SceneLogger @Inject constructor(@SceneFrameworkLog private val logBuffer:
str1 = from.toString()
str2 = to.toString()
str3 = reason
+ bool1 = isInstant
+ },
+ messagePrinter = {
+ buildString {
+ append("Scene change requested: $str1 → $str2")
+ if (isInstant) {
+ append(" (instant)")
+ }
+ append(", reason: $str3")
+ }
},
- messagePrinter = { "Scene change requested: $str1 → $str2, reason: $str3" },
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneDataSource.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneDataSource.kt
index 0e078d5d8064..034da25f1a45 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneDataSource.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneDataSource.kt
@@ -40,4 +40,11 @@ interface SceneDataSource {
toScene: SceneKey,
transitionKey: TransitionKey? = null,
)
+
+ /**
+ * Asks for an instant scene switch to [toScene], without an animated transition of any kind.
+ */
+ fun snapToScene(
+ toScene: SceneKey,
+ )
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneDataSourceDelegator.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneDataSourceDelegator.kt
index 2fbcba977a91..43c3635f32fc 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneDataSourceDelegator.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneDataSourceDelegator.kt
@@ -56,6 +56,12 @@ class SceneDataSourceDelegator(
)
}
+ override fun snapToScene(toScene: SceneKey) {
+ delegateMutable.value.snapToScene(
+ toScene = toScene,
+ )
+ }
+
/**
* Binds the current, dependency injection provided [SceneDataSource] to the given object.
*
@@ -77,5 +83,7 @@ class SceneDataSourceDelegator(
MutableStateFlow(initialSceneKey).asStateFlow()
override fun changeScene(toScene: SceneKey, transitionKey: TransitionKey?) = Unit
+
+ override fun snapToScene(toScene: SceneKey) = Unit
}
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/model/FakeSceneDataSource.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/model/FakeSceneDataSource.kt
index 59a01cbedc5c..957a60f83134 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/model/FakeSceneDataSource.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/model/FakeSceneDataSource.kt
@@ -42,6 +42,10 @@ class FakeSceneDataSource(
}
}
+ override fun snapToScene(toScene: SceneKey) {
+ changeScene(toScene)
+ }
+
/**
* Pauses scene changes.
*