diff --git a/xr/arcore/arcore-runtime/api/restricted_current.txt b/xr/arcore/arcore-runtime/api/restricted_current.txt index 12ea9ee20640d..df9936284a98c 100644 --- a/xr/arcore/arcore-runtime/api/restricted_current.txt +++ b/xr/arcore/arcore-runtime/api/restricted_current.txt @@ -102,9 +102,8 @@ package androidx.xr.arcore.runtime { property public abstract long nativePointer; } - @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public interface Eye { + @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public interface Eye extends androidx.xr.arcore.runtime.Trackable { method @InaccessibleFromKotlin public androidx.xr.runtime.math.Pose getPose(); - method @InaccessibleFromKotlin public androidx.xr.runtime.TrackingState getTrackingState(); method @InaccessibleFromKotlin public boolean isOpen(); property public abstract boolean isOpen; property public abstract androidx.xr.runtime.math.Pose pose; @@ -207,10 +206,9 @@ package androidx.xr.arcore.runtime { ctor @BytecodeOnly public GeospatialPoseNotTrackingException(Throwable!, int, kotlin.jvm.internal.DefaultConstructorMarker!); } - @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public interface Hand { + @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public interface Hand extends androidx.xr.arcore.runtime.Trackable { method @InaccessibleFromKotlin public default java.util.Map getHandJoints(); method @InaccessibleFromKotlin public java.nio.FloatBuffer getHandJointsBuffer(); - method @InaccessibleFromKotlin public androidx.xr.runtime.TrackingState getTrackingState(); method public static java.util.Map parseHandJoint(androidx.xr.runtime.TrackingState trackingState, java.nio.FloatBuffer handJointsBuffer); property public default java.util.Map handJoints; property public abstract java.nio.FloatBuffer handJointsBuffer; diff --git a/xr/arcore/arcore-runtime/src/main/kotlin/androidx/xr/arcore/runtime/Eye.kt b/xr/arcore/arcore-runtime/src/main/kotlin/androidx/xr/arcore/runtime/Eye.kt index 04799d87fdded..908de937a52b0 100644 --- a/xr/arcore/arcore-runtime/src/main/kotlin/androidx/xr/arcore/runtime/Eye.kt +++ b/xr/arcore/arcore-runtime/src/main/kotlin/androidx/xr/arcore/runtime/Eye.kt @@ -22,7 +22,7 @@ import androidx.xr.runtime.math.Pose /** Describes a user's eye information with coarse and fine precision. */ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX) -public interface Eye { +public interface Eye : Trackable { /** * a flag indicating whether or not the eye is open. It's set to true if it's open, false if * it's closed. * @@ -33,5 +33,5 @@ public interface Eye { public val pose: Pose /** the tracking state of the eye */ - public val trackingState: TrackingState + public override val trackingState: TrackingState } diff --git a/xr/arcore/arcore-runtime/src/main/kotlin/androidx/xr/arcore/runtime/Hand.kt b/xr/arcore/arcore-runtime/src/main/kotlin/androidx/xr/arcore/runtime/Hand.kt index d22ac9f9a9f7c..e5e8a5f43f683 100644 --- a/xr/arcore/arcore-runtime/src/main/kotlin/androidx/xr/arcore/runtime/Hand.kt +++ b/xr/arcore/arcore-runtime/src/main/kotlin/androidx/xr/arcore/runtime/Hand.kt @@ -25,7 +25,7 @@ import java.nio.FloatBuffer /** Describes a hand. */ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX) -public interface Hand { +public interface Hand : Trackable { public companion object { /** @@ -62,7 +62,7 @@ public interface Hand { } /** The current [androidx.xr.runtime.TrackingState] of the hand's data. */ - public val trackingState: TrackingState + public override val trackingState: TrackingState /** The value describing the data of the hand, including trackingState and handJoints' poses. */ public val handJointsBuffer: FloatBuffer diff --git a/xr/arcore/arcore-testing/src/main/kotlin/androidx/xr/arcore/testing/FakeRuntimeEye.kt b/xr/arcore/arcore-testing/src/main/kotlin/androidx/xr/arcore/testing/FakeRuntimeEye.kt index d35397a017e1e..b2ef6add04f66 100644 --- a/xr/arcore/arcore-testing/src/main/kotlin/androidx/xr/arcore/testing/FakeRuntimeEye.kt +++ b/xr/arcore/arcore-testing/src/main/kotlin/androidx/xr/arcore/testing/FakeRuntimeEye.kt @@ -21,7 +21,7 @@ import androidx.xr.runtime.TrackingState import androidx.xr.runtime.math.Pose /** Fake implementation of [androidx.xr.arcore.runtime.Eye] for testing purposes. */ -public class FakeRuntimeEye : Eye { +public class FakeRuntimeEye() : Eye { override var isOpen: Boolean = true override var pose: Pose = Pose() diff --git a/xr/arcore/arcore/api/current.txt b/xr/arcore/arcore/api/current.txt index e57623d361d2d..006a4dd0e6367 100644 --- a/xr/arcore/arcore/api/current.txt +++ b/xr/arcore/arcore/api/current.txt @@ -170,7 +170,7 @@ package androidx.xr.arcore { @SuppressCompatibility @kotlin.RequiresOptIn(message="This is an experimental API. It may be changed or removed in the future.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalGesturesApi { } - public final class Eye { + public final class Eye implements androidx.xr.arcore.Trackable { method @InaccessibleFromKotlin public kotlinx.coroutines.flow.StateFlow getState(); method public static androidx.xr.arcore.Eye? left(androidx.xr.runtime.Session session); method public static androidx.xr.arcore.Eye? right(androidx.xr.runtime.Session session); @@ -183,7 +183,7 @@ package androidx.xr.arcore { method public androidx.xr.arcore.Eye? right(androidx.xr.runtime.Session session); } - public static final class Eye.State { + public static final class Eye.State implements androidx.xr.arcore.Trackable.State { ctor public Eye.State(boolean isOpen, androidx.xr.runtime.math.Pose pose, androidx.xr.runtime.TrackingState trackingState); method @InaccessibleFromKotlin public androidx.xr.runtime.math.Pose getPose(); method @InaccessibleFromKotlin public androidx.xr.runtime.TrackingState getTrackingState(); @@ -436,7 +436,7 @@ package androidx.xr.arcore { property public androidx.xr.arcore.Geospatial.Surface TERRAIN; } - public final class Hand { + public final class Hand implements androidx.xr.arcore.Trackable { method public static androidx.xr.arcore.Hand.HandSide getPrimaryHandSide(android.content.ContentResolver resolver); method @InaccessibleFromKotlin public kotlinx.coroutines.flow.StateFlow getState(); method public static androidx.xr.arcore.Hand? left(androidx.xr.runtime.Session session); @@ -457,7 +457,7 @@ package androidx.xr.arcore { enum_constant public static final androidx.xr.arcore.Hand.HandSide UNKNOWN; } - public static final class Hand.State { + public static final class Hand.State implements androidx.xr.arcore.Trackable.State { method @InaccessibleFromKotlin public java.util.Map getHandJoints(); method @InaccessibleFromKotlin public java.nio.FloatBuffer getHandJointsBuffer(); method @InaccessibleFromKotlin public androidx.xr.runtime.TrackingState getTrackingState(); diff --git a/xr/arcore/arcore/api/restricted_current.txt b/xr/arcore/arcore/api/restricted_current.txt index dc2d5bb2839f7..c293c3fef7a79 100644 --- a/xr/arcore/arcore/api/restricted_current.txt +++ b/xr/arcore/arcore/api/restricted_current.txt @@ -177,7 +177,7 @@ package androidx.xr.arcore { @SuppressCompatibility @kotlin.RequiresOptIn(message="This is an experimental API. It may be changed or removed in the future.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalGesturesApi { } - public final class Eye { + public final class Eye implements androidx.xr.arcore.Trackable { method @InaccessibleFromKotlin public kotlinx.coroutines.flow.StateFlow getState(); method public static androidx.xr.arcore.Eye? left(androidx.xr.runtime.Session session); method public static androidx.xr.arcore.Eye? right(androidx.xr.runtime.Session session); @@ -191,7 +191,7 @@ package androidx.xr.arcore { method public androidx.xr.arcore.Eye? right(androidx.xr.runtime.Session session); } - public static final class Eye.State { + public static final class Eye.State implements androidx.xr.arcore.Trackable.State { ctor public Eye.State(boolean isOpen, androidx.xr.runtime.math.Pose pose, androidx.xr.runtime.TrackingState trackingState); method @InaccessibleFromKotlin public androidx.xr.runtime.math.Pose getPose(); method @InaccessibleFromKotlin public androidx.xr.runtime.TrackingState getTrackingState(); @@ -445,7 +445,7 @@ package androidx.xr.arcore { property public androidx.xr.arcore.Geospatial.Surface TERRAIN; } - public final class Hand { + public final class Hand implements androidx.xr.arcore.Trackable { method public static androidx.xr.arcore.Hand.HandSide getPrimaryHandSide(android.content.ContentResolver resolver); method @InaccessibleFromKotlin public kotlinx.coroutines.flow.StateFlow getState(); method public static androidx.xr.arcore.Hand? left(androidx.xr.runtime.Session session); @@ -467,7 +467,7 @@ package androidx.xr.arcore { enum_constant public static final androidx.xr.arcore.Hand.HandSide UNKNOWN; } - public static final class Hand.State { + public static final class Hand.State implements androidx.xr.arcore.Trackable.State { method @InaccessibleFromKotlin public java.util.Map getHandJoints(); method @InaccessibleFromKotlin public java.nio.FloatBuffer getHandJointsBuffer(); method @InaccessibleFromKotlin public androidx.xr.runtime.TrackingState getTrackingState(); diff --git a/xr/arcore/arcore/src/main/kotlin/androidx/xr/arcore/Eye.kt b/xr/arcore/arcore/src/main/kotlin/androidx/xr/arcore/Eye.kt index 197df43f15bd5..4a17af26c09d1 100644 --- a/xr/arcore/arcore/src/main/kotlin/androidx/xr/arcore/Eye.kt +++ b/xr/arcore/arcore/src/main/kotlin/androidx/xr/arcore/Eye.kt @@ -32,7 +32,8 @@ import kotlinx.coroutines.flow.asStateFlow * An [Eye] instance provides the state of the eye (shut or gazing), as well as a [Pose] indicating * where the user is currently looking. */ -public class Eye internal constructor(internal val runtimeEye: RuntimeEye) : Updatable { +public class Eye internal constructor(internal val runtimeEye: RuntimeEye) : + Trackable, Updatable { public companion object { /** @@ -88,14 +89,14 @@ public class Eye internal constructor(internal val runtimeEye: RuntimeEye) : Upd /** The eye's pose */ public val pose: Pose, /** the tracking state of the eye */ - public val trackingState: TrackingState, - ) {} + public override val trackingState: TrackingState, + ) : Trackable.State {} private var _state = MutableStateFlow(State(runtimeEye.isOpen, runtimeEye.pose, runtimeEye.trackingState)) /** A [StateFlow] that contains the latest [State] of an [Eye]. */ - public val state: StateFlow = _state.asStateFlow() + public override val state: StateFlow = _state.asStateFlow() /** * This function is used by the runtime to propagate internal state changes. It is not intended diff --git a/xr/arcore/arcore/src/main/kotlin/androidx/xr/arcore/Hand.kt b/xr/arcore/arcore/src/main/kotlin/androidx/xr/arcore/Hand.kt index a3fd1ddd6762a..1e029457cbbab 100644 --- a/xr/arcore/arcore/src/main/kotlin/androidx/xr/arcore/Hand.kt +++ b/xr/arcore/arcore/src/main/kotlin/androidx/xr/arcore/Hand.kt @@ -34,7 +34,8 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow /** Contains the tracking information of one of the user's hands. */ -public class Hand internal constructor(internal val runtimeHand: RuntimeHand) : Updatable { +public class Hand internal constructor(internal val runtimeHand: RuntimeHand) : + Trackable, Updatable { /** * Companion object holding info to the left and right hands. */ public companion object { @@ -115,9 +116,9 @@ public class Hand internal constructor(internal val runtimeHand: RuntimeHand) : */ public class State internal constructor( - public val trackingState: TrackingState, + public override val trackingState: TrackingState, public val handJointsBuffer: FloatBuffer, - ) { + ) : Trackable.State { private class JointsMap( val trackingState: TrackingState, @@ -215,7 +216,7 @@ public class Hand internal constructor(internal val runtimeHand: RuntimeHand) : private val _state = MutableStateFlow(State(TrackingState.PAUSED, ByteBuffer.allocate(0).asFloatBuffer())) /** The current [State] of this hand. */ - public val state: StateFlow = _state.asStateFlow() + public override val state: StateFlow = _state.asStateFlow() @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX) override suspend fun update() { diff --git a/xr/arcore/arcore/src/main/kotlin/androidx/xr/arcore/XrResourcesManager.kt b/xr/arcore/arcore/src/main/kotlin/androidx/xr/arcore/XrResourcesManager.kt index b76d21c4e4831..1853e1a4b6341 100644 --- a/xr/arcore/arcore/src/main/kotlin/androidx/xr/arcore/XrResourcesManager.kt +++ b/xr/arcore/arcore/src/main/kotlin/androidx/xr/arcore/XrResourcesManager.kt @@ -202,6 +202,8 @@ internal class XrResourcesManager { is RuntimePlane -> Plane(runtimeTrackable, this) is RuntimeObject -> AugmentedObject(runtimeTrackable, this) is RuntimeFace -> Face(runtimeTrackable, this) + is RuntimeEye -> Eye(runtimeTrackable) + is RuntimeHand -> Hand(runtimeTrackable) else -> throw IllegalArgumentException( "Unsupported trackable type: ${runtimeTrackable.javaClass}" diff --git a/xr/arcore/arcore/src/test/kotlin/androidx/xr/arcore/EyeTest.kt b/xr/arcore/arcore/src/test/kotlin/androidx/xr/arcore/EyeTest.kt index c16adbd22bf94..fa7461efd92df 100644 --- a/xr/arcore/arcore/src/test/kotlin/androidx/xr/arcore/EyeTest.kt +++ b/xr/arcore/arcore/src/test/kotlin/androidx/xr/arcore/EyeTest.kt @@ -20,6 +20,7 @@ import androidx.activity.ComponentActivity import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.xr.arcore.testing.FakeLifecycleManager import androidx.xr.arcore.testing.FakePerceptionRuntimeFactory +import androidx.xr.arcore.testing.FakeRuntimeAnchor import androidx.xr.arcore.testing.FakeRuntimeEye import androidx.xr.runtime.Config import androidx.xr.runtime.EyeTrackingMode @@ -48,7 +49,6 @@ class EyeTest { private lateinit var testDispatcher: TestDispatcher private lateinit var testScope: TestScope private lateinit var session: Session - private lateinit var xrResourcesManager: XrResourcesManager @Before fun setUp() { @@ -56,13 +56,14 @@ class EyeTest { testScope = TestScope(testDispatcher) activityController = Robolectric.buildActivity(ComponentActivity::class.java) activity = activityController.get() - xrResourcesManager = XrResourcesManager() + val xrResourcesManager = XrResourcesManager() val shadowApplication = shadowOf(activity.application) FakeLifecycleManager.TestPermissions.forEach { permission -> shadowApplication.grantPermissions(permission) } FakePerceptionRuntimeFactory.hasCreatePermission = true + FakeRuntimeAnchor.anchorsCreatedCount = 0 activityController.create() session = (Session.create(activity, testDispatcher) as SessionCreateSuccess).session