aboutsummaryrefslogtreecommitdiffstats
path: root/Alc
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2017-01-26 14:30:14 -0800
committerChris Robinson <[email protected]>2017-01-26 14:33:03 -0800
commitf0c8b7f255b17a2fcfcf622a78794cde07f033cd (patch)
treeacf95430dc7690d452f6f933c285d21dfcd000ac /Alc
parent1ebfce4cac35731f1df5702ce613eada81f6ffa5 (diff)
Get the JavaVM handle on Android targets
Diffstat (limited to 'Alc')
-rw-r--r--Alc/ALc.c64
-rw-r--r--Alc/compat.h8
2 files changed, 72 insertions, 0 deletions
diff --git a/Alc/ALc.c b/Alc/ALc.c
index 80378d91..91ff79af 100644
--- a/Alc/ALc.c
+++ b/Alc/ALc.c
@@ -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 */