diff --git a/src/frontends/android/app/src/main/jni/libandroidbridge/backend/android_scheduler.c b/src/frontends/android/app/src/main/jni/libandroidbridge/backend/android_scheduler.c index 5a901fe15..3252082bb 100644 --- a/src/frontends/android/app/src/main/jni/libandroidbridge/backend/android_scheduler.c +++ b/src/frontends/android/app/src/main/jni/libandroidbridge/backend/android_scheduler.c @@ -21,6 +21,12 @@ #include #include +/** + * Threshold in milliseconds up to which the default scheduler is used. + * This includes the roaming events (100 ms) and initial retransmits. + */ +#define DEFAULT_SCHEDULER_THRESHOLD 3000 + typedef struct private_scheduler_t private_scheduler_t; /** @@ -52,6 +58,11 @@ struct private_scheduler_t { * Mutex to safely access the scheduled jobs. */ mutex_t *mutex; + + /** + * Default scheduler used for short-term events. + */ + scheduler_t *default_scheduler; }; /** @@ -137,6 +148,14 @@ METHOD(scheduler_t, schedule_job_ms, void, entry_t *entry = NULL; jstring jid; + /* use the default scheduler for short-term events */ + if (ms <= DEFAULT_SCHEDULER_THRESHOLD) + { + this->default_scheduler->schedule_job_ms(this->default_scheduler, + job, ms); + return; + } + androidjni_attach_thread(&env); jid = allocate_id(this, env); if (!jid) @@ -213,6 +232,8 @@ METHOD(scheduler_t, flush, void, JNIEnv *env; jmethodID method_id; + this->default_scheduler->flush(this->default_scheduler); + this->mutex->lock(this->mutex); this->jobs->destroy_function(this->jobs, destroy_entry); this->jobs = hashtable_create(hashtable_hash_str, hashtable_equals_str, 16); @@ -247,6 +268,7 @@ METHOD(scheduler_t, destroy, void, (*env)->DeleteGlobalRef(env, this->cls); } androidjni_detach_thread(); + this->default_scheduler->destroy(this->default_scheduler); this->mutex->destroy(this->mutex); this->jobs->destroy(this->jobs); free(this); @@ -255,7 +277,7 @@ METHOD(scheduler_t, destroy, void, /* * Described in header */ -scheduler_t *android_scheduler_create(jobject context) +scheduler_t *android_scheduler_create(jobject context, scheduler_t *scheduler) { private_scheduler_t *this; JNIEnv *env; @@ -272,6 +294,7 @@ scheduler_t *android_scheduler_create(jobject context) .flush = _flush, .destroy = _destroy, }, + .default_scheduler = scheduler, .jobs = hashtable_create(hashtable_hash_str, hashtable_equals_str, 16), .mutex = mutex_create(MUTEX_TYPE_DEFAULT), ); diff --git a/src/frontends/android/app/src/main/jni/libandroidbridge/backend/android_scheduler.h b/src/frontends/android/app/src/main/jni/libandroidbridge/backend/android_scheduler.h index a27491084..eea011211 100644 --- a/src/frontends/android/app/src/main/jni/libandroidbridge/backend/android_scheduler.h +++ b/src/frontends/android/app/src/main/jni/libandroidbridge/backend/android_scheduler.h @@ -28,9 +28,14 @@ /** * Create an Android-specific scheduler_t implementation. * + * The given scheduler is used for short-term events. We can't destroy it anyway + * because of the scheduler job operating on it, and this way we can use it to + * avoid the overhead of broadcasts for some events. + * * @param context Context object + * @param scheduler the default scheduler used as fallback * @return scheduler_t instance */ -scheduler_t *android_scheduler_create(jobject context); +scheduler_t *android_scheduler_create(jobject context, scheduler_t *scheduler); #endif /** ANDROID_SCHEDULER_H_ @}*/ diff --git a/src/frontends/android/app/src/main/jni/libandroidbridge/charonservice.c b/src/frontends/android/app/src/main/jni/libandroidbridge/charonservice.c index a459f9f3a..bb8bdba82 100644 --- a/src/frontends/android/app/src/main/jni/libandroidbridge/charonservice.c +++ b/src/frontends/android/app/src/main/jni/libandroidbridge/charonservice.c @@ -94,11 +94,6 @@ struct private_charonservice_t { * Sockets that were bypassed and we keep track for */ linked_list_t *sockets; - - /** - * Default scheduler if we don't use it - */ - scheduler_t *default_scheduler; }; /** @@ -580,15 +575,6 @@ static void charonservice_init(JNIEnv *env, jobject service, jobject builder, ); charonservice = &this->public; - if (android_sdk_version >= ANDROID_MARSHMALLOW) - { - /* use a custom scheduler so the app is woken when jobs have to run. - * we can't destroy the default scheduler here due to the scheduler - * job that's operating on it, so we stash it away until later */ - this->default_scheduler = lib->scheduler; - lib->scheduler = android_scheduler_create(service); - } - lib->plugins->add_static_features(lib->plugins, "androidbridge", features, countof(features), TRUE, NULL, NULL); @@ -615,7 +601,6 @@ static void charonservice_deinit(JNIEnv *env) { private_charonservice_t *this = (private_charonservice_t*)charonservice; - DESTROY_IF(this->default_scheduler); this->network_manager->destroy(this->network_manager); this->sockets->destroy(this->sockets); this->builder->destroy(this->builder); @@ -661,6 +646,12 @@ JNI_METHOD(CharonVpnService, initializeCharon, jboolean, return FALSE; } + if (android_sdk_version >= ANDROID_MARSHMALLOW) + { + /* use a custom scheduler so the app is woken when jobs have to run */ + lib->scheduler = android_scheduler_create(this, lib->scheduler); + } + /* set options before initializing other libraries that might read them */ logfile = androidjni_convert_jstring(env, jlogfile);