2 * Copyright (c) 2018 Samsung Electronics Co., Ltd.
4 * Licensed under the Flora License, Version 1.1 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://floralicense.org/license/
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
22 #include "appinfo-provider.h"
23 #include "err-check.h"
26 #define AUL_APPSTATUS_OBJECT_PATH "/Org/Tizen/Aul/AppStatus"
27 #define AUL_APPSTATUS_INTERFACE_NAME "org.tizen.aul.AppStatus"
28 #define SIGNAL_AMD_LAUNCH "AppLaunch"
29 #define SIGNAL_AMD_TERMINATED "AppTerminated"
31 struct app_info_descriptor
37 static struct app_info_data
41 GDBusConnection *dbus_conn;
47 struct app_info_iterator
53 typedef void(*dbus_signal_cb)(GVariant *parameters);
55 static void add_app(int pid, const char *app_id);
56 static void remove_app_by_pid(int pid);
57 static GDBusConnection *dbus_create_connection();
58 static void dbus_register_signal(const char *path, const char *interface,
59 const char *name, dbus_signal_cb callback);
61 static int running_apps_iter(const aul_app_info* info, void* data);
62 static void app_launched(GVariant *parameters);
63 static void app_terminated(GVariant *parameters);
65 bool app_info_iterator_next(app_info_iterator_t *iter)
67 ON_NULL_RETURN_VAL(iter, false);
69 if (iter->position >= iter->data->len - 1)
76 const char *app_info_iterator_get_app_id(app_info_iterator_t *iter)
78 ON_NULL_RETURN_VAL(iter, NULL);
80 struct app_info_descriptor elem = g_array_index(iter->data, struct app_info_descriptor, iter->position);
84 int app_info_iterator_get_pid(app_info_iterator_t *iter)
86 ON_NULL_RETURN_VAL(iter, -1);
88 struct app_info_descriptor elem = g_array_index(iter->data, struct app_info_descriptor, iter->position);
92 void app_info_iterator_free(app_info_iterator_t *iter)
96 struct app_info_descriptor elem;
97 for (int i = 0; i < iter->data->len; i++)
99 elem = g_array_index(app_info.app_data, struct app_info_descriptor, i);
103 g_array_free(iter->data, TRUE);
108 app_info_iterator_t *app_info_provider_get_running_applications()
110 struct app_info_descriptor elem;
111 struct app_info_iterator *iter = (struct app_info_iterator *)g_malloc(sizeof(struct app_info_iterator));
113 iter->data = g_array_new(FALSE, TRUE, sizeof(struct app_info_descriptor));
115 g_mutex_lock(&app_info.mutex);
117 for (int i = 0; i < app_info.app_data->len; i++)
119 elem = g_array_index(app_info.app_data, struct app_info_descriptor, i);
120 struct app_info_descriptor cpy;
123 cpy.app_id = strdup(elem.app_id);
125 g_array_append_val(iter->data, cpy);
128 g_mutex_unlock(&app_info.mutex);
130 if (iter->data->len == 0)
132 g_array_free(iter->data, TRUE);
140 int app_info_provider_find_main_pid(const char *app_id)
142 ON_NULL_RETURN_VAL(app_id, -1);
144 struct app_info_descriptor elem;
146 g_mutex_lock(&app_info.mutex);
148 for (int i = 0; i < app_info.app_data->len; i++)
150 elem = g_array_index(app_info.app_data, struct app_info_descriptor, i);
152 if (elem.app_id && strcmp(elem.app_id, app_id) == 0)
154 g_mutex_unlock(&app_info.mutex);
159 g_mutex_unlock(&app_info.mutex);
163 char *app_info_provider_find_app_id(int pid)
165 struct app_info_descriptor elem;
167 g_mutex_lock(&app_info.mutex);
169 for (int i = 0; i < app_info.app_data->len; i++)
171 elem = g_array_index(app_info.app_data, struct app_info_descriptor, i);
173 if (elem.pid == pid && elem.app_id)
175 char *id = strdup(elem.app_id);
176 g_mutex_unlock(&app_info.mutex);
181 g_mutex_unlock(&app_info.mutex);
185 int app_provider_init()
187 g_mutex_init(&app_info.mutex);
188 app_info.app_data = g_array_new(FALSE, TRUE, sizeof(struct app_info_descriptor));
190 app_info.dbus_conn = dbus_create_connection();
191 if (!(app_info.dbus_conn))
194 aul_app_get_all_running_app_info(running_apps_iter, NULL);
196 dbus_register_signal(AUL_APPSTATUS_OBJECT_PATH, AUL_APPSTATUS_INTERFACE_NAME, SIGNAL_AMD_LAUNCH, app_launched);
197 dbus_register_signal(AUL_APPSTATUS_OBJECT_PATH, AUL_APPSTATUS_INTERFACE_NAME, SIGNAL_AMD_TERMINATED, app_terminated);
202 void app_provider_shutdown()
204 g_array_free(app_info.app_data, TRUE);
205 g_object_unref(app_info.dbus_conn);
206 g_mutex_clear(&app_info.mutex);
209 static int running_apps_iter(const aul_app_info* info, void* data)
211 add_app(info->pid, info->appid);
215 static void add_app(int pid, const char *app_id)
217 ON_NULL_RETURN(app_id);
219 struct app_info_descriptor descr;
223 int len = strlen(app_id) + 1;
224 char *_app_id = (char *)g_malloc(len * sizeof(char));
225 snprintf(_app_id, len, "%s", app_id);
226 descr.app_id = _app_id;
228 g_mutex_lock(&app_info.mutex);
230 g_array_append_val(app_info.app_data, descr);
232 g_mutex_unlock(&app_info.mutex);
235 static void remove_app_by_pid(int pid)
237 g_mutex_lock(&app_info.mutex);
238 struct app_info_descriptor elem;
240 for (int i = 0; i < app_info.app_data->len; i++)
242 elem = g_array_index(app_info.app_data, struct app_info_descriptor, i);
246 g_array_remove_index(app_info.app_data, i);
250 g_mutex_unlock(&app_info.mutex);
253 static GDBusConnection *dbus_create_connection()
256 GDBusConnection *conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
259 ERR("Failed to create GDbusConnection ", err->message);
267 static void d_bus_signal_handler(GDBusConnection *connection,
268 const gchar *sender, const gchar *object_path,
269 const gchar *interface_name, const gchar *signal_name,
270 GVariant *parameters, gpointer user_data)
272 dbus_signal_cb cb = (dbus_signal_cb)user_data;
279 static void dbus_register_signal(const char *path, const char *interface,
280 const char *name, dbus_signal_cb callback)
282 g_dbus_connection_signal_subscribe(app_info.dbus_conn,
283 NULL, interface, name, path, NULL, G_DBUS_SIGNAL_FLAGS_NONE,
284 d_bus_signal_handler, callback, NULL);
287 static void app_launched(GVariant *parameters)
292 char *pkg_type = NULL;
294 g_variant_get(parameters, "(i&s&s&s)", &pid, &app_id, &pkg_id, &pkg_type);
295 if (pid == 0 || !app_id || !pkg_id || !pkg_type) {
296 ERR("There is no message");
300 add_app(pid, app_id);
303 static void app_terminated(GVariant *parameters)
307 g_variant_get(parameters, "(i)", &pid);
309 ERR("There is no message");
313 remove_app_by_pid(pid);