1 // Copyright 2018 Dolphin Emulator Project
2 // Licensed under GPLv2+
3 // Refer to the license.txt file included.
4
5 #include "jni/AndroidCommon/IDCache.h"
6
7 #include <jni.h>
8
9 static constexpr jint JNI_VERSION = JNI_VERSION_1_6;
10
11 static JavaVM* s_java_vm;
12
13 static jclass s_native_library_class;
14 static jmethodID s_display_alert_msg;
15 static jmethodID s_do_rumble;
16 static jmethodID s_get_update_touch_pointer;
17
18 static jclass s_game_file_class;
19 static jfieldID s_game_file_pointer;
20 static jmethodID s_game_file_constructor;
21
22 static jclass s_game_file_cache_class;
23 static jfieldID s_game_file_cache_pointer;
24
25 static jclass s_analytics_class;
26 static jmethodID s_send_analytics_report;
27 static jmethodID s_get_analytics_value;
28
29 static jclass s_linked_hash_map_class;
30 static jmethodID s_linked_hash_map_init;
31 static jmethodID s_linked_hash_map_put;
32
33 static jclass s_ini_file_class;
34 static jfieldID s_ini_file_pointer;
35 static jclass s_ini_file_section_class;
36 static jfieldID s_ini_file_section_pointer;
37 static jmethodID s_ini_file_section_constructor;
38
39 static jclass s_compress_cb_class;
40 static jmethodID s_compress_cb_run;
41
42 static jclass s_content_handler_class;
43 static jmethodID s_content_handler_open_fd;
44 static jmethodID s_content_handler_delete;
45
46 namespace IDCache
47 {
GetEnvForThread()48 JNIEnv* GetEnvForThread()
49 {
50 thread_local static struct OwnedEnv
51 {
52 OwnedEnv()
53 {
54 status = s_java_vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6);
55 if (status == JNI_EDETACHED)
56 s_java_vm->AttachCurrentThread(&env, nullptr);
57 }
58
59 ~OwnedEnv()
60 {
61 if (status == JNI_EDETACHED)
62 s_java_vm->DetachCurrentThread();
63 }
64
65 int status;
66 JNIEnv* env = nullptr;
67 } owned;
68 return owned.env;
69 }
70
GetNativeLibraryClass()71 jclass GetNativeLibraryClass()
72 {
73 return s_native_library_class;
74 }
75
GetDisplayAlertMsg()76 jmethodID GetDisplayAlertMsg()
77 {
78 return s_display_alert_msg;
79 }
80
GetDoRumble()81 jmethodID GetDoRumble()
82 {
83 return s_do_rumble;
84 }
85
GetUpdateTouchPointer()86 jmethodID GetUpdateTouchPointer()
87 {
88 return s_get_update_touch_pointer;
89 }
90
GetAnalyticsClass()91 jclass GetAnalyticsClass()
92 {
93 return s_analytics_class;
94 }
95
GetSendAnalyticsReport()96 jmethodID GetSendAnalyticsReport()
97 {
98 return s_send_analytics_report;
99 }
100
GetAnalyticsValue()101 jmethodID GetAnalyticsValue()
102 {
103 return s_get_analytics_value;
104 }
105
GetGameFileClass()106 jclass GetGameFileClass()
107 {
108 return s_game_file_class;
109 }
110
GetGameFilePointer()111 jfieldID GetGameFilePointer()
112 {
113 return s_game_file_pointer;
114 }
115
GetGameFileConstructor()116 jmethodID GetGameFileConstructor()
117 {
118 return s_game_file_constructor;
119 }
120
GetGameFileCacheClass()121 jclass GetGameFileCacheClass()
122 {
123 return s_game_file_cache_class;
124 }
125
GetGameFileCachePointer()126 jfieldID GetGameFileCachePointer()
127 {
128 return s_game_file_cache_pointer;
129 }
130
GetLinkedHashMapClass()131 jclass GetLinkedHashMapClass()
132 {
133 return s_linked_hash_map_class;
134 }
135
GetLinkedHashMapInit()136 jmethodID GetLinkedHashMapInit()
137 {
138 return s_linked_hash_map_init;
139 }
140
GetLinkedHashMapPut()141 jmethodID GetLinkedHashMapPut()
142 {
143 return s_linked_hash_map_put;
144 }
145
GetIniFileClass()146 jclass GetIniFileClass()
147 {
148 return s_ini_file_class;
149 }
150
GetIniFilePointer()151 jfieldID GetIniFilePointer()
152 {
153 return s_ini_file_pointer;
154 }
155
GetIniFileSectionClass()156 jclass GetIniFileSectionClass()
157 {
158 return s_ini_file_section_class;
159 }
160
GetIniFileSectionPointer()161 jfieldID GetIniFileSectionPointer()
162 {
163 return s_ini_file_section_pointer;
164 }
165
GetIniFileSectionConstructor()166 jmethodID GetIniFileSectionConstructor()
167 {
168 return s_ini_file_section_constructor;
169 }
170
GetCompressCallbackClass()171 jclass GetCompressCallbackClass()
172 {
173 return s_compress_cb_class;
174 }
175
GetCompressCallbackRun()176 jmethodID GetCompressCallbackRun()
177 {
178 return s_compress_cb_run;
179 }
180
GetContentHandlerClass()181 jclass GetContentHandlerClass()
182 {
183 return s_content_handler_class;
184 }
185
GetContentHandlerOpenFd()186 jmethodID GetContentHandlerOpenFd()
187 {
188 return s_content_handler_open_fd;
189 }
190
GetContentHandlerDelete()191 jmethodID GetContentHandlerDelete()
192 {
193 return s_content_handler_delete;
194 }
195
196 } // namespace IDCache
197
198 #ifdef __cplusplus
199 extern "C" {
200 #endif
201
JNI_OnLoad(JavaVM * vm,void * reserved)202 jint JNI_OnLoad(JavaVM* vm, void* reserved)
203 {
204 s_java_vm = vm;
205
206 JNIEnv* env;
207 if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION) != JNI_OK)
208 return JNI_ERR;
209
210 const jclass native_library_class = env->FindClass("org/dolphinemu/dolphinemu/NativeLibrary");
211 s_native_library_class = reinterpret_cast<jclass>(env->NewGlobalRef(native_library_class));
212 s_display_alert_msg = env->GetStaticMethodID(s_native_library_class, "displayAlertMsg",
213 "(Ljava/lang/String;Ljava/lang/String;Z)Z");
214 s_do_rumble = env->GetStaticMethodID(s_native_library_class, "rumble", "(ID)V");
215 s_get_update_touch_pointer =
216 env->GetStaticMethodID(s_native_library_class, "updateTouchPointer", "()V");
217 env->DeleteLocalRef(native_library_class);
218
219 const jclass game_file_class = env->FindClass("org/dolphinemu/dolphinemu/model/GameFile");
220 s_game_file_class = reinterpret_cast<jclass>(env->NewGlobalRef(game_file_class));
221 s_game_file_pointer = env->GetFieldID(game_file_class, "mPointer", "J");
222 s_game_file_constructor = env->GetMethodID(game_file_class, "<init>", "(J)V");
223 env->DeleteLocalRef(game_file_class);
224
225 const jclass game_file_cache_class =
226 env->FindClass("org/dolphinemu/dolphinemu/model/GameFileCache");
227 s_game_file_cache_class = reinterpret_cast<jclass>(env->NewGlobalRef(game_file_cache_class));
228 s_game_file_cache_pointer = env->GetFieldID(game_file_cache_class, "mPointer", "J");
229 env->DeleteLocalRef(game_file_cache_class);
230
231 const jclass analytics_class = env->FindClass("org/dolphinemu/dolphinemu/utils/Analytics");
232 s_analytics_class = reinterpret_cast<jclass>(env->NewGlobalRef(analytics_class));
233 s_send_analytics_report =
234 env->GetStaticMethodID(s_analytics_class, "sendReport", "(Ljava/lang/String;[B)V");
235 s_get_analytics_value = env->GetStaticMethodID(s_analytics_class, "getValue",
236 "(Ljava/lang/String;)Ljava/lang/String;");
237 env->DeleteLocalRef(analytics_class);
238
239 const jclass ini_file_class = env->FindClass("org/dolphinemu/dolphinemu/utils/IniFile");
240 s_ini_file_class = reinterpret_cast<jclass>(env->NewGlobalRef(ini_file_class));
241 s_ini_file_pointer = env->GetFieldID(ini_file_class, "mPointer", "J");
242 env->DeleteLocalRef(ini_file_class);
243
244 const jclass ini_file_section_class =
245 env->FindClass("org/dolphinemu/dolphinemu/utils/IniFile$Section");
246 s_ini_file_section_class = reinterpret_cast<jclass>(env->NewGlobalRef(ini_file_section_class));
247 s_ini_file_section_pointer = env->GetFieldID(ini_file_section_class, "mPointer", "J");
248 s_ini_file_section_constructor = env->GetMethodID(
249 ini_file_section_class, "<init>", "(Lorg/dolphinemu/dolphinemu/utils/IniFile;J)V");
250 env->DeleteLocalRef(ini_file_section_class);
251
252 const jclass map_class = env->FindClass("java/util/LinkedHashMap");
253 s_linked_hash_map_class = reinterpret_cast<jclass>(env->NewGlobalRef(map_class));
254 s_linked_hash_map_init = env->GetMethodID(s_linked_hash_map_class, "<init>", "(I)V");
255 s_linked_hash_map_put = env->GetMethodID(
256 s_linked_hash_map_class, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
257
258 const jclass compress_cb_class =
259 env->FindClass("org/dolphinemu/dolphinemu/utils/CompressCallback");
260 s_compress_cb_class = reinterpret_cast<jclass>(env->NewGlobalRef(compress_cb_class));
261 s_compress_cb_run = env->GetMethodID(s_compress_cb_class, "run", "(Ljava/lang/String;F)Z");
262
263 const jclass content_handler_class =
264 env->FindClass("org/dolphinemu/dolphinemu/utils/ContentHandler");
265 s_content_handler_class = reinterpret_cast<jclass>(env->NewGlobalRef(content_handler_class));
266 s_content_handler_open_fd = env->GetStaticMethodID(s_content_handler_class, "openFd",
267 "(Ljava/lang/String;Ljava/lang/String;)I");
268 s_content_handler_delete =
269 env->GetStaticMethodID(s_content_handler_class, "delete", "(Ljava/lang/String;)Z");
270
271 return JNI_VERSION;
272 }
273
JNI_OnUnload(JavaVM * vm,void * reserved)274 void JNI_OnUnload(JavaVM* vm, void* reserved)
275 {
276 JNIEnv* env;
277 if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION) != JNI_OK)
278 return;
279
280 env->DeleteGlobalRef(s_native_library_class);
281 env->DeleteGlobalRef(s_game_file_class);
282 env->DeleteGlobalRef(s_game_file_cache_class);
283 env->DeleteGlobalRef(s_analytics_class);
284 env->DeleteGlobalRef(s_linked_hash_map_class);
285 env->DeleteGlobalRef(s_ini_file_class);
286 env->DeleteGlobalRef(s_ini_file_section_class);
287 env->DeleteGlobalRef(s_compress_cb_class);
288 env->DeleteGlobalRef(s_content_handler_class);
289 }
290
291 #ifdef __cplusplus
292 }
293 #endif
294