Fixed a issue for using heap after free
[platform/core/connectivity/stc-manager.git] / src / monitor / stc-application-lifecycle.c
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include "stc-application-lifecycle.h"
18
19 /*
20  * AUL
21  */
22 #define AUL_APP_STATUS_DBUS_PATH                   "/Org/Tizen/Aul/AppStatus"
23 #define AUL_APP_STATUS_DBUS_SIGNAL_INTERFACE       "org.tizen.aul.AppStatus"
24 #define AUL_APP_STATUS_BUS_NAME                    AUL_APP_STATUS_DBUS_SIGNAL_INTERFACE
25
26 #define AUL_APP_STATUS_DBUS_LAUNCH_REQUEST         "AppLaunch"
27 #define AUL_APP_STATUS_DBUS_LAUNCH_REQUEST_TYPE    "(isss)"
28
29 #define AUL_APP_STATUS_DBUS_STATUS_CHANGE          "AppStatusChange"
30 #define AUL_APP_STATUS_DBUS_STATUS_CHANGE_TYPE     "(issss)"
31
32 #define AUL_APP_STATUS_DBUS_GROUP                  "AppGroup"
33 #define AUL_APP_STATUS_DBUS_GROUP_TYPE             "(iis)"
34
35 #define AUL_APP_STATUS_DBUS_TERMINATED             "AppTerminated"
36 #define AUL_APP_STATUS_DBUS_TERMINATED_TYPE        "(i)"
37
38 typedef enum {
39         STC_CMD_NONE,
40         STC_CMD_SET_FOREGRD,
41         STC_CMD_SET_BACKGRD,
42         STC_CMD_SET_APP_LAUNCHED,
43         STC_CMD_SET_SERVICE_LAUNCHED,
44         STC_CMD_SET_TERMINATED,
45         STC_CMD_MAX_ELEM
46 } stc_cmd_type_e;
47
48 typedef struct {
49         guint sub_id;
50         const gchar *path;
51         const gchar *interface;
52         const gchar *member;
53         const gchar *param_type;
54         GDBusSignalCallback callback;
55         gpointer user_data;
56 } signal_map_s;
57
58 static stc_error_e __stc_manager_app_status_changed(stc_cmd_type_e cmd,
59                                                     pid_t pid,
60                                                     gchar *app_id,
61                                                     gchar *pkg_id,
62                                                     stc_app_type_e app_type)
63 {
64         __STC_LOG_FUNC_ENTER__;
65         stc_error_e ret = STC_ERROR_NONE;
66
67         switch (cmd) {
68         case STC_CMD_SET_FOREGRD:
69         {
70                 stc_app_key_s app_key;
71                 stc_app_value_s app_value;
72                 stc_process_key_s proc_key;
73                 stc_process_value_s proc_value;
74
75                 memset(&app_key, 0, sizeof(stc_app_key_s));
76                 memset(&app_value, 0, sizeof(stc_app_value_s));
77                 memset(&proc_key, 0, sizeof(stc_process_key_s));
78                 memset(&proc_value, 0, sizeof(stc_process_value_s));
79
80                 app_key.pkg_id = g_strdup(pkg_id);
81                 app_key.app_id = g_strdup(app_id);
82
83                 app_value.type = app_type;
84                 app_value.processes = NULL;
85
86                 proc_key.pid = pid;
87
88                 proc_value.ground = STC_APP_STATE_FOREGROUND;
89
90                 stc_monitor_application_add(app_key, app_value);
91                 stc_monitor_process_add(app_key, proc_key, proc_value);
92                 stc_monitor_process_update_ground(app_key, proc_key,
93                                                   STC_APP_STATE_FOREGROUND);
94
95                 FREE(app_key.pkg_id);
96                 FREE(app_key.app_id);
97                 break;
98         }
99         case STC_CMD_SET_BACKGRD:
100         {
101                 stc_app_key_s app_key;
102                 stc_app_value_s app_value;
103                 stc_process_key_s proc_key;
104                 stc_process_value_s proc_value;
105
106                 memset(&app_key, 0, sizeof(stc_app_key_s));
107                 memset(&app_value, 0, sizeof(stc_app_value_s));
108                 memset(&proc_key, 0, sizeof(stc_process_key_s));
109                 memset(&proc_value, 0, sizeof(stc_process_value_s));
110
111                 app_key.pkg_id = g_strdup(pkg_id);
112                 app_key.app_id = g_strconcat(app_id, STC_BACKGROUND_APP_SUFFIX,
113                                              NULL);
114
115                 app_value.type = app_type;
116                 app_value.processes = NULL;
117
118                 proc_key.pid = pid;
119
120                 proc_value.ground = STC_APP_STATE_BACKGROUND;
121
122                 stc_monitor_application_add(app_key, app_value);
123                 stc_monitor_process_add(app_key, proc_key, proc_value);
124                 stc_monitor_process_update_ground(app_key, proc_key,
125                                                   STC_APP_STATE_BACKGROUND);
126
127                 FREE(app_key.pkg_id);
128                 FREE(app_key.app_id);
129                 break;
130         }
131         case STC_CMD_SET_APP_LAUNCHED:
132         {
133                 stc_app_key_s app_key;
134                 stc_app_value_s app_value;
135                 stc_process_key_s proc_key;
136                 stc_process_value_s proc_value;
137
138                 memset(&app_key, 0, sizeof(stc_app_key_s));
139                 memset(&app_value, 0, sizeof(stc_app_value_s));
140                 memset(&proc_key, 0, sizeof(stc_process_key_s));
141                 memset(&proc_value, 0, sizeof(stc_process_value_s));
142
143                 app_key.pkg_id = g_strdup(pkg_id);
144                 app_key.app_id = g_strdup(app_id);
145
146                 app_value.type = app_type;
147                 app_value.processes = NULL;
148
149                 proc_key.pid = pid;
150
151                 proc_value.ground = STC_APP_STATE_UNKNOWN;
152
153                 /* create foreground cgroup */
154                 stc_monitor_application_add(app_key, app_value);
155                 stc_monitor_process_add(app_key, proc_key, proc_value);
156
157                 /* create background cgroup */
158                 FREE(app_key.app_id);
159
160                 app_key.app_id = g_strconcat(app_id, STC_BACKGROUND_APP_SUFFIX,
161                                              NULL);
162                 stc_monitor_application_add(app_key, app_value);
163
164                 FREE(app_key.pkg_id);
165                 g_free(app_key.app_id);
166                 break;
167         }
168         case STC_CMD_SET_SERVICE_LAUNCHED:
169         {
170                 stc_app_key_s app_key;
171                 stc_app_value_s app_value;
172                 stc_process_key_s proc_key;
173                 stc_process_value_s proc_value;
174
175                 memset(&app_key, 0, sizeof(stc_app_key_s));
176                 memset(&app_value, 0, sizeof(stc_app_value_s));
177                 memset(&proc_key, 0, sizeof(stc_process_key_s));
178                 memset(&proc_value, 0, sizeof(stc_process_value_s));
179
180                 app_key.pkg_id = g_strdup(pkg_id);
181                 app_key.app_id = g_strconcat(app_id, STC_BACKGROUND_APP_SUFFIX,
182                                              NULL);
183
184                 app_value.type = app_type;
185                 app_value.processes = NULL;
186
187                 proc_key.pid = pid;
188
189                 /* services will run always in background. */
190                 proc_value.ground = STC_APP_STATE_BACKGROUND;
191
192                 stc_monitor_application_add(app_key, app_value);
193                 stc_monitor_process_add(app_key, proc_key, proc_value);
194
195                 FREE(app_key.pkg_id);
196                 g_free(app_key.app_id);
197                 break;
198         }
199         case STC_CMD_SET_TERMINATED:
200         {
201                 stc_monitor_process_remove(pid);
202                 break;
203         }
204         default:
205                 STC_LOGE("Unhandled command");
206                 ret = STC_ERROR_INVALID_PARAMETER;
207         }
208
209         __STC_LOG_FUNC_EXIT__;
210         return ret;
211 }
212
213 static void __stc_gdbus_handle_aul_launch(GDBusConnection *connection,
214                                           const gchar *sender_name,
215                                           const gchar *object_path,
216                                           const gchar *interface_name,
217                                           const gchar *signal_name,
218                                           GVariant *parameters,
219                                           gpointer user_data)
220 {
221         __STC_LOG_FUNC_ENTER__;
222         pid_t pid;
223         stc_cmd_type_e status;
224         stc_app_type_e apptype;
225         gchar *appid, *pkgid, *pkgtype;
226
227         RETURN_IF_DBUS_TYPE_MISMATCH(parameters,
228                                      AUL_APP_STATUS_DBUS_LAUNCH_REQUEST_TYPE);
229
230         g_variant_get(parameters, AUL_APP_STATUS_DBUS_LAUNCH_REQUEST_TYPE,
231                       &pid, &appid, &pkgid, &pkgtype);
232
233         if (!strncmp(pkgtype, "svc", 3)) {
234                 apptype = STC_APP_TYPE_SERVICE;
235                 status = STC_CMD_SET_SERVICE_LAUNCHED;
236
237         } else if (!strncmp(pkgtype, "ui", 2)) {
238                 apptype = STC_APP_TYPE_GUI;
239                 status = STC_CMD_SET_APP_LAUNCHED;
240
241         } else if (!strncmp(pkgtype, "widget", 6)) {
242                 apptype = STC_APP_TYPE_WIDGET;
243                 status = STC_CMD_SET_APP_LAUNCHED;
244
245         } else if (!strncmp(pkgtype, "watch", 5)) {
246                 apptype = STC_APP_TYPE_WATCH;
247                 status = STC_CMD_SET_APP_LAUNCHED;
248
249         } else {
250                 __STC_LOG_FUNC_EXIT__;
251                 goto handle_error;
252         }
253
254         __stc_manager_app_status_changed(status, pid, appid, pkgid, apptype);
255
256         __STC_LOG_FUNC_EXIT__;
257 handle_error:
258         FREE(appid);
259         FREE(pkgid);
260         FREE(pkgtype);
261 }
262
263 static void __stc_gdbus_handle_aul_changestate(GDBusConnection *connection,
264                                                const gchar *sender_name,
265                                                const gchar *object_path,
266                                                const gchar *interface_name,
267                                                const gchar *signal_name,
268                                                GVariant *parameters,
269                                                gpointer user_data)
270 {
271         __STC_LOG_FUNC_ENTER__;
272         pid_t pid;
273         stc_cmd_type_e status;
274         stc_app_type_e apptype;
275         gchar *appid, *pkgid, *statstr, *pkgtype;
276
277         RETURN_IF_DBUS_TYPE_MISMATCH(parameters,
278                                      AUL_APP_STATUS_DBUS_STATUS_CHANGE_TYPE);
279
280         g_variant_get(parameters, AUL_APP_STATUS_DBUS_STATUS_CHANGE_TYPE,
281                       &pid, &appid, &pkgid, &statstr, &pkgtype);
282
283         if (!strncmp(statstr, "fg", 2)) {
284                 status = STC_CMD_SET_FOREGRD;
285         } else if (!strncmp(statstr, "bg", 2)) {
286                 status = STC_CMD_SET_BACKGRD;
287         } else {
288                 __STC_LOG_FUNC_EXIT__;
289                 goto handle_error;
290         }
291
292         if (!strncmp(pkgtype, "svc", 3))
293                 apptype = STC_APP_TYPE_SERVICE;
294         else if (!strncmp(pkgtype, "widget", 6))
295                 apptype = STC_APP_TYPE_WIDGET;
296         else if (!strncmp(pkgtype, "watch", 5))
297                 apptype = STC_APP_TYPE_WATCH;
298         else
299                 apptype = STC_APP_TYPE_GUI;
300
301         __stc_manager_app_status_changed(status, pid, appid, pkgid, apptype);
302
303         __STC_LOG_FUNC_EXIT__;
304 handle_error:
305         FREE(appid);
306         FREE(pkgid);
307         FREE(statstr);
308         FREE(pkgtype);
309 }
310
311 static void __stc_gdbus_handle_aul_group(GDBusConnection *connection,
312                                          const gchar *sender_name,
313                                          const gchar *object_path,
314                                          const gchar *interface_name,
315                                          const gchar *signal_name,
316                                          GVariant *parameters,
317                                          gpointer user_data)
318 {
319         __STC_LOG_FUNC_ENTER__;
320         pid_t ownerpid, childpid;
321         gchar *appid;
322
323         RETURN_IF_DBUS_TYPE_MISMATCH(parameters,
324                                      AUL_APP_STATUS_DBUS_GROUP_TYPE);
325
326         g_variant_get(parameters, AUL_APP_STATUS_DBUS_GROUP_TYPE,
327                       &ownerpid, &childpid, &appid);
328
329         if (ownerpid == childpid) {
330                 STC_LOGD("Skip merge, when one app %d makes multiple window.",
331                          ownerpid);
332                 __STC_LOG_FUNC_EXIT__;
333                 goto handle_error;
334         }
335
336         STC_LOGD("received process grouping : owner %d, child %d, previous appid %s",
337                  ownerpid, childpid, appid);
338
339         /**
340          * TODO: app_set_group(ownerpid, childpid, appid)
341          */
342
343         __STC_LOG_FUNC_EXIT__;
344 handle_error:
345         FREE(appid);
346 }
347
348 static void __stc_gdbus_handle_aul_terminated(GDBusConnection *connection,
349                                               const gchar *sender_name,
350                                               const gchar *object_path,
351                                               const gchar *interface_name,
352                                               const gchar *signal_name,
353                                               GVariant *parameters,
354                                               gpointer user_data)
355 {
356         __STC_LOG_FUNC_ENTER__;
357         pid_t pid;
358         stc_cmd_type_e status = STC_CMD_SET_TERMINATED;
359
360         RETURN_IF_DBUS_TYPE_MISMATCH(parameters,
361                                      AUL_APP_STATUS_DBUS_TERMINATED_TYPE);
362
363         g_variant_get(parameters, AUL_APP_STATUS_DBUS_TERMINATED_TYPE,
364                       &pid);
365
366         __stc_manager_app_status_changed(status, pid, NULL, NULL,
367                                          STC_APP_TYPE_NONE);
368
369         __STC_LOG_FUNC_EXIT__;
370 }
371
372 signal_map_s signal_map[] = {
373
374         /* AMD DBUS */
375         {
376                 0,
377                 AUL_APP_STATUS_DBUS_PATH,
378                 AUL_APP_STATUS_DBUS_SIGNAL_INTERFACE,
379                 AUL_APP_STATUS_DBUS_LAUNCH_REQUEST,
380                 AUL_APP_STATUS_DBUS_LAUNCH_REQUEST_TYPE,
381                 __stc_gdbus_handle_aul_launch,
382                 NULL
383         },
384         {
385                 0,
386                 AUL_APP_STATUS_DBUS_PATH,
387                 AUL_APP_STATUS_DBUS_SIGNAL_INTERFACE,
388                 AUL_APP_STATUS_DBUS_STATUS_CHANGE,
389                 AUL_APP_STATUS_DBUS_STATUS_CHANGE_TYPE,
390                 __stc_gdbus_handle_aul_changestate,
391                 NULL
392         },
393         {
394                 0,
395                 AUL_APP_STATUS_DBUS_PATH,
396                 AUL_APP_STATUS_DBUS_SIGNAL_INTERFACE,
397                 AUL_APP_STATUS_DBUS_GROUP,
398                 AUL_APP_STATUS_DBUS_GROUP_TYPE,
399                 __stc_gdbus_handle_aul_group,
400                 NULL
401         },
402         {
403                 0,
404                 AUL_APP_STATUS_DBUS_PATH,
405                 AUL_APP_STATUS_DBUS_SIGNAL_INTERFACE,
406                 AUL_APP_STATUS_DBUS_TERMINATED,
407                 AUL_APP_STATUS_DBUS_TERMINATED_TYPE,
408                 __stc_gdbus_handle_aul_terminated,
409                 NULL
410         },
411         {
412                 0,
413                 NULL,
414                 NULL,
415                 NULL,
416                 NULL
417         }
418 };
419
420 stc_error_e stc_application_lifecycle_monitor_init(stc_s *stc)
421 {
422         guint i = 0;
423         ret_value_msg_if(stc == NULL, STC_ERROR_INVALID_PARAMETER, "failed to get stc data");
424
425         for (i = 0; signal_map[i].member != NULL; i++) {
426                 signal_map[i].sub_id =
427                         stc_manager_gdbus_subscribe_signal(stc->connection,
428                                                            NULL,
429                                                            signal_map[i].interface,
430                                                            signal_map[i].member,
431                                                            signal_map[i].path,
432                                                            NULL,
433                                                            G_DBUS_SIGNAL_FLAGS_NONE,
434                                                            signal_map[i].callback,
435                                                            signal_map[i].user_data,
436                                                            NULL);
437                 STC_LOGI("Successfully subscribed [%s] signal",
438                          signal_map[i].member);
439         }
440
441         return STC_ERROR_NONE;
442 }
443
444 stc_error_e stc_application_lifecycle_monitor_deinit(stc_s *stc)
445 {
446         guint i = 0;
447         ret_value_msg_if(stc == NULL, STC_ERROR_INVALID_PARAMETER, "failed to get stc data");
448
449         for (i = 0; signal_map[i].member != NULL; i++) {
450                 stc_manager_gdbus_unsubscribe_signal(stc->connection,
451                                                      signal_map[i].sub_id);
452                 signal_map[i].sub_id = 0;
453                 STC_LOGD("Successfully unsubscribed [%s] signal",
454                          signal_map[i].member);
455         }
456
457         return STC_ERROR_NONE;
458 }