Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7c885623 authored by Mike Schneider's avatar Mike Schneider Committed by Android (Google) Code Review
Browse files

Merge changes I51f27332,I68db8b6d,I959517ff into main

* changes:
  Suspend [MotionValue.keepRunning] when idle #MotionMechanics
  Add [DebugInspector] to [MotionValue] #MotionMechanics
  [MotionValue] implementation #MotionMechanics
parents f488b492 2aed5342
Loading
Loading
Loading
Loading
+920 −0

File added.

Preview size limit exceeded, changes collapsed.

+84 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.mechanics.debug

import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import com.android.mechanics.DiscontinuityAnimation
import com.android.mechanics.MotionValue
import com.android.mechanics.spec.InputDirection
import com.android.mechanics.spec.SegmentData
import com.android.mechanics.spec.SegmentKey
import com.android.mechanics.spring.SpringParameters
import com.android.mechanics.spring.SpringState
import kotlinx.coroutines.DisposableHandle

/** Utility to gain inspection access to internal [MotionValue] state. */
class DebugInspector
internal constructor(
    initialFrameData: FrameData,
    initialIsActive: Boolean,
    initialIsAnimating: Boolean,
    disposableHandle: DisposableHandle,
) : DisposableHandle by disposableHandle {

    /** The last completed frame's data. */
    var frame: FrameData by mutableStateOf(initialFrameData)
        internal set

    /** Whether a [MotionValue.keepRunning] coroutine is active currently. */
    var isActive: Boolean by mutableStateOf(initialIsActive)
        internal set

    /**
     * `false` whenever the [MotionValue.keepRunning] coroutine internally is suspended while no
     * animation is running and the input is not changing.
     */
    var isAnimating: Boolean by mutableStateOf(initialIsAnimating)
        internal set
}

/** The input, output and internal state of a [MotionValue] for the frame. */
data class FrameData
internal constructor(
    val input: Float,
    val gestureDirection: InputDirection,
    val gestureDistance: Float,
    val frameTimeNanos: Long,
    val springState: SpringState,
    private val segment: SegmentData,
    private val animation: DiscontinuityAnimation,
) {
    val isStable: Boolean
        get() = springState == SpringState.AtRest

    val springParameters: SpringParameters
        get() = animation.springParameters

    val segmentKey: SegmentKey
        get() = segment.key

    val output: Float
        get() = currentDirectMapped + (animation.targetValue + springState.displacement)

    val outputTarget: Float
        get() = currentDirectMapped + animation.targetValue

    private val currentDirectMapped: Float
        get() = segment.mapping.map(input) - animation.targetValue
}
+1 −1
Original line number Diff line number Diff line
@@ -31,7 +31,7 @@ import kotlin.math.pow
 * @see SpringParameters function to create this value.
 */
@JvmInline
value class SpringParameters(private val packedValue: Long) {
value class SpringParameters(val packedValue: Long) {
    val stiffness: Float
        get() = unpackFloat1(packedValue)

+5 −1
Original line number Diff line number Diff line
@@ -31,7 +31,7 @@ import kotlin.math.sqrt
 * @see SpringState function to create this value.
 */
@JvmInline
value class SpringState(private val packedValue: Long) {
value class SpringState(val packedValue: Long) {
    val displacement: Float
        get() = unpackFloat1(packedValue)

@@ -51,6 +51,10 @@ value class SpringState(private val packedValue: Long) {
        return currentEnergy <= maxStableEnergy
    }

    fun addDisplacement(displacementDelta: Float): SpringState {
        return SpringState(displacement + displacementDelta, velocity)
    }

    override fun toString(): String {
        return "MechanicsSpringState(displacement=$displacement, velocity=$velocity)"
    }
+3 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ package {
android_test {
    name: "mechanics_tests",
    manifest: "AndroidManifest.xml",
    defaults: ["MotionTestDefaults"],
    test_suites: ["device-tests"],

    srcs: [
@@ -37,8 +38,9 @@ android_test {
        // ":mechanics_tests" dependencies
        "androidx.compose.animation_animation-core",
        "platform-test-annotations",
        "PlatformMotionTesting",
        "PlatformMotionTestingCompose",
        "androidx.compose.ui_ui-test-junit4",
        "androidx.compose.ui_ui-test-manifest",
        "androidx.test.runner",
        "androidx.test.ext.junit",
        "kotlin-test",
Loading