proc: Reset the window stack information from proc_app_info 63/296563/5
authorUnsung Lee <unsung.lee@samsung.com>
Mon, 31 Jul 2023 11:17:47 +0000 (20:17 +0900)
committerUnsung Lee <unsung.lee@samsung.com>
Wed, 2 Aug 2023 04:46:22 +0000 (13:46 +0900)
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 <unsung.lee@samsung.com>
src/process/proc-main.c
src/process/proc-main.h
src/process/proc-monitor.c

index b09f2dd..7eb1f2c 100644 (file)
@@ -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;
 }
index d9f0723..396733d 100644 (file)
@@ -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(
index 40bd847..ffe5978 100644 (file)
@@ -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)