Loading PREUPLOAD.cfg +2 −0 Original line number Diff line number Diff line Loading @@ -11,5 +11,7 @@ checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --sha ${PREUPL ktlint_hook = ${REPO_ROOT}/prebuilts/ktlint/ktlint.py --no-verify-format -f ${PREUPLOAD_FILES} alint_hook = ${REPO_ROOT}/vendor/google/tools/alint [Tool Paths] ktfmt = ${REPO_ROOT}/external/ktfmt/ktfmt.sh mechanics/benchmark/tests/src/com/android/mechanics/benchmark/MotionValueBenchmark.kt +21 −2 Original line number Diff line number Diff line Loading @@ -37,13 +37,32 @@ import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import platform.test.motion.compose.MonotonicClockTestScope import platform.test.motion.compose.runMonotonicClockTest /** Benchmark, which will execute on an Android device. Previous results: go/mm-microbenchmarks */ @RunWith(AndroidJUnit4::class) class MotionValueBenchmark { @get:Rule val benchmarkRule = BenchmarkRule() private val tearDownOperations = mutableListOf<() -> Unit>() /** * Runs a test block within a [MonotonicClockTestScope] provided by the underlying * [platform.test.motion.compose.runMonotonicClockTest] and ensures automatic cleanup. * * This mechanism provides a convenient way to register cleanup actions (e.g., stopping * coroutines, resetting states) that should reliably run at the end of the test, simplifying * test setup and teardown. */ private fun runMonotonicClockTest(block: suspend MonotonicClockTestScope.() -> Unit) { return platform.test.motion.compose.runMonotonicClockTest { try { block() } finally { tearDownOperations.fastForEach { it.invoke() } } } } private data class TestData( val motionValue: MotionValue, val gestureContext: DistanceGestureContext, Loading Loading @@ -144,7 +163,7 @@ class MotionValueBenchmark { private fun MonotonicClockTestScope.keepRunningDuringTest(motionValue: MotionValue) { val keepRunningJob = launch { motionValue.keepRunning() } doOnTearDown { keepRunningJob.cancel() } tearDownOperations += { keepRunningJob.cancel() } } private val MotionSpec.Companion.ZeroToOne_AtOne Loading mechanics/src/com/android/mechanics/MotionValue.kt +16 −1 Original line number Diff line number Diff line Loading @@ -312,7 +312,22 @@ private class ObservableComputations( override val currentSegment by derivedStateOf { computeCurrentSegment() } override val currentGuaranteeState by derivedStateOf { computeCurrentGuaranteeState() } override val currentAnimation by derivedStateOf { computeCurrentAnimation() } override val currentSpringState by derivedStateOf { computeCurrentSpringState() } private var memoizedSpringState: SpringState = SpringState.AtRest private var memoizedAnimation: DiscontinuityAnimation? = null private var memoizedTimeNanos: Long = Long.MIN_VALUE override val currentSpringState: SpringState get() { val animation = currentAnimation val timeNanos = currentAnimationTimeNanos return if (memoizedAnimation == animation && memoizedTimeNanos == timeNanos) { memoizedSpringState } else { memoizedAnimation = animation memoizedTimeNanos = timeNanos computeCurrentSpringState(animation, timeNanos).also { memoizedSpringState = it } } } suspend fun keepRunning(continueRunning: () -> Boolean) { check(!isActive) { "MotionValue($label) is already running" } Loading mechanics/src/com/android/mechanics/impl/Computations.kt +3 −3 Original line number Diff line number Diff line Loading @@ -403,11 +403,11 @@ internal interface ComputeAnimation : ComputeGuaranteeState { internal interface ComputeSpringState : ComputeAnimation { val currentAnimation: DiscontinuityAnimation fun computeCurrentSpringState(): SpringState { with(currentAnimation) { fun computeCurrentSpringState(animation: DiscontinuityAnimation, timeNanos: Long): SpringState { with(animation) { if (isAtRest) return SpringState.AtRest val nanosSinceAnimationStart = currentAnimationTimeNanos - springStartTimeNanos val nanosSinceAnimationStart = timeNanos - springStartTimeNanos val updatedSpringState = springStartState.calculateUpdatedState(nanosSinceAnimationStart, springParameters) Loading mechanics/src/com/android/mechanics/view/ViewMotionValue.kt +4 −2 Original line number Diff line number Diff line Loading @@ -209,7 +209,8 @@ private class ImperativeComputations( override var currentSegment: SegmentData = computeCurrentSegment() override var currentGuaranteeState: GuaranteeState = computeCurrentGuaranteeState() override var currentAnimation: DiscontinuityAnimation = computeCurrentAnimation() override var currentSpringState: SpringState = computeCurrentSpringState() override var currentSpringState: SpringState = computeCurrentSpringState(currentAnimation, currentAnimationTimeNanos) // ---- Lifecycle ------------------------------------------------------------------------------ Loading Loading @@ -281,7 +282,8 @@ private class ImperativeComputations( currentSegment = computeCurrentSegment() currentGuaranteeState = computeCurrentGuaranteeState() currentAnimation = computeCurrentAnimation() currentSpringState = computeCurrentSpringState() currentSpringState = computeCurrentSpringState(currentAnimation, currentAnimationTimeNanos) } debugInspector?.run { Loading Loading
PREUPLOAD.cfg +2 −0 Original line number Diff line number Diff line Loading @@ -11,5 +11,7 @@ checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --sha ${PREUPL ktlint_hook = ${REPO_ROOT}/prebuilts/ktlint/ktlint.py --no-verify-format -f ${PREUPLOAD_FILES} alint_hook = ${REPO_ROOT}/vendor/google/tools/alint [Tool Paths] ktfmt = ${REPO_ROOT}/external/ktfmt/ktfmt.sh
mechanics/benchmark/tests/src/com/android/mechanics/benchmark/MotionValueBenchmark.kt +21 −2 Original line number Diff line number Diff line Loading @@ -37,13 +37,32 @@ import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import platform.test.motion.compose.MonotonicClockTestScope import platform.test.motion.compose.runMonotonicClockTest /** Benchmark, which will execute on an Android device. Previous results: go/mm-microbenchmarks */ @RunWith(AndroidJUnit4::class) class MotionValueBenchmark { @get:Rule val benchmarkRule = BenchmarkRule() private val tearDownOperations = mutableListOf<() -> Unit>() /** * Runs a test block within a [MonotonicClockTestScope] provided by the underlying * [platform.test.motion.compose.runMonotonicClockTest] and ensures automatic cleanup. * * This mechanism provides a convenient way to register cleanup actions (e.g., stopping * coroutines, resetting states) that should reliably run at the end of the test, simplifying * test setup and teardown. */ private fun runMonotonicClockTest(block: suspend MonotonicClockTestScope.() -> Unit) { return platform.test.motion.compose.runMonotonicClockTest { try { block() } finally { tearDownOperations.fastForEach { it.invoke() } } } } private data class TestData( val motionValue: MotionValue, val gestureContext: DistanceGestureContext, Loading Loading @@ -144,7 +163,7 @@ class MotionValueBenchmark { private fun MonotonicClockTestScope.keepRunningDuringTest(motionValue: MotionValue) { val keepRunningJob = launch { motionValue.keepRunning() } doOnTearDown { keepRunningJob.cancel() } tearDownOperations += { keepRunningJob.cancel() } } private val MotionSpec.Companion.ZeroToOne_AtOne Loading
mechanics/src/com/android/mechanics/MotionValue.kt +16 −1 Original line number Diff line number Diff line Loading @@ -312,7 +312,22 @@ private class ObservableComputations( override val currentSegment by derivedStateOf { computeCurrentSegment() } override val currentGuaranteeState by derivedStateOf { computeCurrentGuaranteeState() } override val currentAnimation by derivedStateOf { computeCurrentAnimation() } override val currentSpringState by derivedStateOf { computeCurrentSpringState() } private var memoizedSpringState: SpringState = SpringState.AtRest private var memoizedAnimation: DiscontinuityAnimation? = null private var memoizedTimeNanos: Long = Long.MIN_VALUE override val currentSpringState: SpringState get() { val animation = currentAnimation val timeNanos = currentAnimationTimeNanos return if (memoizedAnimation == animation && memoizedTimeNanos == timeNanos) { memoizedSpringState } else { memoizedAnimation = animation memoizedTimeNanos = timeNanos computeCurrentSpringState(animation, timeNanos).also { memoizedSpringState = it } } } suspend fun keepRunning(continueRunning: () -> Boolean) { check(!isActive) { "MotionValue($label) is already running" } Loading
mechanics/src/com/android/mechanics/impl/Computations.kt +3 −3 Original line number Diff line number Diff line Loading @@ -403,11 +403,11 @@ internal interface ComputeAnimation : ComputeGuaranteeState { internal interface ComputeSpringState : ComputeAnimation { val currentAnimation: DiscontinuityAnimation fun computeCurrentSpringState(): SpringState { with(currentAnimation) { fun computeCurrentSpringState(animation: DiscontinuityAnimation, timeNanos: Long): SpringState { with(animation) { if (isAtRest) return SpringState.AtRest val nanosSinceAnimationStart = currentAnimationTimeNanos - springStartTimeNanos val nanosSinceAnimationStart = timeNanos - springStartTimeNanos val updatedSpringState = springStartState.calculateUpdatedState(nanosSinceAnimationStart, springParameters) Loading
mechanics/src/com/android/mechanics/view/ViewMotionValue.kt +4 −2 Original line number Diff line number Diff line Loading @@ -209,7 +209,8 @@ private class ImperativeComputations( override var currentSegment: SegmentData = computeCurrentSegment() override var currentGuaranteeState: GuaranteeState = computeCurrentGuaranteeState() override var currentAnimation: DiscontinuityAnimation = computeCurrentAnimation() override var currentSpringState: SpringState = computeCurrentSpringState() override var currentSpringState: SpringState = computeCurrentSpringState(currentAnimation, currentAnimationTimeNanos) // ---- Lifecycle ------------------------------------------------------------------------------ Loading Loading @@ -281,7 +282,8 @@ private class ImperativeComputations( currentSegment = computeCurrentSegment() currentGuaranteeState = computeCurrentGuaranteeState() currentAnimation = computeCurrentAnimation() currentSpringState = computeCurrentSpringState() currentSpringState = computeCurrentSpringState(currentAnimation, currentAnimationTimeNanos) } debugInspector?.run { Loading