From d42eb1d920ba74b77e7e41f0e7eb6d2488e0d34b Mon Sep 17 00:00:00 2001 From: "B. Petersen" Date: Mon, 25 May 2020 16:59:13 +0200 Subject: [PATCH] get rid of open/close context --- jni/dc_wrapper.c | 77 ++----------------- src/com/b44t/messenger/DcContext.java | 28 +++---- .../securesms/connect/AccountManager.java | 12 +-- .../connect/ApplicationDcContext.java | 22 ++++-- 4 files changed, 43 insertions(+), 96 deletions(-) diff --git a/jni/dc_wrapper.c b/jni/dc_wrapper.c index 3afac1711..4afdf40df 100644 --- a/jni/dc_wrapper.c +++ b/jni/dc_wrapper.c @@ -173,14 +173,6 @@ 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; @@ -195,42 +187,12 @@ static dc_context_t* get_dc_context(JNIEnv *env, jobject obj) } -static uintptr_t s_context_callback_(dc_context_t* context, int event, uintptr_t data1, uintptr_t data2) +JNIEXPORT jlong Java_com_b44t_messenger_DcContext_createContextCPtr(JNIEnv *env, jobject obj, jstring osname, jstring dbfile) { - jlong l; - JNIEnv* env; - dc_jnicontext_t* jnicontext = dc_get_userdata(context); - - if (jnicontext==NULL || jnicontext->jvm==NULL || jnicontext->cls==NULL || jnicontext->obj==NULL || jnicontext->methodId==NULL) { - return 0; /* may happen on startup */ - } - - (*jnicontext->jvm)->GetEnv(jnicontext->jvm, (void**)&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)->CallLongMethod(env, jnicontext->obj, jnicontext->methodId, (jint)event, (jlong)data1, (jlong)data2); - return (uintptr_t)l; -} - - -JNIEXPORT jlong Java_com_b44t_messenger_DcContext_createContextCPtr(JNIEnv *env, jobject obj, jstring osname) -{ - jclass cls = (*env)->GetObjectClass(env, obj); - - 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 contextCPtr = (jlong)dc_context_new(s_context_callback_, jnicontext, osnamePtr); + CHAR_REF(dbfile) + jlong contextCPtr = (jlong)dc_context_new(osnamePtr, dbfilePtr, NULL); + CHAR_UNREF(dbfile) CHAR_UNREF(osname); return contextCPtr; } @@ -244,21 +206,6 @@ JNIEXPORT void Java_com_b44t_messenger_DcContact_unrefContextCPtr(JNIEnv *env, j /* DcContext - open/configure/connect/fetch */ -JNIEXPORT jint Java_com_b44t_messenger_DcContext_open(JNIEnv *env, jobject obj, jstring dbfile) -{ - CHAR_REF(dbfile); - jint ret = dc_open(get_dc_context(env, obj), dbfilePtr, NULL); - CHAR_UNREF(dbfile) - return ret; -} - - -JNIEXPORT void Java_com_b44t_messenger_DcContext_close(JNIEnv *env, jobject obj) -{ - dc_close(get_dc_context(env, obj)); -} - - JNIEXPORT void Java_com_b44t_messenger_DcContext_setStockTranslation(JNIEnv *env, jobject obj, jint stock_id, jstring translation) { CHAR_REF(translation); @@ -303,93 +250,79 @@ JNIEXPORT jint Java_com_b44t_messenger_DcContext_isConfigured(JNIEnv *env, jobje } +// TODO-ASYNC: delete these functions, also in the java-part JNIEXPORT void Java_com_b44t_messenger_DcContext_performImapJobs(JNIEnv *env, jobject obj) { - dc_perform_imap_jobs(get_dc_context(env, obj)); } JNIEXPORT void Java_com_b44t_messenger_DcContext_performImapIdle(JNIEnv *env, jobject obj) { - dc_perform_imap_idle(get_dc_context(env, obj)); } JNIEXPORT void Java_com_b44t_messenger_DcContext_performImapFetch(JNIEnv *env, jobject obj) { - dc_perform_imap_fetch(get_dc_context(env, obj)); } JNIEXPORT void Java_com_b44t_messenger_DcContext_interruptImapIdle(JNIEnv *env, jobject obj) { - dc_interrupt_imap_idle(get_dc_context(env, obj)); } JNIEXPORT void Java_com_b44t_messenger_DcContext_performSentboxJobs(JNIEnv *env, jobject obj) { - dc_perform_sentbox_jobs(get_dc_context(env, obj)); } JNIEXPORT void Java_com_b44t_messenger_DcContext_performSentboxFetch(JNIEnv *env, jobject obj) { - dc_perform_sentbox_fetch(get_dc_context(env, obj)); } JNIEXPORT void Java_com_b44t_messenger_DcContext_performSentboxIdle(JNIEnv *env, jobject obj) { - dc_perform_sentbox_idle(get_dc_context(env, obj)); } JNIEXPORT void Java_com_b44t_messenger_DcContext_interruptSentboxIdle(JNIEnv *env, jobject obj) { - dc_interrupt_sentbox_idle(get_dc_context(env, obj)); } JNIEXPORT void Java_com_b44t_messenger_DcContext_performMvboxJobs(JNIEnv *env, jobject obj) { - dc_perform_mvbox_jobs(get_dc_context(env, obj)); } JNIEXPORT void Java_com_b44t_messenger_DcContext_performMvboxFetch(JNIEnv *env, jobject obj) { - dc_perform_mvbox_fetch(get_dc_context(env, obj)); } JNIEXPORT void Java_com_b44t_messenger_DcContext_performMvboxIdle(JNIEnv *env, jobject obj) { - dc_perform_mvbox_idle(get_dc_context(env, obj)); } JNIEXPORT void Java_com_b44t_messenger_DcContext_interruptMvboxIdle(JNIEnv *env, jobject obj) { - dc_interrupt_mvbox_idle(get_dc_context(env, obj)); } JNIEXPORT void Java_com_b44t_messenger_DcContext_performSmtpJobs(JNIEnv *env, jobject obj) { - dc_perform_smtp_jobs(get_dc_context(env, obj)); } JNIEXPORT void Java_com_b44t_messenger_DcContext_performSmtpIdle(JNIEnv *env, jobject obj) { - dc_perform_smtp_idle(get_dc_context(env, obj)); } JNIEXPORT void Java_com_b44t_messenger_DcContext_interruptSmtpIdle(JNIEnv *env, jobject obj) { - dc_interrupt_smtp_idle(get_dc_context(env, obj)); } diff --git a/src/com/b44t/messenger/DcContext.java b/src/com/b44t/messenger/DcContext.java index 38a4f8fca..fecb50c38 100644 --- a/src/com/b44t/messenger/DcContext.java +++ b/src/com/b44t/messenger/DcContext.java @@ -72,20 +72,27 @@ public class DcContext { public final static int DC_EMPTY_MVBOX = 0x01; public final static int DC_EMPTY_INBOX = 0x02; - public DcContext(String osName) { - handleEvent(0,0,0); // call handleEvent() to make sure it is not optimized away and JNI won't find it - contextCPtr = createContextCPtr(osName); + public DcContext(String osName, String dbfile) { + contextCPtr = createContextCPtr(osName, dbfile); + } + + public boolean isOk() { + return contextCPtr != 0; } @Override protected void finalize() throws Throwable { super.finalize(); - unrefContextCPtr(); - contextCPtr = 0; + unref(); + } + + public void unref() { + if (contextCPtr != 0) { + unrefContextCPtr(); + contextCPtr = 0; + } } - public native int open (String dbfile); - public native void close (); public native void setStockTranslation (int stockId, String translation); public native String getBlobdir (); public native void configure (); @@ -189,11 +196,6 @@ public class DcContext { */ public native boolean setLocation (float latitude, float longitude, float accuracy); - // event handling - you should @Override this function in derived classes - public long handleEvent(int event, long data1, long data2) { - return 0; - } - // helper to get/return strings from/to handleEvent() public native static boolean data1IsString(int event); public native static boolean data2IsString(int event); @@ -201,7 +203,7 @@ public class DcContext { // working with raw c-data private long contextCPtr; // CAVE: the name is referenced in the JNI - private native long createContextCPtr(String osName); + private native long createContextCPtr(String osName, String dbfile); private native void unrefContextCPtr (); public native long createMsgCPtr (int viewtype); private native long getChatlistCPtr (int listflags, String query, int queryId); diff --git a/src/org/thoughtcrime/securesms/connect/AccountManager.java b/src/org/thoughtcrime/securesms/connect/AccountManager.java index bbabb281a..aa8e6ef09 100644 --- a/src/org/thoughtcrime/securesms/connect/AccountManager.java +++ b/src/org/thoughtcrime/securesms/connect/AccountManager.java @@ -65,8 +65,8 @@ public class AccountManager { private @Nullable Account maybeGetAccount(File file) { try { if (!file.isDirectory() && file.getName().endsWith(".db")) { - DcContext testContext = new DcContext(null); - if (testContext.open(file.getAbsolutePath()) != 0) { + DcContext testContext = new DcContext(null, file.getAbsolutePath()); + if (testContext.isOk()) { Account ret = new Account(); ret.dbName = file.getName(); ret.displayname = testContext.getConfig("displayname"); @@ -99,7 +99,7 @@ public class AccountManager { // getSelectedAccount() ApplicationContext appContext = (ApplicationContext)context.getApplicationContext(); appContext.dcContext.stopThreads(); - appContext.dcContext.close(); + appContext.dcContext.unref(); appContext.dcContext = new ApplicationDcContext(context); } @@ -243,10 +243,10 @@ public class AccountManager { if (deleteDbName!=null) { // used to delete the previous account, however, as a resilience check, make sure, // we do not delete already configured accounts (just in case sth. changes the flow of activities) - DcContext testContext = new DcContext(null); - if (testContext.open(new File(activity.getFilesDir(), deleteDbName).getAbsolutePath()) != 0) { + DcContext testContext = new DcContext(null, new File(activity.getFilesDir(), deleteDbName).getAbsolutePath()); + if (testContext.isOk()) { if (testContext.isConfigured() == 0) { - testContext.close(); + testContext.unref(); AccountManager.getInstance().deleteAccount(activity, deleteDbName); PreferenceManager.getDefaultSharedPreferences(activity) .edit().putString("prev_account_db_name", "").apply(); diff --git a/src/org/thoughtcrime/securesms/connect/ApplicationDcContext.java b/src/org/thoughtcrime/securesms/connect/ApplicationDcContext.java index e52af1e4a..a410f732a 100644 --- a/src/org/thoughtcrime/securesms/connect/ApplicationDcContext.java +++ b/src/org/thoughtcrime/securesms/connect/ApplicationDcContext.java @@ -56,12 +56,9 @@ public class ApplicationDcContext extends DcContext { public NotificationCenter notificationCenter; public ApplicationDcContext(Context context) { - super("Android "+BuildConfig.VERSION_NAME); + super("Android "+BuildConfig.VERSION_NAME, AccountManager.getInstance().getSelectedAccount(context).getAbsolutePath()); this.context = context; - File dbfile = AccountManager.getInstance().getSelectedAccount(context); - open(dbfile.getAbsolutePath()); - // migration, can be removed after some versions (added 5/2020) // (this will convert only for one account, but that is fine, multi-account is experimental anyway) try { @@ -341,6 +338,10 @@ public class ApplicationDcContext extends DcContext { public boolean run = true; public void startThreads(int flags) { + + // TODO-ASYNC: remove this function, handle the flags differently + + /* synchronized (threadsCritical) { if (imapThread == null || !imapThread.isAlive()) { @@ -432,9 +433,14 @@ public class ApplicationDcContext extends DcContext { smtpThread.start(); } } + */ } public void waitForThreadsExecutedOnce() { + + // TODO-ASYNC + + /* while(true) { synchronized (incLoopsCritical) { if(inboxLoops>0 && mvboxLoops>0 && smtpLoops>0) { @@ -443,10 +449,15 @@ public class ApplicationDcContext extends DcContext { } Util.sleep(500); } + */ } public void stopThreads() { notificationCenter.removeAllNotifiations(); + + // TODO-ASYNC + + /* run = false; synchronized (threadsCritical) { while (true) { @@ -470,6 +481,7 @@ public class ApplicationDcContext extends DcContext { } } Log.i(TAG, "!!!!!!!!!!!! threads stopped"); + */ } @@ -557,7 +569,7 @@ public class ApplicationDcContext extends DcContext { }); } - @Override + // TODO-ASYNC: make this work again public long handleEvent(final int event, long data1, long data2) { switch (event) { case DC_EVENT_INFO: