summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/testing/ElementStateAccess.kt9
-rw-r--r--packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/DataPointTypes.kt84
-rw-r--r--packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/FeatureCaptures.kt57
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/composable/BouncerPredictiveBackTest.kt85
4 files changed, 153 insertions, 82 deletions
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/testing/ElementStateAccess.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/testing/ElementStateAccess.kt
index cade9bff5abb..ad2ddfe2b2a4 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/testing/ElementStateAccess.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/testing/ElementStateAccess.kt
@@ -16,9 +16,12 @@
package com.android.compose.animation.scene.testing
+import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.semantics.SemanticsNode
+import androidx.compose.ui.unit.IntSize
import com.android.compose.animation.scene.Element
import com.android.compose.animation.scene.Element.Companion.AlphaUnspecified
+import com.android.compose.animation.scene.Element.Companion.SizeUnspecified
import com.android.compose.animation.scene.ElementModifier
import com.android.compose.animation.scene.Scale
@@ -28,6 +31,12 @@ val SemanticsNode.lastAlphaForTesting: Float?
val SemanticsNode.lastScaleForTesting: Scale?
get() = elementState.lastScale.takeIf { it != Scale.Unspecified }
+val SemanticsNode.lastOffsetForTesting: Offset?
+ get() = elementState.lastOffset.takeIf { it != Offset.Unspecified }
+
+val SemanticsNode.lastSizeForTesting: IntSize?
+ get() = elementState.lastSize.takeIf { it != SizeUnspecified }
+
private val SemanticsNode.elementState: Element.State
get() {
val elementModifier =
diff --git a/packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/DataPointTypes.kt b/packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/DataPointTypes.kt
new file mode 100644
index 000000000000..7be7fa17eeea
--- /dev/null
+++ b/packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/DataPointTypes.kt
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2025 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.compose.animation.scene
+
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.geometry.isFinite
+import androidx.compose.ui.geometry.isUnspecified
+import org.json.JSONObject
+import platform.test.motion.golden.DataPointType
+import platform.test.motion.golden.UnknownTypeException
+
+fun Scale.asDataPoint() = DataPointTypes.scale.makeDataPoint(this)
+
+object DataPointTypes {
+ val scale: DataPointType<Scale> =
+ DataPointType(
+ "scale",
+ jsonToValue = {
+ when (it) {
+ "unspecified" -> Scale.Unspecified
+ "default" -> Scale.Default
+ "zero" -> Scale.Zero
+ is JSONObject -> {
+ val pivot = it.get("pivot")
+ Scale(
+ scaleX = it.getDouble("x").toFloat(),
+ scaleY = it.getDouble("y").toFloat(),
+ pivot =
+ when (pivot) {
+ "unspecified" -> Offset.Unspecified
+ "infinite" -> Offset.Infinite
+ is JSONObject ->
+ Offset(
+ pivot.getDouble("x").toFloat(),
+ pivot.getDouble("y").toFloat(),
+ )
+ else -> throw UnknownTypeException()
+ },
+ )
+ }
+ else -> throw UnknownTypeException()
+ }
+ },
+ valueToJson = {
+ when (it) {
+ Scale.Unspecified -> "unspecified"
+ Scale.Default -> "default"
+ Scale.Zero -> "zero"
+ else -> {
+ JSONObject().apply {
+ put("x", it.scaleX)
+ put("y", it.scaleY)
+ put(
+ "pivot",
+ when {
+ it.pivot.isUnspecified -> "unspecified"
+ !it.pivot.isFinite -> "infinite"
+ else ->
+ JSONObject().apply {
+ put("x", it.pivot.x)
+ put("y", it.pivot.y)
+ }
+ },
+ )
+ }
+ }
+ }
+ },
+ )
+}
diff --git a/packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/FeatureCaptures.kt b/packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/FeatureCaptures.kt
new file mode 100644
index 000000000000..8658bbf1da56
--- /dev/null
+++ b/packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/FeatureCaptures.kt
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2025 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.compose.animation.scene
+
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.semantics.SemanticsNode
+import androidx.compose.ui.unit.IntSize
+import com.android.compose.animation.scene.DataPointTypes.scale
+import com.android.compose.animation.scene.testing.lastAlphaForTesting
+import com.android.compose.animation.scene.testing.lastOffsetForTesting
+import com.android.compose.animation.scene.testing.lastScaleForTesting
+import com.android.compose.animation.scene.testing.lastSizeForTesting
+import platform.test.motion.compose.DataPointTypes.intSize
+import platform.test.motion.compose.DataPointTypes.offset
+import platform.test.motion.golden.DataPoint
+import platform.test.motion.golden.DataPointTypes
+import platform.test.motion.golden.FeatureCapture
+
+/**
+ * [FeatureCapture] implementations to record animated state of [SceneTransitionLayout] [Element].
+ */
+object FeatureCaptures {
+
+ val elementAlpha =
+ FeatureCapture<SemanticsNode, Float>("alpha") {
+ DataPoint.of(it.lastAlphaForTesting, DataPointTypes.float)
+ }
+
+ val elementScale =
+ FeatureCapture<SemanticsNode, Scale>("scale") {
+ DataPoint.of(it.lastScaleForTesting, scale)
+ }
+
+ val elementOffset =
+ FeatureCapture<SemanticsNode, Offset>("offset") {
+ DataPoint.of(it.lastOffsetForTesting, offset)
+ }
+
+ val elementSize =
+ FeatureCapture<SemanticsNode, IntSize>("size") {
+ DataPoint.of(it.lastSizeForTesting, intSize)
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/composable/BouncerPredictiveBackTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/composable/BouncerPredictiveBackTest.kt
index d8a9719d2058..dda460a6198f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/composable/BouncerPredictiveBackTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/composable/BouncerPredictiveBackTest.kt
@@ -30,22 +30,17 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.geometry.isFinite
-import androidx.compose.ui.geometry.isUnspecified
-import androidx.compose.ui.semantics.SemanticsNode
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
import com.android.compose.animation.scene.ContentScope
+import com.android.compose.animation.scene.FeatureCaptures.elementAlpha
+import com.android.compose.animation.scene.FeatureCaptures.elementScale
import com.android.compose.animation.scene.ObservableTransitionState
-import com.android.compose.animation.scene.Scale
import com.android.compose.animation.scene.SceneKey
import com.android.compose.animation.scene.UserAction
import com.android.compose.animation.scene.UserActionResult
import com.android.compose.animation.scene.isElement
-import com.android.compose.animation.scene.testing.lastAlphaForTesting
-import com.android.compose.animation.scene.testing.lastScaleForTesting
import com.android.compose.theme.PlatformTheme
import com.android.systemui.SysuiTestCase
import com.android.systemui.bouncer.domain.interactor.bouncerInteractor
@@ -71,12 +66,12 @@ import com.android.systemui.scene.ui.composable.Scene
import com.android.systemui.scene.ui.composable.SceneContainer
import com.android.systemui.scene.ui.view.sceneJankMonitorFactory
import com.android.systemui.testKosmos
+import kotlin.test.Ignore
import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.flowOf
-import org.json.JSONObject
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -89,14 +84,8 @@ import platform.test.motion.compose.MotionControl
import platform.test.motion.compose.feature
import platform.test.motion.compose.recordMotion
import platform.test.motion.compose.runTest
-import platform.test.motion.golden.DataPoint
-import platform.test.motion.golden.DataPointType
-import platform.test.motion.golden.DataPointTypes
-import platform.test.motion.golden.FeatureCapture
-import platform.test.motion.golden.UnknownTypeException
import platform.test.screenshot.DeviceEmulationSpec
import platform.test.screenshot.Displays.Phone
-import kotlin.test.Ignore
/** MotionTest for the Bouncer Predictive Back animation */
@LargeTest
@@ -280,72 +269,4 @@ class BouncerPredictiveBackTest : SysuiTestCase() {
override suspend fun onActivated() = awaitCancellation()
}
-
- companion object {
- private val elementAlpha =
- FeatureCapture<SemanticsNode, Float>("alpha") {
- DataPoint.of(it.lastAlphaForTesting, DataPointTypes.float)
- }
-
- private val elementScale =
- FeatureCapture<SemanticsNode, Scale>("scale") {
- DataPoint.of(it.lastScaleForTesting, scale)
- }
-
- private val scale: DataPointType<Scale> =
- DataPointType(
- "scale",
- jsonToValue = {
- when (it) {
- "unspecified" -> Scale.Unspecified
- "default" -> Scale.Default
- "zero" -> Scale.Zero
- is JSONObject -> {
- val pivot = it.get("pivot")
- Scale(
- scaleX = it.getDouble("x").toFloat(),
- scaleY = it.getDouble("y").toFloat(),
- pivot =
- when (pivot) {
- "unspecified" -> Offset.Unspecified
- "infinite" -> Offset.Infinite
- is JSONObject ->
- Offset(
- pivot.getDouble("x").toFloat(),
- pivot.getDouble("y").toFloat(),
- )
- else -> throw UnknownTypeException()
- },
- )
- }
- else -> throw UnknownTypeException()
- }
- },
- valueToJson = {
- when (it) {
- Scale.Unspecified -> "unspecified"
- Scale.Default -> "default"
- Scale.Zero -> "zero"
- else -> {
- JSONObject().apply {
- put("x", it.scaleX)
- put("y", it.scaleY)
- put(
- "pivot",
- when {
- it.pivot.isUnspecified -> "unspecified"
- !it.pivot.isFinite -> "infinite"
- else ->
- JSONObject().apply {
- put("x", it.pivot.x)
- put("y", it.pivot.y)
- }
- },
- )
- }
- }
- }
- },
- )
- }
}