mirror of
https://gitlab.freedesktop.org/monado/monado.git
synced 2025-01-14 10:55:23 +00:00
a/android: Base implementation of xrt_instance_android
Co-authored-by: Jarvis Huang <quic_jarvhuan@quicinc.com> Part-of: <https://gitlab.freedesktop.org/monado/monado/-/merge_requests/1655>
This commit is contained in:
parent
3a7e98a51b
commit
28ec3246eb
|
@ -17,6 +17,8 @@ add_library(
|
|||
android_custom_surface.h
|
||||
android_globals.cpp
|
||||
android_globals.h
|
||||
android_instance_base.c
|
||||
android_instance_base.h
|
||||
android_lifecycle_callbacks.cpp
|
||||
android_lifecycle_callbacks.h
|
||||
android_load_class.cpp
|
||||
|
|
163
src/xrt/auxiliary/android/android_instance_base.c
Normal file
163
src/xrt/auxiliary/android/android_instance_base.c
Normal file
|
@ -0,0 +1,163 @@
|
|||
// Copyright 2023, Qualcomm Innovation Center, Inc.
|
||||
// Copyright 2021-2024, Collabora, Ltd.
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
/*!
|
||||
* @file
|
||||
* @brief Basic xrt_instance_base implementation.
|
||||
* @author Jarvis Huang
|
||||
* @author Rylie Pavlik <rylie.pavlik@collabora.com>
|
||||
* @ingroup aux_android
|
||||
*/
|
||||
|
||||
#include "android_instance_base.h"
|
||||
|
||||
#include "android/android_globals.h"
|
||||
#include "android/android_lifecycle_callbacks.h"
|
||||
#include "util/u_logging.h"
|
||||
#include "xrt/xrt_instance.h"
|
||||
#include "xrt/xrt_android.h"
|
||||
#include "xrt/xrt_results.h"
|
||||
|
||||
#include <jni.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
static inline struct android_instance_base *
|
||||
android_instance_base(struct xrt_instance_android *xinst_android)
|
||||
{
|
||||
return (struct android_instance_base *)(xinst_android);
|
||||
}
|
||||
|
||||
static inline const struct android_instance_base *
|
||||
android_instance_base_const(const struct xrt_instance_android *xinst_android)
|
||||
{
|
||||
return (const struct android_instance_base *)(xinst_android);
|
||||
}
|
||||
|
||||
static struct _JavaVM *
|
||||
base_get_vm(const struct xrt_instance_android *xinst_android)
|
||||
{
|
||||
|
||||
const struct android_instance_base *aib = android_instance_base_const(xinst_android);
|
||||
return aib->vm;
|
||||
}
|
||||
|
||||
static void *
|
||||
base_get_context(const struct xrt_instance_android *xinst_android)
|
||||
{
|
||||
|
||||
const struct android_instance_base *aib = android_instance_base_const(xinst_android);
|
||||
return aib->context;
|
||||
}
|
||||
|
||||
static xrt_result_t
|
||||
base_register_activity_lifecycle_callback(struct xrt_instance_android *xinst_android,
|
||||
xrt_android_lifecycle_event_handler_t callback,
|
||||
enum xrt_android_lifecycle_event event_mask,
|
||||
void *userdata)
|
||||
{
|
||||
struct android_instance_base *aib = android_instance_base(xinst_android);
|
||||
int ret = 0;
|
||||
if (aib->lifecycle_callbacks == NULL) {
|
||||
U_LOG_I("No lifecycle callback container, instance is likely Service");
|
||||
} else {
|
||||
ret = android_lifecycle_callbacks_register_callback(aib->lifecycle_callbacks, callback, event_mask,
|
||||
userdata);
|
||||
}
|
||||
// If it fails, the inner callback container threw on emplace_back. Should basically never happen,
|
||||
// but technically an allocation error.
|
||||
return ret == 0 ? XRT_SUCCESS : XRT_ERROR_ALLOCATION;
|
||||
}
|
||||
|
||||
|
||||
static xrt_result_t
|
||||
base_remove_activity_lifecycle_callback(struct xrt_instance_android *xinst_android,
|
||||
xrt_android_lifecycle_event_handler_t callback,
|
||||
enum xrt_android_lifecycle_event event_mask,
|
||||
void *userdata)
|
||||
{
|
||||
struct android_instance_base *aib = android_instance_base(xinst_android);
|
||||
int ret = 0;
|
||||
if (aib->lifecycle_callbacks != NULL) {
|
||||
// We expect 1 to be returned, to remove the callback we previously added
|
||||
ret = android_lifecycle_callbacks_remove_callback(aib->lifecycle_callbacks, callback, event_mask,
|
||||
userdata);
|
||||
}
|
||||
|
||||
return ret > 0 ? XRT_SUCCESS : XRT_ERROR_ANDROID;
|
||||
}
|
||||
|
||||
xrt_result_t
|
||||
android_instance_base_init(struct android_instance_base *aib,
|
||||
struct xrt_instance *xinst,
|
||||
const struct xrt_instance_info *ii)
|
||||
{
|
||||
struct _JavaVM *vm = ii->platform_info.vm;
|
||||
void *context = ii->platform_info.context;
|
||||
|
||||
if (vm == NULL) {
|
||||
U_LOG_E("Invalid Java VM - trying globals");
|
||||
vm = android_globals_get_vm();
|
||||
}
|
||||
|
||||
if (context == NULL) {
|
||||
U_LOG_E("Invalid Context - trying globals");
|
||||
context = android_globals_get_context();
|
||||
}
|
||||
|
||||
if (vm == NULL) {
|
||||
U_LOG_E("Invalid Java VM");
|
||||
return XRT_ERROR_ANDROID;
|
||||
}
|
||||
|
||||
if (context == NULL) {
|
||||
U_LOG_E("Invalid context");
|
||||
return XRT_ERROR_ANDROID;
|
||||
}
|
||||
|
||||
JNIEnv *env = NULL;
|
||||
if (vm->functions->AttachCurrentThread(&vm->functions, &env, NULL) != JNI_OK) {
|
||||
U_LOG_E("Failed to attach thread");
|
||||
return XRT_ERROR_ANDROID;
|
||||
}
|
||||
|
||||
jobject global_context = (*env)->NewGlobalRef(env, context);
|
||||
if (global_context == NULL) {
|
||||
U_LOG_E("Failed to create global ref");
|
||||
return XRT_ERROR_ANDROID;
|
||||
}
|
||||
|
||||
xinst->android_instance = &aib->base;
|
||||
aib->vm = vm;
|
||||
aib->context = global_context;
|
||||
aib->base.get_vm = base_get_vm;
|
||||
aib->base.get_context = base_get_context;
|
||||
aib->base.register_activity_lifecycle_callback = base_register_activity_lifecycle_callback;
|
||||
aib->base.remove_activity_lifecycle_callback = base_remove_activity_lifecycle_callback;
|
||||
|
||||
// aib->base.register_surface_callback = base_register_surface_callback;
|
||||
// aib->base.remove_surface_callback = base_remove_surface_callback;
|
||||
|
||||
aib->lifecycle_callbacks = android_lifecycle_callbacks_create(&aib->base);
|
||||
|
||||
if (aib->lifecycle_callbacks == NULL) {
|
||||
return XRT_ERROR_ALLOCATION;
|
||||
}
|
||||
return XRT_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
android_instance_base_cleanup(struct android_instance_base *aib, struct xrt_instance *xinst)
|
||||
{
|
||||
assert(&(aib->base) == xinst->android_instance);
|
||||
android_lifecycle_callbacks_destroy(&aib->lifecycle_callbacks);
|
||||
|
||||
if (aib->vm != NULL) {
|
||||
JNIEnv *env = NULL;
|
||||
if (aib->vm->functions->AttachCurrentThread(&aib->vm->functions, &env, NULL) == JNI_OK) {
|
||||
(*env)->DeleteGlobalRef(env, aib->context);
|
||||
}
|
||||
}
|
||||
|
||||
xinst->android_instance = NULL;
|
||||
}
|
74
src/xrt/auxiliary/android/android_instance_base.h
Normal file
74
src/xrt/auxiliary/android/android_instance_base.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
// Copyright 2023, Qualcomm Innovation Center, Inc.
|
||||
// Copyright 2020-2024, Collabora, Ltd.
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
/*!
|
||||
* @file
|
||||
* @brief Base implementation of the @ref xrt_instance_android interface.
|
||||
* @author Jarvis Huang
|
||||
* @author Rylie Pavlik <rylie.pavlik@collabora.com>
|
||||
* @ingroup aux_android
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "xrt/xrt_instance.h"
|
||||
#include "xrt/xrt_android.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct _JavaVM;
|
||||
struct android_lifecycle_callbacks;
|
||||
|
||||
/*!
|
||||
* @brief A basic implementation of the @ref xrt_instance_android interface,
|
||||
* a platform-specific "aspect" of @ref xrt_instance.
|
||||
*
|
||||
* Store nested in your @ref xrt_instance implementation (by value, not separately allocated),
|
||||
* and call @ref android_instance_base_init in your instance creation and
|
||||
* @ref android_instance_base_cleanup in instance destruction.
|
||||
*
|
||||
*/
|
||||
struct android_instance_base
|
||||
{
|
||||
struct xrt_instance_android base;
|
||||
struct _JavaVM *vm;
|
||||
void *context;
|
||||
struct android_lifecycle_callbacks *lifecycle_callbacks;
|
||||
};
|
||||
|
||||
/*!
|
||||
* @brief Initialize resources owned by @p android_instance_base and
|
||||
* sets the @ref xrt_instance::android_instance pointer.
|
||||
*
|
||||
* @param aib The object to initialize.
|
||||
* @param xinst The xrt_instance to update.
|
||||
* @param vm The JavaVM pointer.
|
||||
* @param activity The activity jobject, cast to a void pointer.
|
||||
*
|
||||
* @returns @ref XRT_SUCCESS on success, @ref XRT_ERROR_ALLOCATION if we could not allocate
|
||||
* our required objects, and @ref XRT_ERROR_ANDROID if something goes very wrong with Java/JNI
|
||||
* that should be impossible and likely indicates a logic error in the code.
|
||||
*
|
||||
* @public @memberof android_instance_base
|
||||
*/
|
||||
xrt_result_t
|
||||
android_instance_base_init(struct android_instance_base *aib,
|
||||
struct xrt_instance *xinst,
|
||||
const struct xrt_instance_info *ii);
|
||||
|
||||
/*!
|
||||
* @brief Release resources owned by @ref android_instance_base and unsets the aspect pointer
|
||||
* - but does not free @p aib itself, since it is intended to be held by value.
|
||||
*
|
||||
* @param aib The object to de-initialize.
|
||||
* @param xinst The xrt_instance to update.
|
||||
*
|
||||
* @public @memberof android_instance_base
|
||||
*/
|
||||
void
|
||||
android_instance_base_cleanup(struct android_instance_base *aib, struct xrt_instance *xinst);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
Loading…
Reference in a new issue