diff options
author | Chris Robinson <[email protected]> | 2017-01-26 14:30:14 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2017-01-26 14:33:03 -0800 |
commit | f0c8b7f255b17a2fcfcf622a78794cde07f033cd (patch) | |
tree | acf95430dc7690d452f6f933c285d21dfcd000ac /Alc | |
parent | 1ebfce4cac35731f1df5702ce613eada81f6ffa5 (diff) |
Get the JavaVM handle on Android targets
Diffstat (limited to 'Alc')
-rw-r--r-- | Alc/ALc.c | 64 | ||||
-rw-r--r-- | Alc/compat.h | 8 |
2 files changed, 72 insertions, 0 deletions
@@ -1166,6 +1166,70 @@ static void alc_initconfig(void) } #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig) +#ifdef __ANDROID__ +#include <jni.h> + +static JavaVM *gJavaVM; +static pthread_key_t gJVMThreadKey; + +static void CleanupJNIEnv(void* UNUSED(ptr)) +{ + JCALL0(gJavaVM,DetachCurrentThread)(); +} + +void *Android_GetJNIEnv(void) +{ + /* http://developer.android.com/guide/practices/jni.html + * + * All threads are Linux threads, scheduled by the kernel. They're usually + * started from managed code (using Thread.start), but they can also be + * created elsewhere and then attached to the JavaVM. For example, a thread + * started with pthread_create can be attached with the JNI + * AttachCurrentThread or AttachCurrentThreadAsDaemon functions. Until a + * thread is attached, it has no JNIEnv, and cannot make JNI calls. + * Attaching a natively-created thread causes a java.lang.Thread object to + * be constructed and added to the "main" ThreadGroup, making it visible to + * the debugger. Calling AttachCurrentThread on an already-attached thread + * is a no-op. + */ + JNIEnv *env = pthread_getspecific(gJVMThreadKey); + if(!env) + { + int status = JCALL(gJavaVM,AttachCurrentThread)(&env, NULL); + if(status < 0) + { + ERR("Failed to attach current thread\n"); + return NULL; + } + pthread_setspecific(gJVMThreadKey, env); + } + return env; +} + +/* Automatically called by JNI. */ +JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void* UNUSED(reserved)) +{ + void *env; + int err; + + gJavaVM = jvm; + if(JCALL(gJavaVM,GetEnv)(&env, JNI_VERSION_1_4) != JNI_OK) + { + ERR("Failed to get JNIEnv with JNI_VERSION_1_4\n"); + return JNI_ERR; + } + + /* Create gJVMThreadKey so we can keep track of the JNIEnv assigned to each + * thread. The JNIEnv *must* be detached before the thread is destroyed. + */ + if((err=pthread_key_create(&gJVMThreadKey, CleanupJNIEnv)) != 0) + ERR("pthread_key_create failed: %d\n", err); + pthread_setspecific(gJVMThreadKey, env); + return JNI_VERSION_1_4; +} + +#endif + /************************************************ * Library deinitialization diff --git a/Alc/compat.h b/Alc/compat.h index 114fc655..247ed05b 100644 --- a/Alc/compat.h +++ b/Alc/compat.h @@ -46,4 +46,12 @@ void CloseLib(void *handle); void *GetSymbol(void *handle, const char *name); #endif +#ifdef __ANDROID__ +#define JCALL(obj, func) ((*(obj))->func((obj), EXTRACT_VCALL_ARGS +#define JCALL0(obj, func) ((*(obj))->func((obj) EXTRACT_VCALL_ARGS + +/** Returns a JNIEnv*. */ +void *Android_GetJNIEnv(void); +#endif + #endif /* AL_COMPAT_H */ |