Commit e8078cdb authored by Thomas Guillem's avatar Thomas Guillem

fix android7 crash

android7 doesn't have NewWeakGlobalRef, use a compat function for this API and
before.
parent 6b711de4
...@@ -48,7 +48,8 @@ struct java_event_thread { ...@@ -48,7 +48,8 @@ struct java_event_thread {
pthread_cond_t cond; pthread_cond_t cond;
pthread_t thread; pthread_t thread;
EVENT_QUEUE queue; EVENT_QUEUE queue;
jweak jobj; jweak jweak;
jobject jweakCompat;
}; };
static void * static void *
...@@ -83,9 +84,15 @@ JavaEventThread_thread(void *data) ...@@ -83,9 +84,15 @@ JavaEventThread_thread(void *data)
pthread_mutex_unlock(&p_java_event_thread->lock); pthread_mutex_unlock(&p_java_event_thread->lock);
(*env)->CallVoidMethod(env, p_java_event_thread->jobj, if (p_java_event_thread->jweak)
fields.VLCObject.dispatchEventFromNativeID, (*env)->CallVoidMethod(env, p_java_event_thread->jweak,
p_jevent->type, p_jevent->arg1, p_jevent->arg2); fields.VLCObject.dispatchEventFromNativeID,
p_jevent->type, p_jevent->arg1, p_jevent->arg2);
else
(*env)->CallStaticVoidMethod(env, fields.VLCObject.clazz,
fields.VLCObject.dispatchEventFromWeakNativeID,
p_java_event_thread->jweakCompat,
p_jevent->type, p_jevent->arg1, p_jevent->arg2);
pthread_mutex_lock(&p_java_event_thread->lock); pthread_mutex_lock(&p_java_event_thread->lock);
...@@ -112,9 +119,14 @@ end: ...@@ -112,9 +119,14 @@ end:
} }
java_event_thread * java_event_thread *
JavaEventThread_create(jweak jobj, bool b_sync) JavaEventThread_create(jweak jweak, jobject jweakCompat, bool b_sync)
{ {
java_event_thread *p_java_event_thread = calloc(1, sizeof(java_event_thread)); java_event_thread *p_java_event_thread;
if (!jweak && !jweakCompat)
return NULL;
p_java_event_thread = calloc(1, sizeof(java_event_thread));
if (!p_java_event_thread) if (!p_java_event_thread)
return NULL; return NULL;
...@@ -122,7 +134,8 @@ JavaEventThread_create(jweak jobj, bool b_sync) ...@@ -122,7 +134,8 @@ JavaEventThread_create(jweak jobj, bool b_sync)
pthread_cond_init(&p_java_event_thread->cond, NULL); pthread_cond_init(&p_java_event_thread->cond, NULL);
TAILQ_INIT(&p_java_event_thread->queue); TAILQ_INIT(&p_java_event_thread->queue);
p_java_event_thread->jobj = jobj; p_java_event_thread->jweak = jweak;
p_java_event_thread->jweakCompat = jweakCompat;
p_java_event_thread->b_run = true; p_java_event_thread->b_run = true;
p_java_event_thread->b_sync = b_sync; p_java_event_thread->b_sync = b_sync;
pthread_create(&p_java_event_thread->thread, NULL, pthread_create(&p_java_event_thread->thread, NULL,
......
...@@ -37,7 +37,8 @@ struct java_event ...@@ -37,7 +37,8 @@ struct java_event
/* if b_sync is true, calls to JavaEventThread_add will return only when events /* if b_sync is true, calls to JavaEventThread_add will return only when events
* are handled by Java Side */ * are handled by Java Side */
java_event_thread *JavaEventThread_create(jweak jobj, bool b_sync); java_event_thread *JavaEventThread_create(jweak jweak, jobject jweakCompat,
bool b_sync);
void JavaEventThread_destroy(java_event_thread *p_java_event_thread); void JavaEventThread_destroy(java_event_thread *p_java_event_thread);
int JavaEventThread_add(java_event_thread *p_java_event_thread, int JavaEventThread_add(java_event_thread *p_java_event_thread,
java_event *p_java_event); java_event *p_java_event);
......
...@@ -27,7 +27,8 @@ ...@@ -27,7 +27,8 @@
struct vlcjni_object_owner struct vlcjni_object_owner
{ {
jweak thiz; jweak weak;
jobject weakCompat;
libvlc_event_manager_t *p_event_manager; libvlc_event_manager_t *p_event_manager;
const int *p_events; const int *p_events;
...@@ -73,8 +74,18 @@ VLCJniObject_newFromLibVlc(JNIEnv *env, jobject thiz, ...@@ -73,8 +74,18 @@ VLCJniObject_newFromLibVlc(JNIEnv *env, jobject thiz,
p_obj->p_libvlc = p_libvlc; p_obj->p_libvlc = p_libvlc;
libvlc_retain(p_libvlc); libvlc_retain(p_libvlc);
p_obj->p_owner->thiz = (*env)->NewWeakGlobalRef(env, thiz); if (fields.VLCObject.getWeakReferenceID)
if (!p_obj->p_owner->thiz) {
jobject weakCompat = (*env)->CallObjectMethod(env, thiz,
fields.VLCObject.getWeakReferenceID);
if (weakCompat)
{
p_obj->p_owner->weakCompat = (*env)->NewGlobalRef(env, weakCompat);
(*env)->DeleteLocalRef(env, weakCompat);
}
} else
p_obj->p_owner->weak = (*env)->NewWeakGlobalRef(env, thiz);
if (!p_obj->p_owner->weak && !p_obj->p_owner->weakCompat)
goto error; goto error;
VLCJniObject_setInstance(env, thiz, p_obj); VLCJniObject_setInstance(env, thiz, p_obj);
...@@ -104,8 +115,13 @@ VLCJniObject_release(JNIEnv *env, jobject thiz, vlcjni_object *p_obj) ...@@ -104,8 +115,13 @@ VLCJniObject_release(JNIEnv *env, jobject thiz, vlcjni_object *p_obj)
if (p_obj->p_libvlc) if (p_obj->p_libvlc)
libvlc_release(p_obj->p_libvlc); libvlc_release(p_obj->p_libvlc);
if (p_obj->p_owner && p_obj->p_owner->thiz) if (p_obj->p_owner)
(*env)->DeleteWeakGlobalRef(env, p_obj->p_owner->thiz); {
if (p_obj->p_owner->weak)
(*env)->DeleteWeakGlobalRef(env, p_obj->p_owner->weak);
else if (p_obj->p_owner->weakCompat)
(*env)->DeleteGlobalRef(env, p_obj->p_owner->weakCompat);
}
free(p_obj->p_owner); free(p_obj->p_owner);
free(p_obj); free(p_obj);
...@@ -128,7 +144,8 @@ VLCJniObject_eventCallback(const libvlc_event_t *ev, void *data) ...@@ -128,7 +144,8 @@ VLCJniObject_eventCallback(const libvlc_event_t *ev, void *data)
if (!p_obj->p_owner->p_java_event_thread) if (!p_obj->p_owner->p_java_event_thread)
{ {
p_obj->p_owner->p_java_event_thread = p_obj->p_owner->p_java_event_thread =
JavaEventThread_create(p_obj->p_owner->thiz, true); JavaEventThread_create(p_obj->p_owner->weak,
p_obj->p_owner->weakCompat, true);
if (!p_obj->p_owner->p_java_event_thread) if (!p_obj->p_owner->p_java_event_thread)
return; return;
} }
......
...@@ -224,16 +224,18 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved) ...@@ -224,16 +224,18 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved)
pthread_mutex_init(&vout_android_lock, NULL); pthread_mutex_init(&vout_android_lock, NULL);
pthread_cond_init(&vout_android_surf_attached, NULL); pthread_cond_init(&vout_android_surf_attached, NULL);
#define GET_CLASS(clazz, str) do { \ #define GET_CLASS(clazz, str, b_globlal) do { \
(clazz) = (*env)->FindClass(env, (str)); \ (clazz) = (*env)->FindClass(env, (str)); \
if (!(clazz)) { \ if (!(clazz)) { \
LOGE("FindClass(%s) failed", (str)); \ LOGE("FindClass(%s) failed", (str)); \
return -1; \ return -1; \
} \ } \
(clazz) = (jclass) (*env)->NewGlobalRef(env, (clazz)); \ if (b_globlal) { \
if (!(clazz)) { \ (clazz) = (jclass) (*env)->NewGlobalRef(env, (clazz)); \
LOGE("NewGlobalRef(%s) failed", (str)); \ if (!(clazz)) { \
return -1; \ LOGE("NewGlobalRef(%s) failed", (str)); \
return -1; \
} \
} \ } \
} while (0) } while (0)
...@@ -245,20 +247,28 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved) ...@@ -245,20 +247,28 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved)
} \ } \
} while (0) } while (0)
jclass Version_clazz;
jfieldID SDK_INT_fieldID;
GET_CLASS(Version_clazz, "android/os/Build$VERSION", false);
GET_ID(GetStaticFieldID, SDK_INT_fieldID, Version_clazz, "SDK_INT", "I");
fields.SDK_INT = (*env)->GetStaticIntField(env, Version_clazz,
SDK_INT_fieldID);
GET_CLASS(fields.IllegalStateException.clazz, GET_CLASS(fields.IllegalStateException.clazz,
"java/lang/IllegalStateException"); "java/lang/IllegalStateException", true);
GET_CLASS(fields.IllegalArgumentException.clazz, GET_CLASS(fields.IllegalArgumentException.clazz,
"java/lang/IllegalArgumentException"); "java/lang/IllegalArgumentException", true);
GET_CLASS(fields.String.clazz, GET_CLASS(fields.String.clazz,
"java/lang/String"); "java/lang/String", true);
GET_CLASS(fields.LibVLC.clazz, GET_CLASS(fields.LibVLC.clazz,
"org/videolan/libvlc/LibVLC"); "org/videolan/libvlc/LibVLC", true);
GET_CLASS(fields.VLCObject.clazz, GET_CLASS(fields.VLCObject.clazz,
"org/videolan/libvlc/VLCObject"); "org/videolan/libvlc/VLCObject", true);
GET_CLASS(fields.Media.clazz, GET_CLASS(fields.Media.clazz,
"org/videolan/libvlc/Media"); "org/videolan/libvlc/Media", true);
GET_CLASS(fields.Media.Track.clazz, GET_CLASS(fields.Media.Track.clazz,
"org/videolan/libvlc/Media$Track"); "org/videolan/libvlc/Media$Track", true);
GET_ID(GetStaticMethodID, GET_ID(GetStaticMethodID,
fields.LibVLC.onNativeCrashID, fields.LibVLC.onNativeCrashID,
...@@ -275,6 +285,23 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved) ...@@ -275,6 +285,23 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved)
fields.VLCObject.clazz, fields.VLCObject.clazz,
"dispatchEventFromNative", "(IJJ)V"); "dispatchEventFromNative", "(IJJ)V");
if (fields.SDK_INT <= 7)
{
LOGE("fields.SDK_INT is less than 7: using compat WeakReference");
GET_ID(GetMethodID,
fields.VLCObject.getWeakReferenceID,
fields.VLCObject.clazz,
"getWeakReference", "()Ljava/lang/Object;");
GET_ID(GetStaticMethodID,
fields.VLCObject.dispatchEventFromWeakNativeID,
fields.VLCObject.clazz,
"dispatchEventFromWeakNative", "(Ljava/lang/Object;IJJ)V");
} else
{
fields.VLCObject.getWeakReferenceID = NULL;
fields.VLCObject.dispatchEventFromWeakNativeID = NULL;
}
GET_ID(GetStaticMethodID, GET_ID(GetStaticMethodID,
fields.Media.createAudioTrackFromNativeID, fields.Media.createAudioTrackFromNativeID,
fields.Media.clazz, fields.Media.clazz,
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <vlc/libvlc_media_list.h> #include <vlc/libvlc_media_list.h>
struct fields { struct fields {
jint SDK_INT;
struct { struct {
jclass clazz; jclass clazz;
} IllegalStateException; } IllegalStateException;
...@@ -43,6 +44,8 @@ struct fields { ...@@ -43,6 +44,8 @@ struct fields {
jclass clazz; jclass clazz;
jfieldID mInstanceID; jfieldID mInstanceID;
jmethodID dispatchEventFromNativeID; jmethodID dispatchEventFromNativeID;
jmethodID getWeakReferenceID;
jmethodID dispatchEventFromWeakNativeID;
} VLCObject; } VLCObject;
struct { struct {
struct { struct {
......
...@@ -23,6 +23,8 @@ package org.videolan.libvlc; ...@@ -23,6 +23,8 @@ package org.videolan.libvlc;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import java.lang.ref.WeakReference;
public abstract class VLCObject { public abstract class VLCObject {
private final static String TAG = "LibVLC/VlcObject"; private final static String TAG = "LibVLC/VlcObject";
...@@ -215,4 +217,14 @@ public abstract class VLCObject { ...@@ -215,4 +217,14 @@ public abstract class VLCObject {
mHandler.post(new EventRunnable(mEventListener, event)); mHandler.post(new EventRunnable(mEventListener, event));
} }
private final native void nativeDetachEvents(); private final native void nativeDetachEvents();
/* used only before API 7: substitute for NewWeakGlobalRef */
private Object getWeakReference() {
return new WeakReference<VLCObject>(this);
}
private static void dispatchEventFromWeakNative(Object weak, int eventType, long arg1, long arg2) {
VLCObject obj = ((WeakReference<VLCObject>)weak).get();
if (obj != null)
obj.dispatchEventFromNative(eventType, arg1, arg2);
}
} }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment