Commit b6d40b6e516b293855f5d616d8bad56e81240abd

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

Android: Serializando acesso à JNI

android/jni/globals.h
... ... @@ -46,28 +46,36 @@
46 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 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 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 28  
29 29 #include "globals.h"
30 30 #include <stdio.h>
  31 + #include <pthread.h>
31 32 #include <string.h>
32 33 #include <lib3270/config.h>
33 34 #include <lib3270/popup.h>
... ... @@ -45,29 +46,28 @@
45 46  
46 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 53 /*--[ Implement ]------------------------------------------------------------------------------------*/
54 54  
55 55 jmethodID lib3270_getmethodID(const char *name, const char *sig)
56 56 {
57   - if(!pw3270_env)
  57 + if(!pw3270_jni_active)
58 58 {
59 59 __android_log_print(ANDROID_LOG_ERROR, PACKAGE_NAME, "%s(%s,%s) called outside jni environment",__FUNCTION__,name,sig);
60 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 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 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 135 {
136 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 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 259 {
260 260 H3270 * session = lib3270_session_new("");
261 261  
  262 + pthread_mutex_init(&mutex,NULL);
  263 +
262 264 PW3270_JNI_BEGIN
263 265  
264 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 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 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 348  
355 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 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 57 PW3270_JNI_END
58 58  
59 59 }
  60 +
... ...
android/jni/text.cpp
... ... @@ -35,8 +35,8 @@
35 35 static jbyteArray retString(const char *txt)
36 36 {
37 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 40 return ret;
41 41 }
42 42  
... ...
android/src/br/com/bb/pw3270/lib3270.java
... ... @@ -399,6 +399,7 @@ public class lib3270
399 399  
400 400 /*---[ Native calls ]----------------------------------------------------*/
401 401 static private native int init();
  402 + static private native int deinit();
402 403  
403 404 private native int processEvents();
404 405 // private native int do_connect();
... ...