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;
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;
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);
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;
}
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;
}
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;
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;
error_to_parse_window_stack:
free_window_stack(iter, reply, window_table);
+ _D("Failed to udpate window stack");
+
return RESOURCED_ERROR_FAIL;
}
_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)