The open source OpenXR runtime
at prediction-2 168 lines 5.2 kB view raw
1// Copyright 2023, Qualcomm Innovation Center, Inc. 2// Copyright 2021-2024, Collabora, Ltd. 3// SPDX-License-Identifier: BSL-1.0 4/*! 5 * @file 6 * @brief Basic xrt_instance_base implementation. 7 * @author Jarvis Huang 8 * @author Rylie Pavlik <rylie.pavlik@collabora.com> 9 * @ingroup aux_android 10 */ 11 12#include "android_instance_base.h" 13 14#include "android/android_globals.h" 15#include "android/android_lifecycle_callbacks.h" 16#include "util/u_logging.h" 17#include "xrt/xrt_instance.h" 18#include "xrt/xrt_android.h" 19#include "xrt/xrt_results.h" 20 21#include <jni.h> 22#include <assert.h> 23 24 25static inline struct android_instance_base * 26android_instance_base(struct xrt_instance_android *xinst_android) 27{ 28 return (struct android_instance_base *)(xinst_android); 29} 30 31static inline const struct android_instance_base * 32android_instance_base_const(const struct xrt_instance_android *xinst_android) 33{ 34 return (const struct android_instance_base *)(xinst_android); 35} 36 37static struct _JavaVM * 38base_get_vm(const struct xrt_instance_android *xinst_android) 39{ 40 41 const struct android_instance_base *aib = android_instance_base_const(xinst_android); 42 return aib->vm; 43} 44 45static void * 46base_get_context(const struct xrt_instance_android *xinst_android) 47{ 48 49 const struct android_instance_base *aib = android_instance_base_const(xinst_android); 50 return aib->context; 51} 52 53static xrt_result_t 54base_register_activity_lifecycle_callback(struct xrt_instance_android *xinst_android, 55 xrt_android_lifecycle_event_handler_t callback, 56 enum xrt_android_lifecycle_event event_mask, 57 void *userdata) 58{ 59 struct android_instance_base *aib = android_instance_base(xinst_android); 60 int ret = 0; 61 if (aib->lifecycle_callbacks == NULL) { 62 U_LOG_I("No lifecycle callback container, instance is likely Service"); 63 } else { 64 ret = android_lifecycle_callbacks_register_callback(aib->lifecycle_callbacks, callback, event_mask, 65 userdata); 66 } 67 // If it fails, the inner callback container threw on emplace_back. Should basically never happen, 68 // but technically an allocation error. 69 return ret == 0 ? XRT_SUCCESS : XRT_ERROR_ALLOCATION; 70} 71 72 73static xrt_result_t 74base_remove_activity_lifecycle_callback(struct xrt_instance_android *xinst_android, 75 xrt_android_lifecycle_event_handler_t callback, 76 enum xrt_android_lifecycle_event event_mask, 77 void *userdata) 78{ 79 struct android_instance_base *aib = android_instance_base(xinst_android); 80 int ret = 0; 81 if (aib->lifecycle_callbacks != NULL) { 82 // We expect 1 to be returned, to remove the callback we previously added 83 ret = android_lifecycle_callbacks_remove_callback(aib->lifecycle_callbacks, callback, event_mask, 84 userdata); 85 } 86 87 return ret > 0 ? XRT_SUCCESS : XRT_ERROR_ANDROID; 88} 89 90xrt_result_t 91android_instance_base_init(struct android_instance_base *aib, 92 struct xrt_instance *xinst, 93 const struct xrt_instance_info *ii) 94{ 95 struct _JavaVM *vm = ii->platform_info.vm; 96 void *context = ii->platform_info.context; 97 98 if (vm == NULL) { 99 U_LOG_E("Invalid Java VM - trying globals"); 100 vm = android_globals_get_vm(); 101 } 102 103 if (context == NULL) { 104 U_LOG_E("Invalid Context - trying globals"); 105 context = android_globals_get_context(); 106 } 107 108 if (vm == NULL) { 109 U_LOG_E("Invalid Java VM"); 110 return XRT_ERROR_ANDROID; 111 } 112 113 if (context == NULL) { 114 U_LOG_E("Invalid context"); 115 return XRT_ERROR_ANDROID; 116 } 117 118 JNIEnv *env = NULL; 119 if (vm->functions->AttachCurrentThread(&vm->functions, &env, NULL) != JNI_OK) { 120 U_LOG_E("Failed to attach thread"); 121 return XRT_ERROR_ANDROID; 122 } 123 124 jobject global_context = (*env)->NewGlobalRef(env, context); 125 if (global_context == NULL) { 126 U_LOG_E("Failed to create global ref"); 127 return XRT_ERROR_ANDROID; 128 } 129 130 xinst->android_instance = &aib->base; 131 aib->vm = vm; 132 aib->context = global_context; 133 aib->base.get_vm = base_get_vm; 134 aib->base.get_context = base_get_context; 135 aib->base.register_activity_lifecycle_callback = base_register_activity_lifecycle_callback; 136 aib->base.remove_activity_lifecycle_callback = base_remove_activity_lifecycle_callback; 137 138 // aib->base.register_surface_callback = base_register_surface_callback; 139 // aib->base.remove_surface_callback = base_remove_surface_callback; 140 141 aib->lifecycle_callbacks = android_lifecycle_callbacks_create(&aib->base); 142 143 if (aib->lifecycle_callbacks == NULL) { 144 return XRT_ERROR_ALLOCATION; 145 } 146 return XRT_SUCCESS; 147} 148 149void 150android_instance_base_cleanup(struct android_instance_base *aib, struct xrt_instance *xinst) 151{ 152 if (xinst->android_instance == NULL) { 153 // Already cleaned up or never initialized. 154 return; 155 } 156 157 assert(&(aib->base) == xinst->android_instance); 158 android_lifecycle_callbacks_destroy(&aib->lifecycle_callbacks); 159 160 if (aib->vm != NULL) { 161 JNIEnv *env = NULL; 162 if (aib->vm->functions->AttachCurrentThread(&aib->vm->functions, &env, NULL) == JNI_OK) { 163 (*env)->DeleteGlobalRef(env, aib->context); 164 } 165 } 166 167 xinst->android_instance = NULL; 168}