mirror of
https://github.com/CTCaer/RetroArch.git
synced 2025-02-21 03:50:28 +00:00
Clean up JNI: (...)
* pthread_key_create is used to set a destructor for every thread created through jni_thread_getenv * To grab a JNIEnv pointer - go through jni_thread_getenv * jni_thread_getenv sets pthread_setspecific for the JNIEnv pointer to bind destructor * Reuse activity->vm everywhere instead of creating local pointer copies * Don't use DetachCurrentThread outside of platform_android's (new) jni_thread_destruct function - the destructor will do this for us now
This commit is contained in:
parent
3f279a2d5c
commit
87421d477c
@ -20,51 +20,47 @@
|
||||
|
||||
static void input_autodetect_get_device_name(void *data, char *buf, size_t size, int id)
|
||||
{
|
||||
struct android_app *android_app = (struct android_app*)data;
|
||||
buf[0] = '\0';
|
||||
JNIEnv *env = jni_thread_getenv();
|
||||
if (!env)
|
||||
return;
|
||||
|
||||
JavaVM *vm = android_app->activity->vm;
|
||||
JNIEnv *env = NULL;
|
||||
(*vm)->AttachCurrentThread(vm, &env, 0);
|
||||
buf[0] = '\0';
|
||||
|
||||
jclass class = NULL;
|
||||
FIND_CLASS(env, class, "android/view/InputDevice");
|
||||
if (!class)
|
||||
goto end;
|
||||
return;
|
||||
|
||||
jmethodID method = NULL;
|
||||
GET_STATIC_METHOD_ID(env, method, class, "getDevice", "(I)Landroid/view/InputDevice;");
|
||||
if (!method)
|
||||
goto end;
|
||||
return;
|
||||
|
||||
jobject device = NULL;
|
||||
CALL_OBJ_STATIC_METHOD_PARAM(env, device, class, method, (jint)id);
|
||||
if (!device)
|
||||
{
|
||||
RARCH_ERR("Failed to find device for ID: %d\n", id);
|
||||
goto end;
|
||||
return;
|
||||
}
|
||||
|
||||
jmethodID getName = NULL;
|
||||
GET_METHOD_ID(env, getName, class, "getName", "()Ljava/lang/String;");
|
||||
if (!getName)
|
||||
goto end;
|
||||
return;
|
||||
|
||||
jobject name = NULL;
|
||||
CALL_OBJ_METHOD(env, name, device, getName);
|
||||
if (!name)
|
||||
{
|
||||
RARCH_ERR("Failed to find name for device ID: %d\n", id);
|
||||
goto end;
|
||||
return;
|
||||
}
|
||||
|
||||
const char *str = (*env)->GetStringUTFChars(env, name, 0);
|
||||
if (str)
|
||||
strlcpy(buf, str, size);
|
||||
(*env)->ReleaseStringUTFChars(env, name, str);
|
||||
|
||||
end:
|
||||
(*vm)->DetachCurrentThread(vm);
|
||||
}
|
||||
|
||||
void input_autodetect_setup(void *data, char *msg, size_t sizeof_msg, unsigned port, unsigned id, int source, bool *primary)
|
||||
|
@ -21,8 +21,6 @@
|
||||
|
||||
struct jni_params
|
||||
{
|
||||
JavaVM *java_vm;
|
||||
JNIEnv *env;
|
||||
jobject class_obj;
|
||||
char class_name[128];
|
||||
char method_name[128];
|
||||
|
@ -27,8 +27,6 @@
|
||||
|
||||
typedef struct android_camera
|
||||
{
|
||||
JNIEnv *env;
|
||||
JavaVM *java_vm;
|
||||
jclass class;
|
||||
jmethodID onCameraInit;
|
||||
jmethodID onCameraFree;
|
||||
@ -41,6 +39,7 @@ typedef struct android_camera
|
||||
|
||||
static void *android_camera_init(const char *device, uint64_t caps, unsigned width, unsigned height)
|
||||
{
|
||||
JNIEnv *env;
|
||||
(void)device;
|
||||
(void)width;
|
||||
(void)height;
|
||||
@ -56,39 +55,39 @@ static void *android_camera_init(const char *device, uint64_t caps, unsigned wid
|
||||
if (!androidcamera)
|
||||
return NULL;
|
||||
|
||||
androidcamera->java_vm = (JavaVM*)android_app->activity->vm;
|
||||
if ((*androidcamera->java_vm)->AttachCurrentThread(androidcamera->java_vm, &androidcamera->env, 0) != JNI_OK)
|
||||
env = jni_thread_getenv();
|
||||
if (!env)
|
||||
return NULL;
|
||||
|
||||
GET_OBJECT_CLASS(androidcamera->env, androidcamera->class, android_app->activity->clazz);
|
||||
GET_OBJECT_CLASS(env, androidcamera->class, android_app->activity->clazz);
|
||||
if (androidcamera->class == NULL)
|
||||
return NULL;
|
||||
|
||||
GET_METHOD_ID(androidcamera->env, androidcamera->onCameraInit, androidcamera->class, "onCameraInit", "()V");
|
||||
GET_METHOD_ID(env, androidcamera->onCameraInit, androidcamera->class, "onCameraInit", "()V");
|
||||
if (!androidcamera->onCameraInit)
|
||||
return NULL;
|
||||
|
||||
GET_METHOD_ID(androidcamera->env, androidcamera->onCameraFree, androidcamera->class, "onCameraFree", "()V");
|
||||
GET_METHOD_ID(env, androidcamera->onCameraFree, androidcamera->class, "onCameraFree", "()V");
|
||||
if (!androidcamera->onCameraFree)
|
||||
return NULL;
|
||||
|
||||
GET_METHOD_ID(androidcamera->env, androidcamera->onCameraSetTexture, androidcamera->class, "onCameraSetTexture", "(I)V");
|
||||
GET_METHOD_ID(env, androidcamera->onCameraSetTexture, androidcamera->class, "onCameraSetTexture", "(I)V");
|
||||
if (!androidcamera->onCameraSetTexture)
|
||||
return NULL;
|
||||
|
||||
GET_METHOD_ID(androidcamera->env, androidcamera->onCameraStart, androidcamera->class, "onCameraStart", "()V");
|
||||
GET_METHOD_ID(env, androidcamera->onCameraStart, androidcamera->class, "onCameraStart", "()V");
|
||||
if (!androidcamera->onCameraStart)
|
||||
return NULL;
|
||||
|
||||
GET_METHOD_ID(androidcamera->env, androidcamera->onCameraStop, androidcamera->class, "onCameraStop", "()V");
|
||||
GET_METHOD_ID(env, androidcamera->onCameraStop, androidcamera->class, "onCameraStop", "()V");
|
||||
if (!androidcamera->onCameraStop)
|
||||
return NULL;
|
||||
|
||||
GET_METHOD_ID(androidcamera->env, androidcamera->onCameraPoll, androidcamera->class, "onCameraPoll", "()Z");
|
||||
GET_METHOD_ID(env, androidcamera->onCameraPoll, androidcamera->class, "onCameraPoll", "()Z");
|
||||
if (!androidcamera->onCameraPoll)
|
||||
return NULL;
|
||||
|
||||
CALL_VOID_METHOD(androidcamera->env, android_app->activity->clazz, androidcamera->onCameraInit);
|
||||
CALL_VOID_METHOD(env, android_app->activity->clazz, androidcamera->onCameraInit);
|
||||
|
||||
return androidcamera;
|
||||
}
|
||||
@ -97,11 +96,11 @@ static void android_camera_free(void *data)
|
||||
{
|
||||
struct android_app *android_app = (struct android_app*)g_android;
|
||||
androidcamera_t *androidcamera = (androidcamera_t*)data;
|
||||
(void)android_app;
|
||||
JNIEnv *env = jni_thread_getenv();
|
||||
if (!env)
|
||||
return;
|
||||
|
||||
CALL_VOID_METHOD(androidcamera->env, android_app->activity->clazz, androidcamera->onCameraFree);
|
||||
|
||||
(*androidcamera->java_vm)->DetachCurrentThread(androidcamera->java_vm);
|
||||
CALL_VOID_METHOD(env, android_app->activity->clazz, androidcamera->onCameraFree);
|
||||
|
||||
free(androidcamera);
|
||||
}
|
||||
@ -110,9 +109,9 @@ static bool android_camera_start(void *data)
|
||||
{
|
||||
struct android_app *android_app = (struct android_app*)g_android;
|
||||
androidcamera_t *androidcamera = (androidcamera_t*)data;
|
||||
|
||||
(void)android_app;
|
||||
(void)androidcamera;
|
||||
JNIEnv *env = jni_thread_getenv();
|
||||
if (!env)
|
||||
return NULL;
|
||||
|
||||
glGenTextures(1, &androidcamera->tex);
|
||||
glBindTexture(GL_TEXTURE_EXTERNAL_OES, androidcamera->tex);
|
||||
@ -121,9 +120,8 @@ static bool android_camera_start(void *data)
|
||||
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
CALL_VOID_METHOD_PARAM(androidcamera->env, android_app->activity->clazz, androidcamera->onCameraSetTexture, (int) androidcamera->tex);
|
||||
|
||||
CALL_VOID_METHOD(androidcamera->env, android_app->activity->clazz, androidcamera->onCameraStart);
|
||||
CALL_VOID_METHOD_PARAM(env, android_app->activity->clazz, androidcamera->onCameraSetTexture, (int) androidcamera->tex);
|
||||
CALL_VOID_METHOD(env, android_app->activity->clazz, androidcamera->onCameraStart);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -132,10 +130,11 @@ static void android_camera_stop(void *data)
|
||||
{
|
||||
struct android_app *android_app = (struct android_app*)g_android;
|
||||
androidcamera_t *androidcamera = (androidcamera_t*)data;
|
||||
(void)android_app;
|
||||
(void)androidcamera;
|
||||
JNIEnv *env = jni_thread_getenv();
|
||||
if (!env)
|
||||
return;
|
||||
|
||||
CALL_VOID_METHOD(androidcamera->env, android_app->activity->clazz, androidcamera->onCameraStop);
|
||||
CALL_VOID_METHOD(env, android_app->activity->clazz, androidcamera->onCameraStop);
|
||||
|
||||
if (androidcamera->tex)
|
||||
glDeleteTextures(1, &androidcamera->tex);
|
||||
@ -146,12 +145,14 @@ static bool android_camera_poll(void *data, retro_camera_frame_raw_framebuffer_t
|
||||
{
|
||||
struct android_app *android_app = (struct android_app*)g_android;
|
||||
androidcamera_t *androidcamera = (androidcamera_t*)data;
|
||||
(void)android_app;
|
||||
(void)androidcamera;
|
||||
JNIEnv *env = jni_thread_getenv();
|
||||
if (!env)
|
||||
return NULL;
|
||||
|
||||
(void)frame_raw_cb;
|
||||
|
||||
jboolean newFrame;
|
||||
CALL_BOOLEAN_METHOD(androidcamera->env, newFrame, android_app->activity->clazz, androidcamera->onCameraPoll);
|
||||
CALL_BOOLEAN_METHOD(env, newFrame, android_app->activity->clazz, androidcamera->onCameraPoll);
|
||||
|
||||
if (newFrame)
|
||||
{
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "../../file.h"
|
||||
|
||||
struct android_app *g_android;
|
||||
static pthread_key_t thread_key;
|
||||
|
||||
//forward decls
|
||||
static void system_deinit(void *data);
|
||||
@ -161,6 +162,33 @@ static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue)
|
||||
android_app_set_input((struct android_app*)activity->instance, NULL);
|
||||
}
|
||||
|
||||
JNIEnv *jni_thread_getenv(void)
|
||||
{
|
||||
struct android_app* android_app = (struct android_app*)g_android;
|
||||
JNIEnv *env;
|
||||
int status = (*android_app->activity->vm)->AttachCurrentThread(android_app->activity->vm, &env, 0);
|
||||
if (status < 0)
|
||||
{
|
||||
RARCH_ERR("jni_thread_getenv: Failed to attach current thread.\n");
|
||||
return NULL;
|
||||
}
|
||||
pthread_setspecific(thread_key, (void*)env);
|
||||
|
||||
return env;
|
||||
}
|
||||
|
||||
static void jni_thread_destruct(void *value)
|
||||
{
|
||||
struct android_app* android_app = (struct android_app*)g_android;
|
||||
JNIEnv *env = (JNIEnv*)value;
|
||||
if (env)
|
||||
{
|
||||
if (android_app)
|
||||
(*android_app->activity->vm)->DetachCurrentThread(android_app->activity->vm);
|
||||
pthread_setspecific(thread_key, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Native activity interaction (called from main thread)
|
||||
// --------------------------------------------------------------------
|
||||
@ -189,6 +217,9 @@ void ANativeActivity_onCreate(ANativeActivity* activity,
|
||||
// these are set only for the native activity, and are reset when it ends
|
||||
ANativeActivity_setWindowFlags(activity, AWINDOW_FLAG_KEEP_SCREEN_ON | AWINDOW_FLAG_FULLSCREEN, 0);
|
||||
|
||||
if (pthread_key_create(&thread_key, jni_thread_destruct))
|
||||
RARCH_ERR("Error initializing pthread_key\n");
|
||||
|
||||
struct android_app* android_app = (struct android_app*)malloc(sizeof(struct android_app));
|
||||
memset(android_app, 0, sizeof(struct android_app));
|
||||
android_app->activity = activity;
|
||||
@ -230,8 +261,10 @@ static bool android_run_events (void *data)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void jni_get (void *data_in, void *data_out)
|
||||
static void jni_get(void *data, void *data_in, void *data_out)
|
||||
{
|
||||
JNIEnv *env;
|
||||
struct android_app* android_app = (struct android_app*)data;
|
||||
struct jni_params *in_params = (struct jni_params*)data_in;
|
||||
struct jni_out_params_char *out_args = (struct jni_out_params_char*)data_out;
|
||||
jclass class = NULL;
|
||||
@ -239,24 +272,31 @@ static void jni_get (void *data_in, void *data_out)
|
||||
jmethodID giid = NULL;
|
||||
jstring ret;
|
||||
|
||||
GET_OBJECT_CLASS(in_params->env, class, in_params->class_obj);
|
||||
GET_METHOD_ID(in_params->env, giid, class, in_params->method_name, in_params->method_signature);
|
||||
CALL_OBJ_METHOD(in_params->env, obj, in_params->class_obj, giid);
|
||||
if (!android_app)
|
||||
return;
|
||||
|
||||
env = jni_thread_getenv();
|
||||
if (!env)
|
||||
return;
|
||||
|
||||
GET_OBJECT_CLASS(env, class, in_params->class_obj);
|
||||
GET_METHOD_ID(env, giid, class, in_params->method_name, in_params->method_signature);
|
||||
CALL_OBJ_METHOD(env, obj, in_params->class_obj, giid);
|
||||
|
||||
if (in_params->submethod_name &&
|
||||
in_params->submethod_signature)
|
||||
{
|
||||
GET_OBJECT_CLASS(in_params->env, class, obj);
|
||||
GET_METHOD_ID(in_params->env, giid, class, in_params->submethod_name, in_params->submethod_signature);
|
||||
GET_OBJECT_CLASS(env, class, obj);
|
||||
GET_METHOD_ID(env, giid, class, in_params->submethod_name, in_params->submethod_signature);
|
||||
|
||||
CALL_OBJ_METHOD_PARAM(in_params->env, ret, obj, giid, (*in_params->env)->NewStringUTF(in_params->env, out_args->in));
|
||||
CALL_OBJ_METHOD_PARAM(env, ret, obj, giid, (*env)->NewStringUTF(env, out_args->in));
|
||||
}
|
||||
|
||||
if (giid && ret)
|
||||
{
|
||||
const char *argv = (*in_params->env)->GetStringUTFChars(in_params->env, ret, 0);
|
||||
const char *argv = (*env)->GetStringUTFChars(env, ret, 0);
|
||||
strlcpy(out_args->out, argv, out_args->out_sizeof);
|
||||
(*in_params->env)->ReleaseStringUTFChars(in_params->env, ret, argv);
|
||||
(*env)->ReleaseStringUTFChars(env, ret, argv);
|
||||
}
|
||||
}
|
||||
|
||||
@ -267,7 +307,6 @@ static void get_environment_settings(int argc, char *argv[], void *data)
|
||||
struct jni_params in_params;
|
||||
struct jni_out_params_char out_args;
|
||||
|
||||
in_params.java_vm = android_app->activity->vm;
|
||||
in_params.class_obj = android_app->activity->clazz;
|
||||
|
||||
strlcpy(in_params.method_name, "getIntent", sizeof(in_params.method_name));
|
||||
@ -275,25 +314,24 @@ static void get_environment_settings(int argc, char *argv[], void *data)
|
||||
strlcpy(in_params.submethod_name, "getStringExtra", sizeof(in_params.submethod_name));
|
||||
strlcpy(in_params.submethod_signature, "(Ljava/lang/String;)Ljava/lang/String;", sizeof(in_params.submethod_signature));
|
||||
|
||||
(*in_params.java_vm)->AttachCurrentThread(in_params.java_vm, &in_params.env, 0);
|
||||
|
||||
// ROM
|
||||
out_args.out = g_extern.fullpath;
|
||||
out_args.out_sizeof = sizeof(g_extern.fullpath);
|
||||
strlcpy(out_args.in, "ROM", sizeof(out_args.in));
|
||||
jni_get(&in_params, &out_args);
|
||||
jni_get(android_app, &in_params, &out_args);
|
||||
|
||||
// Config file
|
||||
out_args.out = g_extern.config_path;
|
||||
out_args.out_sizeof = sizeof(g_extern.config_path);
|
||||
strlcpy(out_args.in, "CONFIGFILE", sizeof(out_args.in));
|
||||
jni_get(&in_params, &out_args);
|
||||
jni_get(android_app, &in_params, &out_args);
|
||||
|
||||
// Current IME
|
||||
out_args.out = android_app->current_ime;
|
||||
out_args.out_sizeof = sizeof(android_app->current_ime);
|
||||
strlcpy(out_args.in, "IME", sizeof(out_args.in));
|
||||
jni_get(&in_params, &out_args);
|
||||
jni_get(android_app, &in_params, &out_args);
|
||||
|
||||
RARCH_LOG("Checking arguments passed ...\n");
|
||||
RARCH_LOG("ROM Filename: [%s].\n", g_extern.fullpath);
|
||||
@ -306,12 +344,10 @@ static void get_environment_settings(int argc, char *argv[], void *data)
|
||||
out_args.out = g_settings.libretro;
|
||||
out_args.out_sizeof = sizeof(g_settings.libretro);
|
||||
strlcpy(out_args.in, "LIBRETRO", sizeof(out_args.in));
|
||||
jni_get(&in_params, &out_args);
|
||||
jni_get(android_app, &in_params, &out_args);
|
||||
|
||||
RARCH_LOG("Checking arguments passed ...\n");
|
||||
RARCH_LOG("Libretro path: [%s].\n", g_settings.libretro);
|
||||
|
||||
(*in_params.java_vm)->DetachCurrentThread(in_params.java_vm);
|
||||
}
|
||||
|
||||
static int process_events(void *data)
|
||||
|
@ -148,6 +148,7 @@ enum {
|
||||
};
|
||||
|
||||
extern void engine_handle_cmd(void);
|
||||
extern JNIEnv *jni_thread_getenv(void);
|
||||
|
||||
extern struct android_app *g_android;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user