diff options
Diffstat (limited to 'src/frontends/android/jni/libandroidbridge/android_jni.c')
-rw-r--r-- | src/frontends/android/jni/libandroidbridge/android_jni.c | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/src/frontends/android/jni/libandroidbridge/android_jni.c b/src/frontends/android/jni/libandroidbridge/android_jni.c new file mode 100644 index 000000000..e7cb14fb7 --- /dev/null +++ b/src/frontends/android/jni/libandroidbridge/android_jni.c @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2012 Tobias Brunner + * Copyright (C) 2012 Giuliano Grassi + * Copyright (C) 2012 Ralf Sager + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "android_jni.h" + +#include <library.h> +#include <threading/thread_value.h> + +/** + * JVM + */ +static JavaVM *android_jvm; + +jclass *android_charonvpnservice_class; +jclass *android_charonvpnservice_builder_class; + +/** + * Thread-local variable. Only used because of the destructor + */ +static thread_value_t *androidjni_threadlocal; + +/** + * Thread-local destructor to ensure that a native thread is detached + * from the JVM even if androidjni_detach_thread() is not called. + */ +static void attached_thread_cleanup(void *arg) +{ + (*android_jvm)->DetachCurrentThread(android_jvm); +} + +/* + * Described in header + */ +void androidjni_attach_thread(JNIEnv **env) +{ + if ((*android_jvm)->GetEnv(android_jvm, (void**)env, + JNI_VERSION_1_6) == JNI_OK) + { /* already attached or even a Java thread */ + return; + } + (*android_jvm)->AttachCurrentThread(android_jvm, env, NULL); + /* use a thread-local value with a destructor that automatically detaches + * the thread from the JVM before it terminates, if not done manually */ + androidjni_threadlocal->set(androidjni_threadlocal, (void*)*env); +} + +/* + * Described in header + */ +void androidjni_detach_thread() +{ + if (androidjni_threadlocal->get(androidjni_threadlocal)) + { /* only do this if we actually attached this thread */ + androidjni_threadlocal->set(androidjni_threadlocal, NULL); + (*android_jvm)->DetachCurrentThread(android_jvm); + } +} + +/** + * Called when this library is loaded by the JVM + */ +jint JNI_OnLoad(JavaVM *vm, void *reserved) +{ + JNIEnv *env; + + android_jvm = vm; + + if ((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_6) != JNI_OK) + { + return -1; + } + + androidjni_threadlocal = thread_value_create(attached_thread_cleanup); + + android_charonvpnservice_class = + (*env)->NewGlobalRef(env, (*env)->FindClass(env, + JNI_PACKAGE_STRING "/CharonVpnService")); + android_charonvpnservice_builder_class = + (*env)->NewGlobalRef(env, (*env)->FindClass(env, + JNI_PACKAGE_STRING "/CharonVpnService$BuilderAdapter")); + + return JNI_VERSION_1_6; +} + +/** + * Called when this library is unloaded by the JVM (which never happens on + * Android) + */ +void JNI_OnUnload(JavaVM *vm, void *reserved) +{ + androidjni_threadlocal->destroy(androidjni_threadlocal); +} + |