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.arcore 18 19 import androidx.annotation.RestrictTo 20 import androidx.xr.runtime.CoreState 21 import androidx.xr.runtime.StateExtender 22 import androidx.xr.runtime.internal.PerceptionManager 23 import androidx.xr.runtime.internal.Runtime 24 import kotlin.time.ComparableTimeMark 25 26 /** [StateExtender] in charge of extending [CoreState] with [PerceptionState]. */ 27 internal class PerceptionStateExtender : StateExtender { 28 29 internal companion object { 30 internal const val MAX_PERCEPTION_STATE_EXTENSION_SIZE = 100 31 32 internal val perceptionStateMap = mutableMapOf<ComparableTimeMark, PerceptionState>() 33 34 private val timeMarkQueue = ArrayDeque<ComparableTimeMark>() 35 } 36 37 internal lateinit var perceptionManager: PerceptionManager 38 39 internal val xrResourcesManager = XrResourcesManager() 40 initializenull41 override fun initialize(runtime: Runtime) { 42 perceptionManager = runtime.perceptionManager 43 xrResourcesManager.lifecycleManager = runtime.lifecycleManager 44 xrResourcesManager.initiateHands(perceptionManager.leftHand, perceptionManager.rightHand) 45 } 46 extendnull47 override suspend fun extend(coreState: CoreState) { 48 check(this::perceptionManager.isInitialized) { 49 "PerceptionStateExtender is not initialized." 50 } 51 52 xrResourcesManager.syncTrackables(perceptionManager.trackables) 53 xrResourcesManager.update() 54 55 xrResourcesManager.leftHand?.update() 56 xrResourcesManager.rightHand?.update() 57 58 updatePerceptionStateMap(coreState) 59 } 60 closenull61 internal fun close() { 62 perceptionStateMap.clear() 63 timeMarkQueue.clear() 64 xrResourcesManager.clear() 65 } 66 updatePerceptionStateMapnull67 private fun updatePerceptionStateMap(coreState: CoreState) { 68 perceptionStateMap.put( 69 coreState.timeMark, 70 PerceptionState( 71 coreState.timeMark, 72 xrResourcesManager.trackablesMap.values, 73 xrResourcesManager.leftHand, 74 xrResourcesManager.rightHand, 75 ), 76 ) 77 timeMarkQueue.add(coreState.timeMark) 78 79 if (timeMarkQueue.size > MAX_PERCEPTION_STATE_EXTENSION_SIZE) { 80 val timeMark = timeMarkQueue.removeFirst() 81 perceptionStateMap.remove(timeMark) 82 } 83 } 84 } 85 86 /** The state of the perception system. */ 87 @get:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX) 88 public val CoreState.perceptionState: PerceptionState? 89 get() = PerceptionStateExtender.perceptionStateMap[this.timeMark] 90