From adf4836bec89de9e7a93a6988c7ae6ea7870936c Mon Sep 17 00:00:00 2001 From: =?utf8?q?Pawe=C5=82=20Stawicki?= Date: Mon, 5 Jun 2017 17:40:47 +0200 Subject: [PATCH] at-spi-bus-launcher: launch universal-switch Change-Id: I16bff1e30b2c72c812be767f1b21f88a65ee1787 --- bus/at-spi-bus-launcher.c | 197 +++++++++++++++++++++++++++++----------------- 1 file changed, 125 insertions(+), 72 deletions(-) diff --git a/bus/at-spi-bus-launcher.c b/bus/at-spi-bus-launcher.c index bb6f9f9..7948d1b 100644 --- a/bus/at-spi-bus-launcher.c +++ b/bus/at-spi-bus-launcher.c @@ -35,7 +35,11 @@ #include #endif +//TODO: move to vconf/vconf-internal-setting-keys.h? +#define VCONFKEY_SETAPPL_ACCESSIBILITY_UNIVERSAL_SWITCH "db/setting/accessibility/universal-switch" + #define APP_CONTROL_OPERATION_SCREEN_READ "http://tizen.org/appcontrol/operation/read_screen" +#define APP_CONTROL_OPERATION_UNIVERSAL_SWITCH "http://tizen.org/appcontrol/operation/universal_switch" #include #include @@ -64,7 +68,7 @@ FILE *log_file; #define LOGD(arg...) do {if (log_file) {fprintf(log_file, ##arg);fprintf(log_file, "\n"); fflush(log_file);}} while(0) #endif -static gboolean _launch_screen_reader_repeat_until_success(gpointer user_data); +static gboolean _launch_process_repeat_until_success(gpointer user_data); typedef enum { A11Y_BUS_STATE_IDLE = 0, @@ -74,6 +78,14 @@ typedef enum { } A11yBusState; typedef struct { + const char * name; + const char * app_control_operation; + const char * vconf_key; + int launch_repeats; + int pid; +} A11yBusClient; + +typedef struct { GMainLoop *loop; gboolean launch_immediately; gboolean a11y_enabled; @@ -83,9 +95,8 @@ typedef struct { GSettings *a11y_schema; GSettings *interface_schema; - int launch_screen_reader_repeats; - gboolean screen_reader_needed; - int pid; + A11yBusClient screen_reader; + A11yBusClient universal_switch; A11yBusState state; @@ -662,24 +673,43 @@ gsettings_key_changed (GSettings *gsettings, const gchar *key, void *user_data) } static int -_screen_reader_dead_tracker (int pid, void *data) +_process_dead_tracker (int pid, void *data) { A11yBusLauncher *app = data; - if (app->pid > 0 && pid == app->pid) + if (app->screen_reader.pid > 0 && pid == app->screen_reader.pid) { LOGE("screen reader is dead, pid: %d, restarting", pid); - app->pid = 0; - g_timeout_add_seconds (2, _launch_screen_reader_repeat_until_success, app); + app->screen_reader.pid = 0; + g_timeout_add_seconds (2, _launch_process_repeat_until_success, &app->screen_reader); + } + + if (app->universal_switch.pid > 0 && pid == app->universal_switch.pid) + { + LOGE("universal switch is dead, pid: %d, restarting", pid); + app->universal_switch.pid = 0; + g_timeout_add_seconds (2, _launch_process_repeat_until_success, &app->universal_switch); } return 0; } +static void +_register_process_dead_tracker () +{ + if(_global_app->screen_reader.pid > 0 || _global_app->universal_switch.pid > 0) { + LOGD("registering process dead tracker"); + aul_listen_app_dead_signal(_process_dead_tracker, _global_app); + } else { + LOGD("unregistering process dead tracker"); + aul_listen_app_dead_signal(NULL, NULL); + } +} + + static gboolean -_launch_screen_reader(gpointer user_data, gboolean by_vconf_change) +_launch_client(A11yBusClient *client, gboolean by_vconf_change) { - A11yBusLauncher *bl = user_data; - LOGD("Launching screen reader"); + LOGD("Launching %s", client->name); bundle *kb = NULL; gboolean ret = FALSE; @@ -700,120 +730,147 @@ _launch_screen_reader(gpointer user_data, gboolean by_vconf_change) } } - int operation_error = appsvc_set_operation(kb, APP_CONTROL_OPERATION_SCREEN_READ); + int operation_error = appsvc_set_operation(kb, client->app_control_operation); LOGD("appsvc_set_operation: %i", operation_error); - bl->pid = appsvc_run_service(kb, 0, NULL, NULL); + client->pid = appsvc_run_service(kb, 0, NULL, NULL); - if (bl->pid > 0) + if (client->pid > 0) { - LOGD("Screen reader launched with pid: %i", bl->pid); - LOGD("registering screen reader dead tracker"); - aul_listen_app_dead_signal(_screen_reader_dead_tracker, bl); + LOGD("Process launched with pid: %i", client->pid); + _register_process_dead_tracker(); ret = TRUE; } else { - LOGD("Can't start screen-reader - error code: %i", bl->pid); + LOGD("Can't start %s - error code: %i", client->name, client->pid); } - bundle_free(kb); return ret; } static gboolean -_launch_screen_reader_repeat_until_success(gpointer user_data) { - A11yBusLauncher *bl = user_data; +_launch_process_repeat_until_success(gpointer user_data) { + A11yBusClient *client = user_data; - if (bl->launch_screen_reader_repeats > 100 || bl->pid > 0) + if (client->launch_repeats > 100 || client->pid > 0) { //do not try anymore return FALSE; } - gboolean ret = _launch_screen_reader(user_data, FALSE); + gboolean ret = _launch_client(client, FALSE); if (ret) { //we managed to - bl->launch_screen_reader_repeats = 0; + client->launch_repeats = 0; return FALSE; } + client->launch_repeats++; //try again return TRUE; } static gboolean -_terminate_screen_reader(A11yBusLauncher *bl) +_terminate_process(int pid) { - LOGD("Terminating screen reader"); int ret; int ret_aul; - if (bl->pid <= 0) + if (pid <= 0) return FALSE; - - LOGD("unregistering screen reader dead tracker"); - aul_listen_app_dead_signal(NULL, NULL); - - int status = aul_app_get_status_bypid(bl->pid); + int status = aul_app_get_status_bypid(pid); if (status < 0) { - LOGD("App with pid %d already terminated", bl->pid); - bl->pid = 0; + LOGD("App with pid %d already terminated", pid); return TRUE; } - LOGD("terminate process with pid %d", bl->pid); - ret_aul = aul_terminate_pid(bl->pid); + LOGD("terminate process with pid %d", pid); + ret_aul = aul_terminate_pid(pid); if (ret_aul >= 0) { LOGD("Terminating with aul_terminate_pid: return is %d", ret_aul); - bl->pid = 0; return TRUE; } else LOGD("aul_terminate_pid failed: return is %d", ret_aul); LOGD("Unable to terminate process using aul api. Sending SIGTERM signal"); - ret = kill(bl->pid, SIGTERM); + ret = kill(pid, SIGTERM); if (!ret) { - bl->pid = 0; return TRUE; } - LOGD("Unable to terminate process: %d with api or signal.", bl->pid); + LOGD("Unable to terminate process: %d with api or signal.", pid); return FALSE; } -void screen_reader_cb(keynode_t *node, void *user_data) +static gboolean +_terminate_client(A11yBusClient *client) { - A11yBusLauncher *bl = user_data; - int ret; + LOGD("Terminating %s", client->name); + int pid = client->pid; + client->pid = 0; + _register_process_dead_tracker(); + gboolean ret = _terminate_process(pid); + return ret; +} - ret = vconf_keynode_get_bool(node); - LOGD("vconf_keynode_get_bool(node): %i", ret); - if (ret < 0) +void vconf_client_cb(keynode_t *node, void *user_data) +{ + A11yBusClient *client = user_data; + int client_needed = vconf_keynode_get_bool(node); + LOGD("vconf_keynode_get_bool(node): %i", client_needed); + if (client_needed < 0) return; //check if process really exists (e.g didn't crash) - if (bl->pid > 0) + if (client->pid > 0) { - int err = kill(bl->pid,0); + int err = kill(client->pid,0); //process doesn't exist if (err == ESRCH) - bl->pid = 0; + client->pid = 0; } - bl->screen_reader_needed = ret; - LOGD("bl->screen_reader_needed: %i, bl->pid: %i", ret, bl->pid); - if (!bl->screen_reader_needed && (bl->pid > 0)) - _terminate_screen_reader(bl); - else if (bl->screen_reader_needed && (bl->pid <= 0)) - _launch_screen_reader(bl, TRUE); + LOGD("client_needed: %i, client->pid: %i", client_needed, client->pid); + if (!client_needed && (client->pid > 0)) + _terminate_client(client); + else if (client_needed && (client->pid <= 0)) + _launch_client(client, TRUE); +} + + +static gboolean register_client(A11yBusClient *client) +{ + gboolean client_needed = FALSE; + + if(!client->vconf_key) { + LOGE("Vconf_key missing for client: %s \n", client->vconf_key); + return FALSE; + } + + int ret = vconf_get_bool(client->vconf_key, &client_needed); + if (ret != 0) + { + LOGD("Could not read %s key value.\n", client->vconf_key); + return FALSE; + } + ret = vconf_notify_key_changed(client->vconf_key, vconf_client_cb, client); + if(ret != 0) + { + LOGD("Could not add information level callback\n"); + return FALSE; + } + + if (client_needed) + g_timeout_add_seconds(2,_launch_process_repeat_until_success, client); + return TRUE; } int @@ -825,7 +882,6 @@ main (int argc, #endif LOGD("Starting atspi bus launcher"); - int name_owner_id; gboolean a11y_set = FALSE; gboolean screen_reader_set = FALSE; gint i; @@ -838,9 +894,16 @@ main (int argc, _global_app = g_slice_new0 (A11yBusLauncher); _global_app->loop = g_main_loop_new (NULL, FALSE); - _global_app->launch_screen_reader_repeats = 0; _global_app->client_watcher_id = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); + _global_app->screen_reader.name = "screen-reader"; + _global_app->screen_reader.app_control_operation = APP_CONTROL_OPERATION_SCREEN_READ; + _global_app->screen_reader.vconf_key = VCONFKEY_SETAPPL_ACCESSIBILITY_TTS; + + _global_app->universal_switch.name = "universal-switch"; + _global_app->universal_switch.app_control_operation = APP_CONTROL_OPERATION_UNIVERSAL_SWITCH; + _global_app->universal_switch.vconf_key = VCONFKEY_SETAPPL_ACCESSIBILITY_UNIVERSAL_SWITCH; + for (i = 1; i < argc; i++) { if (!strcmp (argv[i], "--launch-immediately")) @@ -886,7 +949,7 @@ main (int argc, introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL); g_assert (introspection_data != NULL); - name_owner_id = g_bus_own_name (G_BUS_TYPE_SESSION, + g_bus_own_name (G_BUS_TYPE_SESSION, "org.a11y.Bus", G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT, on_bus_acquired, @@ -895,20 +958,10 @@ main (int argc, _global_app, NULL); - int ret = vconf_get_bool(VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, &_global_app->screen_reader_needed); - if (ret != 0) - { - LOGD("Could not read VCONFKEY_SETAPPL_ACCESSIBILITY_TTS key value.\n"); - return FALSE; - } - ret = vconf_notify_key_changed(VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, screen_reader_cb, _global_app); - if(ret != 0) - { - LOGD("Could not add information level callback\n"); - return FALSE; - } - if (_global_app->screen_reader_needed) - g_timeout_add_seconds(2,_launch_screen_reader_repeat_until_success, _global_app); + if(!register_client(&_global_app->screen_reader)) + return FALSE; + if(!register_client(&_global_app->universal_switch)) + return FALSE; g_main_loop_run (_global_app->loop); -- 2.7.4