From 21b6f0d2bf1974d7eb587415189918aa18cbb915 Mon Sep 17 00:00:00 2001 From: Unsung Lee Date: Mon, 31 Jul 2023 20:17:47 +0900 Subject: [PATCH] proc: Reset the window stack information from proc_app_info Reset window stack information before updating it to remove invalid window information. Currently, window information of window stack is saved in proc_app_info, so resourced needs to know each window owner after the latest window stack update. Change-Id: If2ef136577c329e63cf48673254b9e04642b283c Signed-off-by: Unsung Lee --- src/process/proc-main.c | 142 +++++++++++++++++++++++++++++++++++++++++++++ src/process/proc-main.h | 5 ++ src/process/proc-monitor.c | 24 ++++++-- 3 files changed, 165 insertions(+), 6 deletions(-) diff --git a/src/process/proc-main.c b/src/process/proc-main.c index b09f2dd..7eb1f2c 100644 --- a/src/process/proc-main.c +++ b/src/process/proc-main.c @@ -437,6 +437,136 @@ struct proc_app_info *find_app_info(const pid_t pid) return NULL; } +/** + * Register a window in an app and update window owner list in proc_app_list. + * This function must be called after calling proc_unregister_windows() + */ +int proc_register_window_in_app_info(struct proc_app_info *pai, + struct proc_app_window_info *new_window) +{ + _cleanup_app_list_close_ GSList *proc_app_list = PAL_INIT_VALUE; + GHashTable *owner_table = app_list.window_owner_table; + bool has_window; + + if (!pai) + return RESOURCED_ERROR_INVALID_PARAMETER; + + proc_app_list = proc_app_list_open(); + if (!proc_app_list) + return RESOURCED_ERROR_FAIL; + + /** + * An app can have more than 1 window. + * In this case, resourced stores the most important window information + * into proc_app_info structure. + * + * Criterion for judging which window is the most important: + * + * If one of window has is_focused = 1, then it is the most important. + * Otherwise, the higher in the window stack, the more important window. + */ + has_window = (pai->window.pid != 0); + if (has_window && !new_window->is_focused) { + if (pai->window.is_focused) + return RESOURCED_ERROR_NONE; + + if (pai->window.z < new_window->z) + return RESOURCED_ERROR_NONE; + } + + if (has_window) + g_hash_table_remove(owner_table, &(pai->window.pid)); + + memcpy(&pai->window, new_window, sizeof(struct proc_app_window_info)); + g_hash_table_insert(owner_table, &(pai->window.pid), pai); + + return RESOURCED_ERROR_NONE; +} + +/** + * Unregister all of windows of all apps from window owner list + * in proc_app_list. + * This function must be called before calling proc_register_window_in_app_info() + * to remove all old windows in proc_app_info. + */ +int proc_unregister_windows(void) +{ + _cleanup_app_list_close_ GSList *proc_app_list = PAL_INIT_VALUE; + GHashTable *owner_table = app_list.window_owner_table; + GHashTableIter window_table_iter; + gpointer pid; + gpointer value; + + proc_app_list = proc_app_list_open(); + if (!proc_app_list) + return RESOURCED_ERROR_FAIL; + + g_hash_table_iter_init(&window_table_iter, owner_table); + while (g_hash_table_iter_next(&window_table_iter, &pid, &value)) { + struct proc_app_info *pai = (struct proc_app_info *)value; + if (!pai) { + _E("Process app info strucutre can not be null (SIGABRT)"); + assert(0); + } + + memset(&(pai->window), 0, sizeof(struct proc_app_window_info)); + } + g_hash_table_remove_all(owner_table); + + return RESOURCED_ERROR_NONE; +} + +/** + * Unregister this process from window owner list in proc_app_list. + * This function must be called before removing a child process in app. + */ +static int proc_unregister_window_of_process(struct proc_app_info *pai, + pid_t pid) +{ + _cleanup_app_list_close_ GSList *proc_app_list = PAL_INIT_VALUE; + GHashTable *owner_table = app_list.window_owner_table; + + if (!pai) + return RESOURCED_ERROR_INVALID_PARAMETER; + + proc_app_list = proc_app_list_open(); + if (!proc_app_list) + return RESOURCED_ERROR_FAIL; + + if (pai->window.pid != pid) + return RESOURCED_ERROR_NONE; + + g_hash_table_remove(owner_table, &(pai->window.pid)); + memset(&(pai->window), 0, sizeof(struct proc_app_window_info)); + + return RESOURCED_ERROR_NONE; +} + +/** + * Unregister this app from window owner list in proc_app_list. + * This function must be called before removing proc_app_info. + */ +static int proc_unregister_window_of_app(struct proc_app_info *pai) +{ + _cleanup_app_list_close_ GSList *proc_app_list = PAL_INIT_VALUE; + GHashTable *owner_table = app_list.window_owner_table; + + if (!pai) + return RESOURCED_ERROR_INVALID_PARAMETER; + + proc_app_list = proc_app_list_open(); + if (!proc_app_list) + return RESOURCED_ERROR_FAIL; + + if (pai->window.pid == 0) + return RESOURCED_ERROR_NONE; + + g_hash_table_remove(owner_table, &(pai->window.pid)); + memset(&(pai->window), 0, sizeof(struct proc_app_window_info)); + + return RESOURCED_ERROR_NONE; +} + static struct proc_program_info *find_program_info(const char *pkgname) { GSList *iter = NULL; @@ -991,6 +1121,10 @@ EXPORT_TEST void proc_app_info_remove_child_pid(struct proc_app_info *pai, pid_t if (!g_slist_find(pai->childs, PID_TO_GPOINTER(pid))) return; + if (proc_unregister_window_of_process(pai, pid) < 0) + _E("Failed to unregister window of app (%s, pid = %d)", + pai->appid, pid); + pai->childs = g_slist_remove(pai->childs, PID_TO_GPOINTER(pid)); if (!g_slist_length(pai->childs)) goto remove_all; @@ -1034,6 +1168,9 @@ EXPORT_TEST void proc_remove_app_info(struct proc_app_info *pai) if (!pai) return; + if (proc_unregister_window_of_app(pai) < 0) + _E("Failed to unregiser window of app (%s)", pai->appid); + proc_app_info_remove_child_pid(pai, 0); proc_remove_program_info(pai->program, pai); @@ -1328,6 +1465,10 @@ static int resourced_proc_init(void* data) return RESOURCED_ERROR_FAIL; } + app_list.window_owner_table = + g_hash_table_new_full(g_int_hash, g_int_equal, NULL, NULL); + g_assert(app_list.window_owner_table); + proc_module_init(data); return RESOURCED_ERROR_NONE; } @@ -1337,6 +1478,7 @@ static int resourced_proc_exit(void* data) if (prelaunch) free(prelaunch); proc_delete_all_lists(); + g_hash_table_destroy(app_list.window_owner_table); proc_module_exit(data); return RESOURCED_ERROR_NONE; } diff --git a/src/process/proc-main.h b/src/process/proc-main.h index d9f0723..396733d 100644 --- a/src/process/proc-main.h +++ b/src/process/proc-main.h @@ -40,6 +40,7 @@ extern "C" { struct proc_app_list { GSList *list; + GHashTable *window_owner_table; pthread_mutex_t lock; pid_t tid; uint32_t ref; @@ -85,6 +86,10 @@ void proc_set_group(pid_t ownerpid, pid_t childpid, char *pkgname); int proc_get_state(int type, pid_t pid, char *buf, int len); +int proc_register_window_in_app_info(struct proc_app_info *pai, + struct proc_app_window_info *new_window); +int proc_unregister_windows(void); + #ifdef _UNIT_TEST void proc_app_info_add_child_pid(struct proc_app_info *pai, pid_t pid); struct proc_app_info *proc_create_app_info( diff --git a/src/process/proc-monitor.c b/src/process/proc-monitor.c index 40bd847..ffe5978 100644 --- a/src/process/proc-monitor.c +++ b/src/process/proc-monitor.c @@ -138,6 +138,11 @@ static int insert_window_info_in_proc_app_info(GHashTable *window_table) return RESOURCED_ERROR_INVALID_PARAMETER; } + if (proc_unregister_windows() < 0) { + _E("Failed to unregister all windows"); + return RESOURCED_ERROR_FAIL; + } + g_hash_table_iter_init(&iter, window_table); while (g_hash_table_iter_next(&iter, &pid, &value)) { window = (struct proc_app_window_info *)value; @@ -150,12 +155,11 @@ static int insert_window_info_in_proc_app_info(GHashTable *window_table) if (pai == NULL) continue; - memcpy(&pai->window, window, sizeof(struct proc_app_window_info)); - _D("app = %s, pid = %d, is_focused = %d, " - "visibility = %d, x = %d, y = %d, z = %d", - pai->appid, pai->window.pid, - pai->window.is_focused, pai->window.visibility, - pai->window.x, pai->window.y, pai->window.z); + if (proc_register_window_in_app_info(pai, window) < 0) { + _E("Failed to register window of app (%s)", pai->appid); + + return proc_unregister_windows(); + } } return RESOURCED_ERROR_NONE; @@ -261,6 +265,8 @@ static int dbus_update_window_stack(pid_t pid, bool has_focus) error_to_parse_window_stack: free_window_stack(iter, reply, window_table); + _D("Failed to udpate window stack"); + return RESOURCED_ERROR_FAIL; } @@ -1191,6 +1197,12 @@ EXPORT_TEST void proc_dbus_aul_group(GVariant *params) _D("received process grouping : owner %d, child %d, previous appid %s", ownerpid, childpid, appid); proc_set_group(ownerpid, childpid, appid); + /** + * TODO: Do not update window stack when processes are grouping. + * Instead, merge windows between processes to reduce the number of + * window stack update. (Window stack update is based on dbus method call) + */ + dbus_update_window_stack(0, false); } EXPORT_TEST void proc_dbus_aul_terminated(GVariant *params) -- 2.7.4