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 {
pthread_cond_t cond;
pthread_t thread;
EVENT_QUEUE queue;
jweak jobj;
jweak jweak;
jobject jweakCompat;
};
static void *
......@@ -83,9 +84,15 @@ JavaEventThread_thread(void *data)
pthread_mutex_unlock(&p_java_event_thread->lock);
(*env)->CallVoidMethod(env, p_java_event_thread->jobj,
fields.VLCObject.dispatchEventFromNativeID,
p_jevent->type, p_jevent->arg1, p_jevent->arg2);
if (p_java_event_thread->jweak)
(*env)->CallVoidMethod(env, p_java_event_thread->jweak,
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);
......@@ -112,9 +119,14 @@ end:
}
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)
return NULL;
......@@ -122,7 +134,8 @@ JavaEventThread_create(jweak jobj, bool b_sync)
pthread_cond_init(&p_java_event_thread->cond, NULL);
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_sync = b_sync;
pthread_create(&p_java_event_thread->thread, NULL,
......
......@@ -37,7 +37,8 @@ struct java_event
/* if b_sync is true, calls to JavaEventThread_add will return only when events
* 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);
int JavaEventThread_add(java_event_thread *p_java_event_thread,
java_event *p_java_event);
......
......@@ -27,7 +27,8 @@
struct vlcjni_object_owner
{
jweak thiz;
jweak weak;
jobject weakCompat;
libvlc_event_manager_t *p_event_manager;
const int *p_events;
......@@ -73,8 +74,18 @@ VLCJniObject_newFromLibVlc(JNIEnv *env, jobject thiz,
p_obj->p_libvlc = p_libvlc;
libvlc_retain(p_libvlc);
p_obj->p_owner->thiz = (*env)->NewWeakGlobalRef(env, thiz);
if (!p_obj->p_owner->thiz)
if (fields.VLCObject.getWeakReferenceID)
{
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;
VLCJniObject_setInstance(env, thiz, p_obj);
......@@ -104,8 +115,13 @@ VLCJniObject_release(JNIEnv *env, jobject thiz, vlcjni_object *p_obj)
if (p_obj->p_libvlc)
libvlc_release(p_obj->p_libvlc);
if (p_obj->p_owner && p_obj->p_owner->thiz)
(*env)->DeleteWeakGlobalRef(env, p_obj->p_owner->thiz);
if (p_obj->p_owner)
{
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);
......@@ -128,7 +144,8 @@ VLCJniObject_eventCallback(const libvlc_event_t *ev, void *data)
if (!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)
return;
}
......
......@@ -224,16 +224,18 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved)
pthread_mutex_init(&vout_android_lock, 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)); \
if (!(clazz)) { \
LOGE("FindClass(%s) failed", (str)); \
return -1; \
} \
(clazz) = (jclass) (*env)->NewGlobalRef(env, (clazz)); \
if (!(clazz)) { \
LOGE("NewGlobalRef(%s) failed", (str)); \
return -1; \
if (b_globlal) { \
(clazz) = (jclass) (*env)->NewGlobalRef(env, (clazz)); \
if (!(clazz)) { \
LOGE("NewGlobalRef(%s) failed", (str)); \
return -1; \
} \
} \
} while (0)
......@@ -245,20 +247,28 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved)
} \
} 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,
"java/lang/IllegalStateException");
"java/lang/IllegalStateException", true);
GET_CLASS(fields.IllegalArgumentException.clazz,
"java/lang/IllegalArgumentException");
"java/lang/IllegalArgumentException", true);
GET_CLASS(fields.String.clazz,
"java/lang/String");
"java/lang/String", true);
GET_CLASS(fields.LibVLC.clazz,
"org/videolan/libvlc/LibVLC");
"org/videolan/libvlc/LibVLC", true);
GET_CLASS(fields.VLCObject.clazz,
"org/videolan/libvlc/VLCObject");
"org/videolan/libvlc/VLCObject", true);
GET_CLASS(fields.Media.clazz,
"org/videolan/libvlc/Media");
"org/videolan/libvlc/Media", true);
GET_CLASS(fields.Media.Track.clazz,
"org/videolan/libvlc/Media$Track");
"org/videolan/libvlc/Media$Track", true);
GET_ID(GetStaticMethodID,
fields.LibVLC.onNativeCrashID,
......@@ -275,6 +285,23 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved)
fields.VLCObject.clazz,
"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,
fields.Media.createAudioTrackFromNativeID,
fields.Media.clazz,
......
......@@ -26,6 +26,7 @@
#include <vlc/libvlc_media_list.h>
struct fields {
jint SDK_INT;
struct {
jclass clazz;
} IllegalStateException;
......@@ -43,6 +44,8 @@ struct fields {
jclass clazz;
jfieldID mInstanceID;
jmethodID dispatchEventFromNativeID;
jmethodID getWeakReferenceID;
jmethodID dispatchEventFromWeakNativeID;
} VLCObject;
struct {
struct {
......
......@@ -23,6 +23,8 @@ package org.videolan.libvlc;
import android.os.Handler;
import android.os.Looper;
import java.lang.ref.WeakReference;
public abstract class VLCObject {
private final static String TAG = "LibVLC/VlcObject";
......@@ -215,4 +217,14 @@ public abstract class VLCObject {
mHandler.post(new EventRunnable(mEventListener, event));
}
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