Native counterpart of VpnService.Builder added, exposed by charonservice
[strongswan.git] / src / frontends / android / jni / libandroidbridge / android_jni.c
1 /*
2 * Copyright (C) 2012 Tobias Brunner
3 * Copyright (C) 2012 Giuliano Grassi
4 * Copyright (C) 2012 Ralf Sager
5 * Hochschule fuer Technik Rapperswil
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
18 #include "android_jni.h"
19
20 #include <library.h>
21 #include <threading/thread_value.h>
22
23 /**
24 * JVM
25 */
26 static JavaVM *android_jvm;
27
28 jclass *android_charonvpnservice_class;
29 jclass *android_charonvpnservice_builder_class;
30
31 /**
32 * Thread-local variable. Only used because of the destructor
33 */
34 static thread_value_t *androidjni_threadlocal;
35
36 /**
37 * Thread-local destructor to ensure that a native thread is detached
38 * from the JVM even if androidjni_detach_thread() is not called.
39 */
40 static void attached_thread_cleanup(void *arg)
41 {
42 (*android_jvm)->DetachCurrentThread(android_jvm);
43 }
44
45 /*
46 * Described in header
47 */
48 void androidjni_attach_thread(JNIEnv **env)
49 {
50 if ((*android_jvm)->GetEnv(android_jvm, (void**)env,
51 JNI_VERSION_1_6) == JNI_OK)
52 { /* already attached or even a Java thread */
53 return;
54 }
55 (*android_jvm)->AttachCurrentThread(android_jvm, env, NULL);
56 /* use a thread-local value with a destructor that automatically detaches
57 * the thread from the JVM before it terminates, if not done manually */
58 androidjni_threadlocal->set(androidjni_threadlocal, (void*)*env);
59 }
60
61 /*
62 * Described in header
63 */
64 void androidjni_detach_thread()
65 {
66 if (androidjni_threadlocal->get(androidjni_threadlocal))
67 { /* only do this if we actually attached this thread */
68 androidjni_threadlocal->set(androidjni_threadlocal, NULL);
69 (*android_jvm)->DetachCurrentThread(android_jvm);
70 }
71 }
72
73 /**
74 * Called when this library is loaded by the JVM
75 */
76 jint JNI_OnLoad(JavaVM *vm, void *reserved)
77 {
78 JNIEnv *env;
79
80 android_jvm = vm;
81
82 if ((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_6) != JNI_OK)
83 {
84 return -1;
85 }
86
87 androidjni_threadlocal = thread_value_create(attached_thread_cleanup);
88
89 android_charonvpnservice_class =
90 (*env)->NewGlobalRef(env, (*env)->FindClass(env,
91 JNI_PACKAGE_STRING "/CharonVpnService"));
92 android_charonvpnservice_builder_class =
93 (*env)->NewGlobalRef(env, (*env)->FindClass(env,
94 JNI_PACKAGE_STRING "/CharonVpnService$BuilderAdapter"));
95
96 return JNI_VERSION_1_6;
97 }
98
99 /**
100 * Called when this library is unloaded by the JVM (which never happens on
101 * Android)
102 */
103 void JNI_OnUnload(JavaVM *vm, void *reserved)
104 {
105 androidjni_threadlocal->destroy(androidjni_threadlocal);
106 }
107