78static void application_free_cb (gpointer self);
79static gint application_compare_cb(gconstpointer a, gconstpointer b);
85static void applist_free(GList *list);
86static GList *applist_load(
const char *conf_dir);
97static int appsync_mark_active_locked (
const char *name,
int post);
100static gboolean appsync_enumerate_usb_cb (gpointer data);
101static void appsync_start_enumerate_usb_timer (
void);
102static void appsync_cancel_enumerate_usb_timer(
void);
103static void appsync_enumerate_usb (
void);
105static void appsync_stop_apps (
int post);
116static pthread_mutex_t appsync_mutex = PTHREAD_MUTEX_INITIALIZER;
118#define APPSYNC_LOCKED_ENTER do {\
119 if( pthread_mutex_lock(&appsync_mutex) != 0 ) { \
120 log_crit("APPSYNC LOCK FAILED");\
121 _exit(EXIT_FAILURE);\
125#define APPSYNC_LOCKED_LEAVE do {\
126 if( pthread_mutex_unlock(&appsync_mutex) != 0 ) { \
127 log_crit("APPSYNC UNLOCK FAILED");\
128 _exit(EXIT_FAILURE);\
133static GList *appsync_apps_curr = NULL;
136static GList *appsync_apps_next = NULL;
137static bool appsync_apps_updated =
false;
140static guint appsync_enumerate_usb_id = 0;
141static struct timeval appsync_sync_tv = {0, 0};
142static int appsync_no_dbus = 0;
144static int appsync_no_dbus = 1;
173 LOG_REGISTER_CONTEXT;
176 GKeyFile *keyfile = NULL;
178 log_debug(
"loading appsync file: %s", filename);
180 if( !(keyfile = g_key_file_new()) )
183 if( !g_key_file_load_from_file(keyfile, filename, G_KEY_FILE_NONE, NULL) ) {
184 log_warning(
"failed to load appsync file: %s", filename);
188 if( !(self = calloc(1,
sizeof *self)) )
191 self->
name = g_key_file_get_string(keyfile, APP_INFO_ENTRY, APP_INFO_NAME_KEY, NULL);
192 log_debug(
"Appname = %s\n", self->
name ?:
"<unset>");
194 self->
launch = g_key_file_get_string(keyfile, APP_INFO_ENTRY, APP_INFO_LAUNCH_KEY, NULL);
195 log_debug(
"Launch = %s\n", self->
launch ?:
"<unset>");
197 self->
mode = g_key_file_get_string(keyfile, APP_INFO_ENTRY, APP_INFO_MODE_KEY, NULL);
198 log_debug(
"Launch mode = %s\n", self->
mode ?:
"<unset>");
200 self->
systemd = g_key_file_get_integer(keyfile, APP_INFO_ENTRY, APP_INFO_SYSTEMD_KEY, NULL);
201 log_debug(
"Systemd control = %d\n", self->
systemd);
203 self->
post = g_key_file_get_integer(keyfile, APP_INFO_ENTRY, APP_INFO_POST, NULL);
204 log_debug(
"post = %d\n", self->
post);
211 g_key_file_free(keyfile);
214 if( self && !application_is_valid(self) ) {
215 log_warning(
"discarding invalid appsync file: %s", filename);
216 application_free(self),
229 LOG_REGISTER_CONTEXT;
243static void application_free_cb(gpointer self)
245 LOG_REGISTER_CONTEXT;
247 application_free(self);
257static gint application_compare_cb(gconstpointer a, gconstpointer b)
259 LOG_REGISTER_CONTEXT;
263 return strcasecmp(application_a->
name, application_b->
name);
274static void applist_free(GList *list)
276 g_list_free_full(list, application_free_cb);
286static GList *applist_load(
const char *conf_dir)
288 LOG_REGISTER_CONTEXT;
294 if( !(pat = g_strdup_printf(
"%s/*.ini", conf_dir)) )
297 if( glob(pat, 0, 0, &gb) != 0 ) {
298 log_debug(
"no appsync ini-files found");
302 for(
size_t i = 0; i < gb.gl_pathc; ++i ) {
303 application_t *application = application_load(gb.gl_pathv[i]);
305 list = g_list_append(list, application);
311 list = g_list_sort(list, application_compare_cb);
330 LOG_REGISTER_CONTEXT;
332 APPSYNC_LOCKED_ENTER;
334 if( appsync_apps_updated ) {
335 appsync_apps_updated =
false;
336 log_debug(
"Switch appsync config");
337 applist_free(appsync_apps_curr),
338 appsync_apps_curr = appsync_apps_next,
339 appsync_apps_next = 0;
342 APPSYNC_LOCKED_LEAVE;
349 LOG_REGISTER_CONTEXT;
351 APPSYNC_LOCKED_ENTER;
353 if( appsync_apps_curr ) {
354 log_debug(
"Release current appsync config");
355 applist_free(appsync_apps_curr),
356 appsync_apps_curr = 0;
359 if( appsync_apps_next ) {
360 log_debug(
"Release future appsync config");
361 applist_free(appsync_apps_next),
362 appsync_apps_next = 0;
365 APPSYNC_LOCKED_LEAVE;
382 LOG_REGISTER_CONTEXT;
384 GList *applist = applist_load(usbmoded_get_diag_mode() ?
385 CONF_DIR_DIAG_PATH : CONF_DIR_PATH);
387 APPSYNC_LOCKED_ENTER;
389 if( !appsync_apps_curr ) {
390 log_debug(
"Update current appsync config");
391 appsync_apps_curr = applist;
393 applist_free(appsync_apps_next),
394 appsync_apps_next = 0;
395 appsync_apps_updated =
false;
398 log_debug(
"Update future appsync config");
399 applist_free(appsync_apps_next),
400 appsync_apps_next = applist;
401 appsync_apps_updated =
true;
404 if( appsync_apps_curr ) {
405 log_debug(
"Sync list available");
414 APPSYNC_LOCKED_LEAVE;
428 LOG_REGISTER_CONTEXT;
432 log_debug(
"activate-pre mode=%s", mode);
434 APPSYNC_LOCKED_ENTER;
438 gettimeofday(&appsync_sync_tv, 0);
441 if( appsync_apps_curr == 0 )
443 log_debug(
"No sync list!");
445 appsync_enumerate_usb();
452 for( GList *iter = appsync_apps_curr; iter; iter = g_list_next(iter) )
456 if(!strcmp(application->
mode, mode))
470 log_debug(
"Nothing to launch\n");
472 appsync_enumerate_usb();
481 log_debug(
"dbus setup failed => skipping dbus launched apps");
486 appsync_start_enumerate_usb_timer();
490 for( GList *iter = appsync_apps_curr; iter; iter = g_list_next(iter) )
493 if(!strcmp(mode, application->
mode))
496 if(application->
post)
500 log_debug(
"launching pre-enum-app %s", application->
name);
503 if(!systemd_control_service(application->
name, SYSTEMD_START)) {
504 log_debug(
"systemd pre-enum-app %s failed", application->
name);
508 appsync_mark_active_locked(application->
name, 0);
510 else if(application->
launch)
514 if( appsync_no_dbus ) {
515 log_debug(
"dbus pre-enum-app %s ignored", application->
name);
521 appsync_mark_active_locked(application->
name, 0);
526 log_debug(
"dbus pre-enum-app %s failed", application->
name);
530 appsync_mark_active_locked(application->
name, 0);
537 APPSYNC_LOCKED_LEAVE;
553 LOG_REGISTER_CONTEXT;
557 log_debug(
"activate-post mode=%s", mode);
559 APPSYNC_LOCKED_ENTER;
561 if( !appsync_apps_curr ) {
562 log_debug(
"No sync list! skipping post sync");
570 log_debug(
"dbus setup failed => skipping dbus launched apps");
576 for( GList *iter = appsync_apps_curr; iter; iter = g_list_next(iter) )
580 if( !strcmp(application->
mode, mode) ) {
582 if(!application->
post)
585 log_debug(
"launching post-enum-app %s\n", application->
name);
587 if(!systemd_control_service(application->
name, SYSTEMD_START)) {
588 log_err(
"systemd post-enum-app %s failed", application->
name);
592 appsync_mark_active_locked(application->
name, 1);
594 else if( application->
launch ) {
597 if( appsync_no_dbus ) {
598 log_debug(
"dbus pre-enum-app %s ignored", application->
name);
603 log_err(
"dbus post-enum-app %s failed", application->
name);
607 appsync_mark_active_locked(application->
name, 1);
614 APPSYNC_LOCKED_LEAVE;
630static int appsync_mark_active_locked(
const char *name,
int post)
632 LOG_REGISTER_CONTEXT;
637 log_debug(
"%s-enum-app %s is started\n", post ?
"post" :
"pre", name);
639 for( GList *iter = appsync_apps_curr; iter; iter = g_list_next(iter) )
643 if(!strcmp(application->
name, name))
657 if( ret != -1 )
break;
660 if( !post && !missing )
662 log_debug(
"All pre-enum-apps active");
664 appsync_enumerate_usb();
692 LOG_REGISTER_CONTEXT;
694 APPSYNC_LOCKED_ENTER;
695 int ret = appsync_mark_active_locked(name, post);
696 APPSYNC_LOCKED_LEAVE;
702static gboolean appsync_enumerate_usb_cb(gpointer data)
704 LOG_REGISTER_CONTEXT;
707 appsync_enumerate_usb_id = 0;
708 log_debug(
"handling enumeration timeout");
709 appsync_enumerate_usb();
714static void appsync_start_enumerate_usb_timer(
void)
716 LOG_REGISTER_CONTEXT;
718 log_debug(
"scheduling enumeration timeout");
719 if( appsync_enumerate_usb_id )
720 g_source_remove(appsync_enumerate_usb_id), appsync_enumerate_usb_id = 0;
727 appsync_enumerate_usb_id = g_timeout_add_seconds(2, appsync_enumerate_usb_cb, NULL);
730static void appsync_cancel_enumerate_usb_timer(
void)
732 LOG_REGISTER_CONTEXT;
734 if( appsync_enumerate_usb_id )
736 log_debug(
"canceling enumeration timeout");
737 g_source_remove(appsync_enumerate_usb_id), appsync_enumerate_usb_id = 0;
741static void appsync_enumerate_usb(
void)
743 LOG_REGISTER_CONTEXT;
747 log_debug(
"Enumerating");
750 appsync_cancel_enumerate_usb_timer();
753 gettimeofday(&tv, 0);
754 timersub(&tv, &appsync_sync_tv, &tv);
755 log_debug(
"sync to enum: %.3f seconds", tv.tv_sec + tv.tv_usec * 1e-6);
768static void appsync_stop_apps(
int post)
770 LOG_REGISTER_CONTEXT;
772 for( GList *iter = appsync_apps_curr; iter; iter = g_list_next(iter) )
776 if( application->
post == post &&
779 log_debug(
"stopping %s-enum-app %s", post ?
"post" :
"pre",
783 if( !systemd_control_service(application->
name, SYSTEMD_STOP) )
784 log_debug(
"Failed to stop %s\n", application->
name);
786 else if( application->
launch ) {
799 APPSYNC_LOCKED_ENTER;
800 appsync_stop_apps(0);
801 APPSYNC_LOCKED_LEAVE;
808 APPSYNC_LOCKED_ENTER;
809 appsync_stop_apps(1);
810 APPSYNC_LOCKED_LEAVE;
826 LOG_REGISTER_CONTEXT;
828 APPSYNC_LOCKED_ENTER;
834 log_debug(
"assuming all applications are active");
836 for( GList *iter = appsync_apps_curr; iter; iter = g_list_next(iter) )
844 appsync_stop_apps(1);
847 appsync_stop_apps(0);
851 appsync_cancel_enumerate_usb_timer();
854 APPSYNC_LOCKED_LEAVE;
gboolean dbusappsync_init_connection(void)
void dbusappsync_cleanup(void)
gboolean dbusappsync_init(void)
int dbusappsync_launch_app(char *launch)
int appsync_mark_active(const char *name, int post)
void appsync_deactivate_pre(void)
void appsync_switch_configuration(void)
void appsync_free_configuration(void)
void appsync_deactivate_all(bool force)
int appsync_activate_post(const char *mode)
void appsync_deactivate_post(void)
void appsync_load_configuration(void)
int appsync_activate_pre(const char *mode)