Commit b6d40b6e516b293855f5d616d8bad56e81240abd

Authored by perry.werneck@gmail.com
1 parent 1a231040

Android: Serializando acesso à JNI

android/jni/globals.h
@@ -46,28 +46,36 @@ @@ -46,28 +46,36 @@
46 #define PW3270_JNI_END pw3270_env = NULL; pw3270_obj = NULL; 46 #define PW3270_JNI_END pw3270_env = NULL; pw3270_obj = NULL;
47 */ 47 */
48 48
49 - #define PW3270_JNI_BEGIN pw3270_env = env; pw3270_obj = obj; \  
50 - __android_log_print(ANDROID_LOG_VERBOSE, PACKAGE_NAME, "%s.begin env=%p obj=%p",__FUNCTION__,env,obj); 49 + #define PW3270_JNI_BEGIN __android_log_print(ANDROID_LOG_VERBOSE, PACKAGE_NAME, "%s.lock env=%p obj=%p",__FUNCTION__,env,obj); \
  50 + pw3270_jni_lock(env,obj);
51 51
52 - #define PW3270_JNI_END __android_log_print(ANDROID_LOG_VERBOSE, PACKAGE_NAME, "%s.end env=%p obj=%p",__FUNCTION__,pw3270_env,pw3270_obj); \  
53 - pw3270_env = NULL; pw3270_obj = NULL; 52 + #define PW3270_JNI_END __android_log_print(ANDROID_LOG_VERBOSE, PACKAGE_NAME, "%s.unlock env=%p obj=%p",__FUNCTION__,pw3270_jni_active->env,pw3270_jni_active->obj); \
  53 + pw3270_jni_unlock();
54 54
55 - #define PW3270_JNI_ENV pw3270_env  
56 - #define PW3270_JNI_OBJ pw3270_obj 55 + #define PW3270_JNI_ENV pw3270_jni_active->env
  56 + #define PW3270_JNI_OBJ pw3270_jni_active->obj
57 57
58 #define PW3270_SESSION lib3270_get_default_session_handle() 58 #define PW3270_SESSION lib3270_get_default_session_handle()
59 59
60 - #define pw3270_jni_call_void(name, sig, ...) pw3270_env->CallVoidMethod(pw3270_obj,lib3270_getmethodID(name,sig), __VA_ARGS__)  
61 - #define pw3270_jni_call_int(name, sig, ...) pw3270_env->CallIntMethod(pw3270_obj,lib3270_getmethodID(name,sig), __VA_ARGS__)  
62 - #define pw3270_jni_new_string(str) pw3270_env->NewStringUTF(str)  
63 - #define pw3270_jni_new_byte_array(len) pw3270_env->NewByteArray(len) 60 + #define pw3270_jni_call_void(name, sig, ...) pw3270_jni_active->env->CallVoidMethod(pw3270_jni_active->obj,lib3270_getmethodID(name,sig), __VA_ARGS__)
  61 + #define pw3270_jni_call_int(name, sig, ...) pw3270_jni_active->env->CallIntMethod(pw3270_jni_active->obj,lib3270_getmethodID(name,sig), __VA_ARGS__)
  62 + #define pw3270_jni_new_string(str) pw3270_jni_active->env->NewStringUTF(str)
  63 + #define pw3270_jni_new_byte_array(len) pw3270_jni_active->env->NewByteArray(len)
  64 +
  65 + typedef struct _pw3270_jni
  66 + {
  67 + struct _pw3270_jni * parent;
  68 + JNIEnv * env;
  69 + jobject obj;
  70 + } PW3270_JNI;
64 71
65 /*--[ Globals ]--------------------------------------------------------------------------------------*/ 72 /*--[ Globals ]--------------------------------------------------------------------------------------*/
66 73
67 - extern JNIEnv * pw3270_env;  
68 - extern jobject pw3270_obj;  
69 74
  75 + extern PW3270_JNI *pw3270_jni_active;
70 76
71 - jmethodID lib3270_getmethodID(const char *name, const char *sig); 77 + void pw3270_jni_lock(JNIEnv *env, jobject obj);
  78 + void pw3270_jni_unlock();
72 79
  80 + jmethodID lib3270_getmethodID(const char *name, const char *sig);
73 81
android/jni/main.cpp
@@ -28,6 +28,7 @@ @@ -28,6 +28,7 @@
28 28
29 #include "globals.h" 29 #include "globals.h"
30 #include <stdio.h> 30 #include <stdio.h>
  31 + #include <pthread.h>
31 #include <string.h> 32 #include <string.h>
32 #include <lib3270/config.h> 33 #include <lib3270/config.h>
33 #include <lib3270/popup.h> 34 #include <lib3270/popup.h>
@@ -45,29 +46,28 @@ @@ -45,29 +46,28 @@
45 46
46 /*--[ Globals ]--------------------------------------------------------------------------------------*/ 47 /*--[ Globals ]--------------------------------------------------------------------------------------*/
47 48
48 - const char * java_class_name = "br/com/bb/pw3270/lib3270";  
49 - JNIEnv * pw3270_env = NULL;  
50 - jobject pw3270_obj = NULL;  
51 - 49 + const char * java_class_name = "br/com/bb/pw3270/lib3270";
  50 + PW3270_JNI * pw3270_jni_active = NULL;
  51 + static pthread_mutex_t mutex;
52 52
53 /*--[ Implement ]------------------------------------------------------------------------------------*/ 53 /*--[ Implement ]------------------------------------------------------------------------------------*/
54 54
55 jmethodID lib3270_getmethodID(const char *name, const char *sig) 55 jmethodID lib3270_getmethodID(const char *name, const char *sig)
56 { 56 {
57 - if(!pw3270_env) 57 + if(!pw3270_jni_active)
58 { 58 {
59 __android_log_print(ANDROID_LOG_ERROR, PACKAGE_NAME, "%s(%s,%s) called outside jni environment",__FUNCTION__,name,sig); 59 __android_log_print(ANDROID_LOG_ERROR, PACKAGE_NAME, "%s(%s,%s) called outside jni environment",__FUNCTION__,name,sig);
60 return NULL; 60 return NULL;
61 } 61 }
62 62
63 - return pw3270_env->GetMethodID(pw3270_env->GetObjectClass(pw3270_obj), name, sig ); 63 + return PW3270_JNI_ENV->GetMethodID(PW3270_JNI_ENV->GetObjectClass(PW3270_JNI_OBJ), name, sig );
64 } 64 }
65 65
66 static void post_message(int msgid, int arg1 = 0, int arg2 = 0) 66 static void post_message(int msgid, int arg1 = 0, int arg2 = 0)
67 { 67 {
68 - trace("%s: pw3270_env=%p pw3270_obj=%p",__FUNCTION__,pw3270_env,pw3270_obj); 68 + trace("%s: pw3270_env=%p pw3270_obj=%p",__FUNCTION__,PW3270_JNI_ENV,PW3270_JNI_OBJ);
69 69
70 - if(pw3270_env) 70 + if(pw3270_jni_active)
71 pw3270_jni_call_void("postMessage", "(III)V",(jint) msgid, (jint) arg1, (jint) arg2); 71 pw3270_jni_call_void("postMessage", "(III)V",(jint) msgid, (jint) arg1, (jint) arg2);
72 } 72 }
73 73
@@ -135,7 +135,7 @@ static int write_buffer(H3270 *session, unsigned const char *buf, int len) @@ -135,7 +135,7 @@ static int write_buffer(H3270 *session, unsigned const char *buf, int len)
135 { 135 {
136 jbyteArray buffer = pw3270_jni_new_byte_array(len); 136 jbyteArray buffer = pw3270_jni_new_byte_array(len);
137 137
138 - pw3270_env->SetByteArrayRegion(buffer, 0, len, (jbyte*) buf); 138 + PW3270_JNI_ENV->SetByteArrayRegion(buffer, 0, len, (jbyte*) buf);
139 139
140 rc = pw3270_jni_call_int("send_data", "([BI)I", buffer, (jint) len ); 140 rc = pw3270_jni_call_int("send_data", "([BI)I", buffer, (jint) len );
141 } 141 }
@@ -259,6 +259,8 @@ JNIEXPORT jint JNICALL Java_br_com_bb_pw3270_lib3270_init(JNIEnv *env, jclass ob @@ -259,6 +259,8 @@ JNIEXPORT jint JNICALL Java_br_com_bb_pw3270_lib3270_init(JNIEnv *env, jclass ob
259 { 259 {
260 H3270 * session = lib3270_session_new(""); 260 H3270 * session = lib3270_session_new("");
261 261
  262 + pthread_mutex_init(&mutex,NULL);
  263 +
262 PW3270_JNI_BEGIN 264 PW3270_JNI_BEGIN
263 265
264 __android_log_print(ANDROID_LOG_DEBUG, PACKAGE_NAME, "Initializing session %p",session); 266 __android_log_print(ANDROID_LOG_DEBUG, PACKAGE_NAME, "Initializing session %p",session);
@@ -280,18 +282,10 @@ JNIEXPORT jint JNICALL Java_br_com_bb_pw3270_lib3270_init(JNIEnv *env, jclass ob @@ -280,18 +282,10 @@ JNIEXPORT jint JNICALL Java_br_com_bb_pw3270_lib3270_init(JNIEnv *env, jclass ob
280 return 0; 282 return 0;
281 } 283 }
282 284
283 -/*  
284 -JNIEXPORT jint JNICALL Java_br_com_bb_pw3270_lib3270_processEvents(JNIEnv *env, jobject obj) 285 +JNIEXPORT jint JNICALL Java_br_com_bb_pw3270_lib3270_deinit(JNIEnv *env, jclass obj)
285 { 286 {
286 - PW3270_JNI_BEGIN  
287 -  
288 - lib3270_main_iterate(session,1);  
289 -  
290 - PW3270_JNI_END  
291 -  
292 - return 0; 287 + pthread_mutex_destroy(&mutex);
293 } 288 }
294 -*/  
295 289
296 JNIEXPORT jboolean JNICALL Java_br_com_bb_pw3270_lib3270_isConnected(JNIEnv *env, jobject obj) 290 JNIEXPORT jboolean JNICALL Java_br_com_bb_pw3270_lib3270_isConnected(JNIEnv *env, jobject obj)
297 { 291 {
@@ -354,8 +348,42 @@ JNIEXPORT void JNICALL Java_br_com_bb_pw3270_lib3270_procRecvdata(JNIEnv *env, j @@ -354,8 +348,42 @@ JNIEXPORT void JNICALL Java_br_com_bb_pw3270_lib3270_procRecvdata(JNIEnv *env, j
354 348
355 trace("Liberando %d bytes",(size_t) sz); 349 trace("Liberando %d bytes",(size_t) sz);
356 350
357 - pw3270_env->ReleaseByteArrayElements(buffer, (signed char *) netrbuf, 0); 351 + PW3270_JNI_ENV->ReleaseByteArrayElements(buffer, (signed char *) netrbuf, 0);
358 352
359 PW3270_JNI_END 353 PW3270_JNI_END
360 354
361 } 355 }
  356 +
  357 +void pw3270_jni_lock(JNIEnv *env, jobject obj)
  358 +{
  359 + PW3270_JNI *datablock = (PW3270_JNI *) lib3270_malloc(sizeof(PW3270_JNI));
  360 +
  361 + datablock->parent = pw3270_jni_active;
  362 + datablock->env = env;
  363 + datablock->obj = obj;
  364 +
  365 + if(!pw3270_jni_active || pw3270_jni_active->env != env)
  366 + {
  367 + // Environment change, lock
  368 + trace("%s: Environment has changed",__FUNCTION__);
  369 + pthread_mutex_lock(&mutex);
  370 + }
  371 +
  372 + pw3270_jni_active = datablock;
  373 +}
  374 +
  375 +void pw3270_jni_unlock(void)
  376 +{
  377 + PW3270_JNI *datablock = pw3270_jni_active;
  378 + pw3270_jni_active = datablock->parent;
  379 +
  380 + if(!pw3270_jni_active || pw3270_jni_active->env != datablock->env)
  381 + {
  382 + // Environment change, unlock
  383 + trace("%s: Environment has changed",__FUNCTION__);
  384 + pthread_mutex_unlock(&mutex);
  385 + }
  386 +
  387 + lib3270_free(datablock);
  388 +}
  389 +
android/jni/misc.cpp
@@ -57,3 +57,4 @@ JNIEXPORT void JNICALL Java_br_com_bb_pw3270_lib3270_setToggle(JNIEnv *env, jobj @@ -57,3 +57,4 @@ JNIEXPORT void JNICALL Java_br_com_bb_pw3270_lib3270_setToggle(JNIEnv *env, jobj
57 PW3270_JNI_END 57 PW3270_JNI_END
58 58
59 } 59 }
  60 +
android/jni/text.cpp
@@ -35,8 +35,8 @@ @@ -35,8 +35,8 @@
35 static jbyteArray retString(const char *txt) 35 static jbyteArray retString(const char *txt)
36 { 36 {
37 size_t len = strlen(txt); 37 size_t len = strlen(txt);
38 - jbyteArray ret = pw3270_env->NewByteArray(len);  
39 - pw3270_env->SetByteArrayRegion(ret, 0, len, (jbyte*) txt); 38 + jbyteArray ret = PW3270_JNI_ENV->NewByteArray(len);
  39 + PW3270_JNI_ENV->SetByteArrayRegion(ret, 0, len, (jbyte*) txt);
40 return ret; 40 return ret;
41 } 41 }
42 42
android/src/br/com/bb/pw3270/lib3270.java
@@ -399,6 +399,7 @@ public class lib3270 @@ -399,6 +399,7 @@ public class lib3270
399 399
400 /*---[ Native calls ]----------------------------------------------------*/ 400 /*---[ Native calls ]----------------------------------------------------*/
401 static private native int init(); 401 static private native int init();
  402 + static private native int deinit();
402 403
403 private native int processEvents(); 404 private native int processEvents();
404 // private native int do_connect(); 405 // private native int do_connect();