From 59490310fd7a6d257b64cc228917f7108d88b4f0 Mon Sep 17 00:00:00 2001 From: "B. Petersen" Date: Sat, 18 Aug 2018 23:35:16 +0200 Subject: [PATCH] remove globals from DcContext (formerly MrMailbox) to allow multiple instances, add class derived from DcContext --- jni/dc_wrapper.c | 54 +++++++++---------- src/com/b44t/messenger/DcChatlist.java | 1 + src/com/b44t/messenger/DcContext.java | 7 ++- src/com/b44t/messenger/DcMsg.java | 3 +- .../securesms/ApplicationContext.java | 5 +- .../securesms/ApplicationDcContext.java | 31 +++++++++++ 6 files changed, 63 insertions(+), 38 deletions(-) create mode 100644 src/org/thoughtcrime/securesms/ApplicationDcContext.java diff --git a/jni/dc_wrapper.c b/jni/dc_wrapper.c index b72ff984c..9e9693461 100644 --- a/jni/dc_wrapper.c +++ b/jni/dc_wrapper.c @@ -64,29 +64,6 @@ static jstring jstring_new__(JNIEnv* env, const char* a) } -/* global stuff */ - -static JavaVM* s_jvm = NULL; -static jclass s_DcContext_class = NULL; -static jmethodID s_DcCallback_methodID = NULL; -static int s_global_init_done = 0; - - -static void s_init_globals(JNIEnv *env, jclass DcContext_class) -{ - /* make sure, the intialisation is done only once */ - if( s_global_init_done ) { return; } - s_global_init_done = 1; - - /* prepare calling back a Java function */ - (*env)->GetJavaVM(env, &s_jvm); /* JNIEnv cannot be shared between threads, so we share the JavaVM object */ - s_DcContext_class = (*env)->NewGlobalRef(env, DcContext_class); - s_DcCallback_methodID = (*env)->GetStaticMethodID(env, DcContext_class, "handleEvent","(IJJ)J" /*signature as "(param)ret" with I=int, J=long*/ ); -} - - -/* tools */ - static jintArray dc_array2jintArray_n_unref(JNIEnv *env, dc_array_t* ca) { /* takes a C-array of type dc_array_t and converts it it a Java-Array. @@ -152,6 +129,14 @@ static uint32_t* jintArray2uint32Pointer(JNIEnv* env, jintArray ja, int* ret_icn ******************************************************************************/ +typedef struct dc_jnicontext_t { + JavaVM* jvm; // JNIEnv cannot be shared between threads, so we share the JavaVM object + jclass cls; + jobject obj; + jmethodID methodId; +} dc_jnicontext_t; + + static dc_context_t* get_dc_context(JNIEnv *env, jobject obj) { static jfieldID fid = 0; @@ -166,23 +151,22 @@ static dc_context_t* get_dc_context(JNIEnv *env, jobject obj) } -/* DcContext - new/delete */ - static uintptr_t s_context_callback_(dc_context_t* context, int event, uintptr_t data1, uintptr_t data2) { jlong l; JNIEnv* env; + dc_jnicontext_t* jnicontext = dc_get_userdata(context); - if( s_jvm==NULL || s_DcContext_class==NULL || s_DcCallback_methodID==NULL ) { + if( jnicontext==NULL || jnicontext->jvm==NULL || jnicontext->cls==NULL || jnicontext->obj==NULL || jnicontext->methodId==NULL ) { return 0; /* may happen on startup */ } - (*s_jvm)->GetEnv(s_jvm, &env, JNI_VERSION_1_6); /* as this function may be called from _any_ thread, we cannot use a static pointer to JNIEnv */ + (*jnicontext->jvm)->GetEnv(jnicontext->jvm, &env, JNI_VERSION_1_6); // as this function may be called from _any_ thread, we cannot use a static pointer to JNIEnv if( env==NULL ) { return 0; /* may happen on startup */ } - l = (*env)->CallStaticLongMethod(env, s_DcContext_class, s_DcCallback_methodID, (jint)event, (jlong)data1, (jlong)data2); + l = (*env)->CallLongMethod(env, jnicontext->obj, jnicontext->methodId, (jint)event, (jlong)data1, (jlong)data2); return (uintptr_t)l; } @@ -190,9 +174,19 @@ static uintptr_t s_context_callback_(dc_context_t* context, int event, uintptr_t JNIEXPORT jlong Java_com_b44t_messenger_DcContext_DcContextNew(JNIEnv *env, jobject obj, jstring osname) { jclass cls = (*env)->GetObjectClass(env, obj); - s_init_globals(env, cls); + + dc_jnicontext_t* jnicontext = calloc(1, sizeof(dc_jnicontext_t)); + if (cls==NULL || jnicontext==NULL) { + return 0; + } + + (*env)->GetJavaVM(env, &jnicontext->jvm); + jnicontext->cls = (*env)->NewGlobalRef(env, cls); + jnicontext->obj = (*env)->NewGlobalRef(env, obj); + jnicontext->methodId = (*env)->GetMethodID(env, jnicontext->cls, "handleEvent","(IJJ)J" /*signature as "(param)ret" with I=int, J=long*/ ); + CHAR_REF(osname); - jlong hContext = (jlong)dc_context_new(s_context_callback_, NULL, osnamePtr); + jlong hContext = (jlong)dc_context_new(s_context_callback_, jnicontext, osnamePtr); CHAR_UNREF(osname); return hContext; } diff --git a/src/com/b44t/messenger/DcChatlist.java b/src/com/b44t/messenger/DcChatlist.java index 126d28831..a7a8c7a5e 100644 --- a/src/com/b44t/messenger/DcChatlist.java +++ b/src/com/b44t/messenger/DcChatlist.java @@ -24,6 +24,7 @@ package com.b44t.messenger; public class DcChatlist { + public DcChatlist(long hChatlist) { m_hChatlist = hChatlist; } diff --git a/src/com/b44t/messenger/DcContext.java b/src/com/b44t/messenger/DcContext.java index fc5551f0b..02a3557c5 100644 --- a/src/com/b44t/messenger/DcContext.java +++ b/src/com/b44t/messenger/DcContext.java @@ -68,7 +68,7 @@ public class DcContext { public final static int DC_QR_ERROR = 400; public DcContext(String osName) { - handleEvent(0,0,0); + handleEvent(0,0,0); // call handleEvent() to make sure it is not optimized away and JNI won't find it m_hContext = DcContextNew(osName); } @@ -141,9 +141,8 @@ public class DcContext { public native String getSecurejoinQr(int chat_id); public native int joinSecurejoin(String qr); - // event handling - public static long handleEvent(final int event, final long data1, final long data2) // this function is called from within the C-wrapper - { + // event handling - you should @Override this function in derived classes + public long handleEvent(final int event, final long data1, final long data2) { return 0; } diff --git a/src/com/b44t/messenger/DcMsg.java b/src/com/b44t/messenger/DcMsg.java index 42dc98485..e79161691 100644 --- a/src/com/b44t/messenger/DcMsg.java +++ b/src/com/b44t/messenger/DcMsg.java @@ -22,9 +22,8 @@ package com.b44t.messenger; -public class DcMsg { - private static final String TAG = "DcMsg"; +public class DcMsg { public final static int DC_MSG_UNDEFINED = 0; public final static int DC_MSG_TEXT = 10; diff --git a/src/org/thoughtcrime/securesms/ApplicationContext.java b/src/org/thoughtcrime/securesms/ApplicationContext.java index f2b1cf031..55720471d 100644 --- a/src/org/thoughtcrime/securesms/ApplicationContext.java +++ b/src/org/thoughtcrime/securesms/ApplicationContext.java @@ -82,7 +82,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc private volatile boolean isAppVisible; - public DcContext dcContext; + public ApplicationDcContext dcContext; public static ApplicationContext getInstance(Context context) { return (ApplicationContext)context.getApplicationContext(); @@ -93,7 +93,8 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc super.onCreate(); System.loadLibrary("native-utils"); - dcContext = new DcContext("Android"); + dcContext = new ApplicationDcContext(); + dcContext.open("foo"); initializeRandomNumberFix(); initializeLogging(); diff --git a/src/org/thoughtcrime/securesms/ApplicationDcContext.java b/src/org/thoughtcrime/securesms/ApplicationDcContext.java new file mode 100644 index 000000000..438bb9844 --- /dev/null +++ b/src/org/thoughtcrime/securesms/ApplicationDcContext.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2018 Delta Chat contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.thoughtcrime.securesms; + +import com.b44t.messenger.DcContext; + + +public class ApplicationDcContext extends DcContext { + + public ApplicationDcContext() { + super("Android"); + } + + @Override public long handleEvent(final int event, final long data1, final long data2) { + return 0; + } +}