[Android] [PATCH 2/3] jni: factorize attach/detach thread and get_env

Thomas Guillem tom at gllm.fr
Tue Oct 14 16:56:54 CEST 2014


add jni_attach_thread, jni_detach_thread, jni_get_env in libvlcjni.c.

A name should be specified when a thread is attached to Java. Art (on
android-L) was warning us about. jni_attach_thread call AttachCurrentThread
with a JavaVMAttachArgs containing JNI_VERSION and THREAD_NAME.
---
 vlc-android/jni/aout.c                 | 27 ++++++++++++++-------------
 vlc-android/jni/libvlcjni-util.c       | 12 +++++++-----
 vlc-android/jni/libvlcjni.c            | 34 +++++++++++++++++++++++++++++++---
 vlc-android/jni/native_crash_handler.c |  9 +++++----
 vlc-android/jni/vout.c                 | 13 +++++++------
 5 files changed, 64 insertions(+), 31 deletions(-)

diff --git a/vlc-android/jni/aout.c b/vlc-android/jni/aout.c
index bc146b4..af13111 100644
--- a/vlc-android/jni/aout.c
+++ b/vlc-android/jni/aout.c
@@ -42,8 +42,9 @@ typedef struct
     jbyteArray buffer;  /// Raw audio data to be played
 } aout_sys_t;
 
-/** Unique Java VM instance, as defined in libvlcjni.c */
-extern JavaVM *myVm;
+#define THREAD_NAME "jni_aout"
+extern int jni_attach_thread(JNIEnv **env, const char *thread_name);
+extern void jni_detach_thread();
 
 int aout_open(void **opaque, char *format, unsigned *rate, unsigned *nb_channels)
 {
@@ -60,7 +61,7 @@ int aout_open(void **opaque, char *format, unsigned *rate, unsigned *nb_channels
           *nb_channels, format, *rate);
 
     JNIEnv *p_env;
-    if ((*myVm)->AttachCurrentThread (myVm, &p_env, NULL) != 0)
+    if (jni_attach_thread (&p_env, THREAD_NAME) != 0)
     {
         LOGE("Could not attach the display thread to the JVM !");
         goto eattach;
@@ -141,11 +142,11 @@ int aout_open(void **opaque, char *format, unsigned *rate, unsigned *nb_channels
     // Get the play methodId
     p_sys->play = (*p_env)->GetMethodID (p_env, cls, "playAudio", "([BI)V");
     assert (p_sys->play != NULL);
-    (*myVm)->DetachCurrentThread (myVm);
+    jni_detach_thread ();
     return 0;
 
 error:
-    (*myVm)->DetachCurrentThread (myVm);
+    jni_detach_thread ();
 eattach:
     *opaque = NULL;
     free (p_sys);
@@ -165,7 +166,7 @@ void aout_play(void *opaque, const void *samples, unsigned count, int64_t pts)
      * because it will be killed before aout_close is called.
      * aout_close will actually be called in an different thread!
      */
-    (*myVm)->AttachCurrentThread (myVm, &p_env, NULL);
+    jni_attach_thread (&p_env, THREAD_NAME);
 
     (*p_env)->SetByteArrayRegion (p_env, p_sys->buffer, 0,
                                   2 /*nb_channels*/ * count * sizeof (uint16_t),
@@ -186,7 +187,7 @@ void aout_play(void *opaque, const void *samples, unsigned count, int64_t pts)
                               FRAME_SIZE);
     // FIXME: check for errors
 
-    (*myVm)->DetachCurrentThread (myVm);
+    jni_detach_thread ();
 }
 
 void aout_pause(void *opaque, int64_t pts)
@@ -196,7 +197,7 @@ void aout_pause(void *opaque, int64_t pts)
     assert(p_sys);
 
     JNIEnv *p_env;
-    (*myVm)->AttachCurrentThread (myVm, &p_env, NULL);
+    jni_attach_thread (&p_env, THREAD_NAME);
 
     // Call the pause function.
     jclass cls = (*p_env)->GetObjectClass (p_env, p_sys->j_libVlc);
@@ -213,7 +214,7 @@ void aout_pause(void *opaque, int64_t pts)
         (*p_env)->ExceptionClear (p_env);
     }
 
-    (*myVm)->DetachCurrentThread (myVm);
+    jni_detach_thread ();
 }
 
 void aout_close(void *opaque)
@@ -224,7 +225,7 @@ void aout_close(void *opaque)
     assert(p_sys->buffer);
 
     JNIEnv *p_env;
-    (*myVm)->AttachCurrentThread (myVm, &p_env, NULL);
+    jni_attach_thread (&p_env, THREAD_NAME);
 
     // Call the close function.
     jclass cls = (*p_env)->GetObjectClass (p_env, p_sys->j_libVlc);
@@ -242,17 +243,17 @@ void aout_close(void *opaque)
     }
 
     (*p_env)->DeleteGlobalRef (p_env, p_sys->buffer);
-    (*myVm)->DetachCurrentThread (myVm);
+    jni_detach_thread ();
     free (p_sys);
 }
 
 int aout_get_native_sample_rate(void)
 {
     JNIEnv *p_env;
-    (*myVm)->AttachCurrentThread (myVm, &p_env, NULL);
+    jni_attach_thread (&p_env, THREAD_NAME);
     jclass cls = (*p_env)->FindClass (p_env, "android/media/AudioTrack");
     jmethodID method = (*p_env)->GetStaticMethodID (p_env, cls, "getNativeOutputSampleRate", "(I)I");
     int sample_rate = (*p_env)->CallStaticIntMethod (p_env, cls, method, 3); // AudioManager.STREAM_MUSIC
-    (*myVm)->DetachCurrentThread (myVm);
+    jni_detach_thread ();
     return sample_rate;
 }
diff --git a/vlc-android/jni/libvlcjni-util.c b/vlc-android/jni/libvlcjni-util.c
index 37f4d2d..205d59d 100644
--- a/vlc-android/jni/libvlcjni-util.c
+++ b/vlc-android/jni/libvlcjni-util.c
@@ -36,8 +36,10 @@ static jobject debugBufferInstance = NULL;
 // FIXME: use atomics
 static bool buffer_logging;
 
-/** Unique Java VM instance, as defined in libvlcjni.c */
-extern JavaVM *myVm;
+#define THREAD_NAME "libvlcjni-util"
+extern int jni_attach_thread(JNIEnv **env, const char *thread_name);
+extern void jni_detach_thread();
+extern int jni_get_env(JNIEnv **env);
 
 jint getInt(JNIEnv *env, jobject thiz, const char* field) {
     jclass clazz = (*env)->GetObjectClass(env, thiz);
@@ -151,8 +153,8 @@ static void debug_buffer_log(void *data, int level, const char *fmt, va_list ap)
     bool isAttached = false;
     JNIEnv *env = NULL;
 
-    if ((*myVm)->GetEnv(myVm, (void**) &env, JNI_VERSION_1_2) < 0) {
-        if ((*myVm)->AttachCurrentThread(myVm, &env, NULL) < 0)
+    if (jni_get_env(&env) < 0) {
+        if (jni_attach_thread(&env, THREAD_NAME) < 0)
             return;
         isAttached = true;
     }
@@ -179,7 +181,7 @@ static void debug_buffer_log(void *data, int level, const char *fmt, va_list ap)
     free(psz_msg);
 
     if (isAttached)
-        (*myVm)->DetachCurrentThread(myVm);
+        jni_detach_thread();
 }
 
 void debug_log(void *data, int level, const libvlc_log_t *ctx, const char *fmt, va_list ap)
diff --git a/vlc-android/jni/libvlcjni.c b/vlc-android/jni/libvlcjni.c
index e67e361..bfa9a8a 100644
--- a/vlc-android/jni/libvlcjni.c
+++ b/vlc-android/jni/libvlcjni.c
@@ -54,6 +54,11 @@
 
 #define VLC_JNI_VERSION JNI_VERSION_1_2
 
+#define THREAD_NAME "libvlcjni"
+int jni_attach_thread(JNIEnv **env, const char *thread_name);
+void jni_detach_thread();
+int jni_get_env(JNIEnv **env);
+
 static void add_media_options(libvlc_media_t *p_md, JNIEnv *env, jobjectArray mediaOptions)
 {
     int stringCount = (*env)->GetArrayLength(env, mediaOptions);
@@ -123,8 +128,8 @@ static void vlc_event_callback(const libvlc_event_t *ev, void *data)
     if (eventHandlerInstance == NULL)
         return;
 
-    if ((*myVm)->GetEnv(myVm, (void**) &env, VLC_JNI_VERSION) < 0) {
-        if ((*myVm)->AttachCurrentThread(myVm, &env, NULL) < 0)
+    if (jni_get_env(&env) < 0) {
+        if (jni_attach_thread(&env, THREAD_NAME) < 0)
             return;
         isAttached = true;
     }
@@ -199,7 +204,7 @@ static void vlc_event_callback(const libvlc_event_t *ev, void *data)
 end:
     (*env)->DeleteLocalRef(env, bundle);
     if (isAttached)
-        (*myVm)->DetachCurrentThread(myVm);
+        jni_detach_thread();
 }
 
 jint JNI_OnLoad(JavaVM *vm, void *reserved)
@@ -219,6 +224,29 @@ void JNI_OnUnload(JavaVM* vm, void* reserved) {
     pthread_cond_destroy(&vout_android_surf_attached);
 }
 
+int jni_attach_thread(JNIEnv **env, const char *thread_name)
+{
+    JavaVMAttachArgs args;
+    jint result;
+
+    args.version = VLC_JNI_VERSION;
+    args.name = thread_name;
+    args.group = NULL;
+
+    result = (*myVm)->AttachCurrentThread(myVm, env, &args);
+    return result == JNI_OK ? 0 : -1;
+}
+
+void jni_detach_thread()
+{
+    (*myVm)->DetachCurrentThread(myVm);
+}
+
+int jni_get_env(JNIEnv **env)
+{
+    return (*myVm)->GetEnv(myVm, (void **)&env, VLC_JNI_VERSION) == JNI_OK ? 0 : -1;
+}
+
 // FIXME: use atomics
 static bool verbosity;
 
diff --git a/vlc-android/jni/native_crash_handler.c b/vlc-android/jni/native_crash_handler.c
index 04090ee..2cb1590 100644
--- a/vlc-android/jni/native_crash_handler.c
+++ b/vlc-android/jni/native_crash_handler.c
@@ -25,8 +25,9 @@
 static struct sigaction old_actions[NSIG];
 static jobject j_libVLC;
 
-/** Unique Java VM instance, as defined in libvlcjni.c */
-extern JavaVM *myVm;
+#define THREAD_NAME "native_crash_handler"
+extern int jni_attach_thread(JNIEnv **env, const char *thread_name);
+extern void jni_detach_thread();
 
 // Monitored signals.
 static const int monitored_signals[] = {
@@ -51,14 +52,14 @@ void sigaction_callback(int signal, siginfo_t *info, void *reserved)
 {
     // Call the Java LibVLC method that handle the crash.
     JNIEnv *env;
-    (*myVm)->AttachCurrentThread(myVm, &env, NULL);
+    jni_attach_thread(&env, THREAD_NAME);
 
     jclass cls = (*env)->GetObjectClass(env, j_libVLC);
     jmethodID methodId = (*env)->GetMethodID(env, cls, "onNativeCrash", "()V");
     (*env)->CallVoidMethod(env, j_libVLC, methodId);
 
     (*env)->DeleteLocalRef(env, cls);
-    (*myVm)->DetachCurrentThread(myVm);
+    jni_detach_thread();
 
     // Call the old signal handler.
     old_actions[signal].sa_handler(signal);
diff --git a/vlc-android/jni/vout.c b/vlc-android/jni/vout.c
index f2f4346..e178bcb 100644
--- a/vlc-android/jni/vout.c
+++ b/vlc-android/jni/vout.c
@@ -23,8 +23,9 @@
 
 #include <jni.h>
 
-/** Unique Java VM instance, as defined in libvlcjni.c */
-extern JavaVM *myVm;
+#define THREAD_NAME "jni_vout"
+extern int jni_attach_thread(JNIEnv **env, const char *thread_name);
+extern void jni_detach_thread();
 
 pthread_mutex_t vout_android_lock;
 pthread_cond_t vout_android_surf_attached;
@@ -65,14 +66,14 @@ void jni_EventHardwareAccelerationError()
         return;
 
     JNIEnv *env;
-    (*myVm)->AttachCurrentThread(myVm, &env, NULL);
+    jni_attach_thread(&env, THREAD_NAME);
 
     jclass cls = (*env)->GetObjectClass(env, vout_android_gui);
     jmethodID methodId = (*env)->GetMethodID(env, cls, "eventHardwareAccelerationError", "()V");
     (*env)->CallVoidMethod(env, vout_android_gui, methodId);
 
     (*env)->DeleteLocalRef(env, cls);
-    (*myVm)->DetachCurrentThread(myVm);
+    jni_detach_thread();
 }
 
 void jni_SetAndroidSurfaceSizeEnv(JNIEnv *p_env, int width, int height, int visible_width, int visible_height, int sar_num, int sar_den)
@@ -92,10 +93,10 @@ void jni_SetAndroidSurfaceSize(int width, int height, int visible_width, int vis
 {
     JNIEnv *p_env;
 
-    (*myVm)->AttachCurrentThread (myVm, &p_env, NULL);
+    jni_attach_thread(&p_env, THREAD_NAME);
     jni_SetAndroidSurfaceSizeEnv(p_env, width, height, visible_width, visible_height, sar_num, sar_den);
 
-    (*myVm)->DetachCurrentThread (myVm);
+    jni_detach_thread();
 }
 
 bool jni_IsVideoPlayerActivityCreated() {
-- 
2.1.0



More information about the Android mailing list