1 /* 2 * Copyright 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package androidx.xr.runtime.openxr 18 19 import android.os.IBinder 20 import androidx.annotation.RestrictTo 21 import androidx.xr.runtime.internal.Anchor 22 import androidx.xr.runtime.internal.TrackingState 23 import androidx.xr.runtime.math.Pose 24 import java.nio.ByteBuffer 25 import java.util.UUID 26 27 /** Wraps the native [XrSpace] with the [Anchor] interface. */ 28 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX) 29 public class OpenXrAnchor 30 internal constructor( 31 override public val nativePointer: Long, 32 private val xrResources: XrResources, 33 loadedUuid: UUID? = null, 34 ) : ExportableAnchor, Updatable { 35 <lambda>null36 override public val anchorToken: IBinder by lazy { nativeGetAnchorToken(nativePointer) } 37 38 override var pose: Pose = Pose() 39 private set 40 41 override var trackingState: TrackingState = TrackingState.Paused 42 private set 43 44 override var persistenceState: Anchor.PersistenceState = Anchor.PersistenceState.NotPersisted 45 private set 46 47 override var uuid: UUID? = loadedUuid 48 private set 49 persistnull50 override fun persist() { 51 if ( 52 persistenceState == Anchor.PersistenceState.Persisted || 53 persistenceState == Anchor.PersistenceState.Pending 54 ) { 55 return 56 } 57 val uuidBytes = 58 checkNotNull(nativePersistAnchor(nativePointer)) { "Failed to persist anchor." } 59 UUIDFromByteArray(uuidBytes)?.let { 60 uuid = it 61 persistenceState = Anchor.PersistenceState.Pending 62 } 63 } 64 detachnull65 override fun detach() { 66 check(nativeDestroyAnchor(nativePointer)) { "Failed to destroy anchor." } 67 xrResources.removeUpdatable(this) 68 } 69 updatenull70 override fun update(xrTime: Long) { 71 val anchorState: AnchorState = 72 nativeGetAnchorState(nativePointer, xrTime) 73 ?: throw IllegalStateException( 74 "Could not retrieve data for anchor. Is the anchor valid?" 75 ) 76 77 trackingState = anchorState.trackingState 78 anchorState.pose?.let { pose = it } 79 if (uuid != null && persistenceState == Anchor.PersistenceState.Pending) { 80 persistenceState = nativeGetPersistenceState(uuid!!) 81 } 82 } 83 84 internal companion object { UUIDFromByteArraynull85 internal fun UUIDFromByteArray(bytes: ByteArray?): UUID? { 86 if (bytes == null || bytes.size != 16) { 87 return null 88 } 89 val longBytes = ByteBuffer.wrap(bytes) 90 val mostSignificantBits = longBytes.long 91 val leastSignificantBits = longBytes.long 92 return UUID(mostSignificantBits, leastSignificantBits) 93 } 94 } 95 nativeGetAnchorStatenull96 private external fun nativeGetAnchorState(nativePointer: Long, timestampNs: Long): AnchorState? 97 98 private external fun nativeGetAnchorToken(nativePointer: Long): IBinder 99 100 private external fun nativePersistAnchor(nativePointer: Long): ByteArray? 101 102 private external fun nativeGetPersistenceState(uuid: UUID): Anchor.PersistenceState 103 104 private external fun nativeDestroyAnchor(nativePointer: Long): Boolean 105 } 106 107 internal fun Anchor.PersistenceState.Companion.fromOpenXrPersistenceState( 108 value: Int 109 ): Anchor.PersistenceState = 110 when (value) { 111 0 -> 112 Anchor.PersistenceState 113 .NotPersisted // XR_ANCHOR_PERSIST_STATE_PERSIST_NOT_REQUESTED_ANDROID 114 1 -> Anchor.PersistenceState.Pending // XR_ANCHOR_PERSIST_STATE_PERSIST_PENDING_ANDROID 115 2 -> Anchor.PersistenceState.Persisted // XR_ANCHOR_PERSIST_STATE_PERSISTED_ANDROID 116 else -> { 117 throw IllegalArgumentException("Invalid persistence state value.") 118 } 119 } 120