android: Use the default scheduler for short-term events

Using AlarmManager has quite some overhead, so we use our regular
scheduler for events that are to be executed in the near future.
This commit is contained in:
Tobias Brunner 2020-05-02 09:20:59 +02:00
parent 1b4c4123c2
commit d67a5b0c4d
3 changed files with 36 additions and 17 deletions

View File

@ -21,6 +21,12 @@
#include <processing/jobs/callback_job.h>
#include <threading/mutex.h>
/**
* 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),
);

View File

@ -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_ @}*/

View File

@ -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);