Event Systemd Daemon : initail commit
[platform/core/appfw/event-system.git] / src / esd_main.c
1 #include <stdio.h>
2 #include <glib.h>
3 #include <aul.h>
4 #include <unistd.h>
5 #include <ctype.h>
6 #include <dlog.h>
7 #include <Ecore.h>
8 #include <gio/gio.h>
9 #include <assert.h>
10 #include <package-manager.h>
11 #include <pkgmgr-info.h>
12 #include <appsvc/appsvc.h>
13 #include <eventsystem.h>
14 #include <bundle.h>
15
16 #undef LOG_TAG
17 #define LOG_TAG "ESD"
18
19 #define _E(fmt, arg...) LOGE(fmt, ##arg)
20 #define _D(fmt, arg...) LOGD(fmt, ##arg)
21 #define _W(fmt, arg...) LOGW(fmt, ##arg)
22 #define _I(fmt, arg...) LOGI(fmt, ##arg)
23
24 #define retvm_if(expr, val, fmt, arg...) do { \
25         if (expr) { \
26                 _E(fmt, ##arg); \
27                 _E("(%s) -> %s() return", #expr, __func__); \
28                 return val; \
29         } \
30 } while (0)
31
32 #define retv_if(expr, val) do { \
33         if (expr) { \
34                 _E("(%s) -> %s() return", #expr, __func__); \
35                 return val; \
36         } \
37 } while (0)
38
39 static GHashTable *event_launch_table; /* table of events for launch_on_event*/
40
41 #ifdef APPFW_EVENT_SYSTEM_EARLIER_FEATURE
42 const char *earlier_event_list[] = {
43         SYS_EVENT_ESD_STATUS,
44         SYS_EVENT_BATTERY_CHARGER_STATUS,
45         SYS_EVENT_USB_STATUS,
46         SYS_EVENT_LOW_MEMORY,
47         SYS_EVENT_BOOT_COMPLETED,
48         SYS_EVENT_SYSTEM_SHUTDOWN
49 };
50
51 static GHashTable *earlier_event_table; /* table of events for earlier_data */
52
53 typedef struct __earlier_table_item {
54         char *event_name;
55         guint reg_id;
56         bundle *earlier_data; /* event-data from earlier occurrence */
57 } earlier_item;
58 #endif
59
60 typedef struct __eventlaunch_item_param {
61         char *app_id;
62 } eventlaunch_item_param_s;
63
64 typedef struct esd_list_item {
65         char *pkg_id;
66         char *app_id;
67 } esd_list_item_s;
68
69 typedef struct  __event_launch_table_item {
70         char *event_name;
71         char *package_name; /* just for passing pointer to app-list removal func */
72         GList *app_list_evtlaunch; /* app-list for on-event-launch */
73         guint reg_id;
74 } event_launch_item;
75
76 enum __pkg_event_type {
77         UNKNOWN = 0,
78         INSTALL,
79         UNINSTALL,
80         UPDATE,
81 };
82
83 typedef struct __pkgmgr_event {
84         int type;
85         char *pkgid;
86 } esd_pkgmgr_event;
87
88 typedef struct __esd_event_param {
89         char *event_name;
90         bundle *event_data;
91         void *user_data;
92 } esd_event_param;
93
94 typedef struct esd_info {
95         pkgmgr_client *client;
96 } esd_info_s;
97 static esd_info_s s_info;
98
99
100 static void __esd_event_handler(char *event_name, bundle *data, void *user_data);
101
102 static int __get_sender_pid(GDBusConnection *conn, const char *sender_name)
103 {
104         GDBusMessage *msg = NULL;
105         GDBusMessage *reply = NULL;
106         GError *err = NULL;
107         GVariant *body;
108         int pid = 0;
109
110         msg = g_dbus_message_new_method_call("org.freedesktop.DBus", "/org/freedesktop/DBus",
111                 "org.freedesktop.DBus", "GetConnectionUnixProcessID");
112         if (!msg) {
113                 _D("Can't allocate new method call");
114                 goto out;
115         }
116
117         g_dbus_message_set_body(msg, g_variant_new ("(s)", sender_name));
118         reply = g_dbus_connection_send_message_with_reply_sync(conn, msg,
119                 G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, NULL, NULL, &err);
120
121         if (!reply) {
122                 if (err != NULL) {
123                         _E("Failed to get pid [%s]", err->message);
124                         g_error_free(err);
125                 }
126                 goto out;
127         }
128
129         body = g_dbus_message_get_body(reply);
130         g_variant_get(body, "(u)", &pid);
131
132 out:
133         if (msg)
134                 g_object_unref(msg);
135         if (reply)
136                 g_object_unref(reply);
137
138   return pid;
139 }
140
141 static bool __esd_is_service_app(const char *appid)
142 {
143         int ret = 0;
144         bool is_svcapp = false;
145         pkgmgrinfo_app_component component_type;
146         pkgmgrinfo_appinfo_h handle;
147
148         ret = pkgmgrinfo_appinfo_get_usr_appinfo(appid, getuid(), &handle);
149         if (ret != PMINFO_R_OK)
150                 return false;
151
152         ret = pkgmgrinfo_appinfo_get_component(handle, &component_type);
153         if (ret != PMINFO_R_OK) {
154                 pkgmgrinfo_appinfo_destroy_appinfo(handle);
155                 return false;
156         }
157
158         _D("component_type : %d %d", component_type, PMINFO_SVC_APP);
159
160         if (component_type == PMINFO_SVC_APP) {
161                 is_svcapp = true;
162         }
163         pkgmgrinfo_appinfo_destroy_appinfo(handle);
164
165         return is_svcapp;
166 }
167
168 void __esd_free_noti(gpointer data)
169 {
170         eventsystem_info_s *n = (eventsystem_info_s *)data;
171
172         FREE_AND_NULL(n->appid);
173         FREE_AND_NULL(n->event_name);
174         FREE_AND_NULL(n);
175 }
176
177 void __esd_free_app_list(gpointer data)
178 {
179         char *n = (char *)data;
180
181         FREE_AND_NULL(n);
182 }
183
184 static void esd_print_appid_with_eventid(gpointer data, gpointer user_data)
185 {
186         esd_list_item_s *item = (esd_list_item_s *)data;
187         char *event_name = (char *)user_data;
188
189         _D("event_name(%s)-app_id(%s)-pkg_id(%s)", event_name, item->app_id, item->pkg_id);
190 }
191
192 static void esd_print_interested_event(gpointer data, gpointer user_data)
193 {
194         event_launch_item *el_item = (event_launch_item *)data;
195         char *event_name = (char *)el_item->event_name;
196         _D("event_name = (%s)", event_name);
197         g_list_foreach(el_item->app_list_evtlaunch, esd_print_appid_with_eventid, event_name);
198 }
199
200 static void esd_launch_table_print_items(void)
201 {
202         GHashTableIter iter;
203         gpointer key, value;
204
205         g_hash_table_iter_init(&iter, event_launch_table);
206
207         while (g_hash_table_iter_next(&iter, &key, &value)) {
208                 esd_print_interested_event(value, NULL);
209         }
210 }
211
212 static void __esd_print_event_list_of_app(gpointer data, gpointer user_data)
213 {
214         eventsystem_info_s *esi = (eventsystem_info_s *)data;
215         _D("esi : appid(%s), eventid(%s)", esi->appid, esi->event_name);
216 }
217
218 static void esd_print_event_list_of_app(GList *list)
219 {
220         g_list_foreach(list, __esd_print_event_list_of_app, NULL);
221 }
222
223 static int esd_find_compare_by_list_item(gconstpointer data, gconstpointer user_data)
224 {
225         esd_list_item_s *item_1 = (esd_list_item_s *)user_data;
226         esd_list_item_s *item_2 = (esd_list_item_s *)data;
227
228         return strcmp(item_1->app_id, item_2->app_id) |
229                 strcmp(item_1->pkg_id, item_2->pkg_id);
230 }
231
232 static int __esd_get_pkgid_by_appid(const char *app_id, char **pkg_id)
233 {
234         pkgmgrinfo_appinfo_h handle = NULL;
235         char *temp_val = NULL;
236         int ret = 0;
237
238         *pkg_id = NULL;
239
240         ret = pkgmgrinfo_appinfo_get_usr_appinfo(app_id, getuid(), &handle);
241         if (ret < 0) {
242                 _E("failed to get appinfo");
243                 ret = ES_R_ERROR;
244                 goto out;
245         }
246
247         ret = pkgmgrinfo_appinfo_get_pkgname(handle, &temp_val);
248         if (ret == PMINFO_R_OK && temp_val) {
249                 *pkg_id = strdup(temp_val);
250                 _D("pkg_id(%s)", *pkg_id);
251         } else {
252                 _E("failed to get pkgname");
253                 ret = pkgmgrinfo_appinfo_destroy_appinfo(handle);
254                 if (ret != PMINFO_R_OK) {
255                         _E("failed to destroy appinfo");
256                 }
257                 ret = ES_R_ERROR;
258                 goto out;
259         }
260         ret = pkgmgrinfo_appinfo_destroy_appinfo(handle);
261         if (ret != PMINFO_R_OK) {
262                 _E("failed to destroy appinfo");
263                 free(*pkg_id);
264                 ret = ES_R_ERROR;
265                 goto out;
266         }
267
268         ret = ES_R_OK;
269
270 out:
271         return ret;
272 }
273
274 static int __esd_add_list_item(event_launch_item *el_item,
275                 const char *app_id, const char *pkg_id)
276 {
277         char *_pkgid = NULL;
278         esd_list_item_s *item_of_list = NULL;
279
280         if (pkg_id == NULL) {
281                 if (__esd_get_pkgid_by_appid(app_id, &_pkgid) < 0) {
282                         return ES_R_ERROR;
283                 }
284         } else {
285                 _pkgid = (char *)pkg_id;
286         }
287
288         item_of_list = calloc(1, sizeof(esd_list_item_s));
289         if (item_of_list == NULL) {
290                 _E("out_of_memory");
291                 free(_pkgid);
292                 return ES_R_ENOMEM;
293         }
294         item_of_list->app_id = (char *)app_id;
295         item_of_list->pkg_id = _pkgid;
296         el_item->app_list_evtlaunch =
297                 g_list_append(el_item->app_list_evtlaunch, item_of_list);
298
299         return ES_R_OK;
300 }
301
302 static int __esd_add_launch_item(const char *event_name, const char *appid)
303 {
304         GList *app_list = NULL;
305         guint subscription_id = 0;
306         char *app_id = NULL;
307         char *pkg_id = NULL;
308         esd_list_item_s *item_of_list = NULL;
309
310         event_launch_item *el_item =
311                 (event_launch_item *)g_hash_table_lookup(event_launch_table, event_name);
312
313         if (el_item) {
314                 if (__esd_get_pkgid_by_appid(appid, &pkg_id) < 0) {
315                         return ES_R_ERROR;
316                 }
317                 item_of_list = calloc(1, sizeof(esd_list_item_s));
318                 if (item_of_list == NULL) {
319                         _E("memory alloc failed");
320                         free(pkg_id);
321                         return ES_R_ENOMEM;
322                 }
323                 item_of_list->app_id = (char *)appid;
324                 item_of_list->pkg_id = pkg_id;
325
326                 app_list = g_list_find_custom(el_item->app_list_evtlaunch,
327                                 item_of_list, (GCompareFunc)esd_find_compare_by_list_item);
328                 free(item_of_list);
329                 if (app_list == NULL) {
330                         _D("add new item (list item only)");
331                         app_id = strdup((char *)appid);
332                         if (!app_id) {
333                                 _E("out_of_memory");
334                                 free(pkg_id);
335                                 return ES_R_ENOMEM;
336                         }
337                         if (__esd_add_list_item(el_item, app_id, pkg_id) < 0) {
338                                 _E("failed to add list item");
339                                 free(app_id);
340                                 free(pkg_id);
341                                 return ES_R_ERROR;
342                         }
343                 }
344         } else {
345                 _D("add new item (all)");
346                 event_launch_item *eli = calloc(1, sizeof(event_launch_item));
347                 if (!eli) {
348                         _E("memory alloc failed");
349                         return ES_R_ENOMEM;
350                 }
351
352                 eli->event_name = strdup(event_name);
353                 if (!eli->event_name) {
354                         _E("out_of_memory");
355                         FREE_AND_NULL(eli);
356                         return ES_R_ENOMEM;
357                 }
358
359                 app_id = strdup((char *)appid);
360                 if (!app_id) {
361                         _E("out_of_memory");
362                         FREE_AND_NULL(eli->event_name);
363                         FREE_AND_NULL(eli);
364                         return ES_R_ENOMEM;
365                 }
366                 if (__esd_add_list_item(eli, app_id, NULL) < 0) {
367                         _E("failed to add list item");
368                         free(app_id);
369                         FREE_AND_NULL(eli->event_name);
370                         FREE_AND_NULL(eli);
371                         return ES_R_ERROR;
372                 }
373
374                 g_hash_table_insert(event_launch_table, eli->event_name, eli);
375
376                 eventsystem_register_event(eli->event_name, &subscription_id,
377                                         (eventsystem_handler)__esd_event_handler, NULL);
378                 if (subscription_id == 0) {
379                         _E("signal subscription error, event_name(%s), app_id(%s)",
380                                 eli->event_name, app_id);
381                         return ES_R_ERROR;
382                 } else {
383                         eli->reg_id = subscription_id;
384                 }
385         }
386
387         return ES_R_OK;
388 }
389
390 static void esd_add_launch_item(gpointer data, gpointer user_data)
391 {
392         eventsystem_info_s *eis = (eventsystem_info_s *)data;
393         char *event_name = eis->event_name;
394         eventlaunch_item_param_s *eli_p = (eventlaunch_item_param_s *)user_data;
395
396         if (__esd_add_launch_item(event_name, eli_p->app_id) < 0) {
397                 _E("failed to add item");
398         }
399 }
400
401 static void __esd_remove_app_list(gpointer data, gpointer user_data)
402 {
403         esd_list_item_s *item = (esd_list_item_s *)data;
404         event_launch_item *eli = (event_launch_item *)user_data;
405
406         if (!strcmp(eli->package_name, item->pkg_id)) {
407                 _D("pkg_id(%s), app_id(%s)", eli->package_name, item->app_id);
408                 eli->app_list_evtlaunch =
409                         g_list_remove_all(eli->app_list_evtlaunch, data);
410         }
411 }
412
413 static int esd_remove_launch_item(gpointer data, const char *pkg_id)
414 {
415         event_launch_item *eli = (event_launch_item *)data;
416         GList *first_list = NULL;
417
418         eli->package_name = (char *)pkg_id;
419         g_list_foreach(eli->app_list_evtlaunch, __esd_remove_app_list, eli);
420
421         first_list = g_list_first(eli->app_list_evtlaunch);
422         if (first_list == NULL) {
423                 if (eli->reg_id) {
424                         eventsystem_unregister_event(eli->reg_id);
425                 }
426                 return ES_R_REMOVE;
427         }
428
429         return ES_R_OK;
430 }
431
432 static int esd_launch_table_add_items(const char *app_id, GList *event_list)
433 {
434         eventlaunch_item_param_s *eli_p = NULL;
435
436         eli_p = calloc(1, sizeof(eventlaunch_item_param_s));
437         if (eli_p == NULL) {
438                 _E("memory alloc failed");
439                 return ES_R_ENOMEM;
440         }
441
442         eli_p->app_id = (char *)app_id;
443
444         _D("app_id(%s)", eli_p->app_id);
445         g_list_foreach(event_list, esd_add_launch_item, eli_p);
446
447         FREE_AND_NULL(eli_p);
448
449         return ES_R_OK;
450 }
451
452 static int esd_launch_table_remove_items(const char *pkg_id)
453 {
454         GHashTableIter iter;
455         gpointer key, value;
456
457         g_hash_table_iter_init(&iter, event_launch_table);
458
459         while (g_hash_table_iter_next(&iter, &key, &value)) {
460                 if (esd_remove_launch_item(value, pkg_id) == ES_R_REMOVE) {
461                         _D("remove item itself");
462                         g_hash_table_iter_remove(&iter);
463                 }
464         }
465
466         return ES_R_OK;
467 }
468
469 static void esd_event_launch_with_appid(gpointer data, gpointer user_data)
470 {
471         esd_list_item_s *item = (esd_list_item_s *)data;
472         char *app_id = item->app_id;
473         esd_event_param *eep = (esd_event_param *)user_data;
474         static unsigned int req_id;
475         int pid;
476
477         _D("launch_on_event: app_id(%s), event_name(%s)", app_id, eep->event_name);
478
479         if (!aul_app_is_running(app_id)) {
480                 char event_uri[1024] = {0, };
481                 snprintf(event_uri, 1024, "event://%s", eep->event_name);
482                 bundle *b = bundle_dup(eep->event_data);
483                 appsvc_set_operation(b, APPSVC_OPERATION_LAUNCH_ON_EVENT);
484                 appsvc_set_uri(b, event_uri);
485                 appsvc_set_appid(b, app_id);
486
487                 pid = appsvc_usr_run_service(b, req_id++, NULL, eep->user_data, getuid());
488                 _D("pid(%d)", pid);
489
490                 bundle_free(b);
491         } else {
492                 _D("already is running");
493         }
494 }
495
496 static void esd_check_event_launch_with_eventid(gpointer data, gpointer user_data)
497 {
498         event_launch_item *el_item = (event_launch_item *)data;
499         esd_event_param *eep = (esd_event_param *)user_data;
500
501         if (strcmp(eep->event_name, (char *)el_item->event_name) == 0) {
502                 g_list_foreach(el_item->app_list_evtlaunch,
503                         esd_event_launch_with_appid, user_data);
504         }
505 }
506
507 static void __esd_event_handler(char *event_name, bundle *data, void *user_data)
508 {
509         _D("event_name(%s)", event_name);
510
511         event_launch_item *el_item =
512                 (event_launch_item *)g_hash_table_lookup(event_launch_table, event_name);
513
514         if (el_item == NULL) {
515                 return;
516         }
517
518         if (el_item->app_list_evtlaunch != NULL) {
519                 esd_event_param *eep = calloc(1, sizeof(esd_event_param));
520                 if (!eep) {
521                         _E("memory alloc failed");
522                         return;
523                 }
524                 eep->event_name = event_name;
525                 eep->event_data = data;
526                 eep->user_data = (void *)user_data;
527                 esd_check_event_launch_with_eventid(el_item, eep);
528                 free(eep);
529         }
530 }
531
532 #ifdef APPFW_EVENT_SYSTEM_EARLIER_FEATURE
533 static void __esd_earlier_event_handler(char *event_name, bundle *data, void *user_data)
534 {
535         _D("event_name(%s)", event_name);
536
537         earlier_item *item =
538                 (earlier_item *)g_hash_table_lookup(earlier_event_table, event_name);
539
540         /* update earlier value */
541         if (item->earlier_data != NULL) {
542                 bundle_free(item->earlier_data);
543         }
544         item->earlier_data = bundle_dup(data);
545 }
546 #endif
547
548 static GDBusNodeInfo *introspection_data;
549 static const gchar introspection_xml[] =
550 "<node>"
551 "       <interface name='tizen.system.event.app2esd'>"
552 "               <method name='CheckUserCertValidation'>"
553 "                       <arg type='i' name='frompid' direction='in'/>"
554 "                       <arg type='i' name='ret' direction='out'/>"
555 "               </method>"
556 "               <method name='CheckUserSendValidation'>"
557 "                       <arg type='s' name='eventname' direction='in'/>"
558 "                       <arg type='i' name='ret' direction='out'/>"
559 "               </method>"
560 "               <method name='RequestEventLaunch'>"
561 "                       <arg type='s' name='eventname' direction='in'/>"
562 "                       <arg type='s' name='eventdata' direction='in'/>"
563 "                       <arg type='i' name='datalen' direction='in'/>"
564 "                       <arg type='i' name='ret' direction='out'/>"
565 "               </method>"
566 "               <method name='RequestSendingEvent'>"
567 "                       <arg type='s' name='eventname' direction='in'/>"
568 "                       <arg type='s' name='eventdata' direction='in'/>"
569 "                       <arg type='i' name='datalen' direction='in'/>"
570 "                       <arg type='i' name='ret' direction='out'/>"
571 "               </method>"
572 #ifdef APPFW_EVENT_SYSTEM_EARLIER_FEATURE
573 "               <method name='GetEarlierData'>"
574 "                       <arg type='s' name='appid' direction='in'/>"
575 "                       <arg type='i' name='ret' direction='out'/>"
576 "                       <arg type='i' name='len' direction='out'/>"
577 "                       <arg type='s' name='earlier_data' direction='out'/>"
578 "               </method>"
579 #endif
580 "       </interface>"
581 "</node>";
582
583 static void handle_method_call(GDBusConnection *connection,
584                 const gchar *sender, const gchar *object_path,
585                 const gchar *interface_name, const gchar *method_name,
586                 GVariant *parameters, GDBusMethodInvocation *invocation,
587                 gpointer user_data)
588 {
589         GVariant *param = NULL;
590         int result = 0;
591
592         if (g_strcmp0(method_name, "CheckUserCertValidation") == 0) {
593                 char app_id[256] = {0, };
594                 char from_appid[256] = {0, };
595                 int from_pid = 0;
596                 int sender_pid = 0;
597                 int ret = 0;
598
599                 g_variant_get(parameters, "(i)", &from_pid);
600
601                 _D("from_pid(%d)", from_pid);
602
603                 if (from_pid > 0) {
604                         ret = aul_app_get_appid_bypid(from_pid, from_appid, sizeof(from_appid));
605                         if (ret != AUL_R_OK) {
606                                 _E("failed to get appid by from_pid");
607                                 result = ES_R_ERROR;
608                                 goto out_1;
609                         }
610                 }
611
612                 sender_pid = __get_sender_pid(connection, sender);
613
614                 if (sender_pid > 0) {
615                         ret = aul_app_get_appid_bypid(sender_pid, app_id, sizeof(app_id));
616                         if (ret != AUL_R_OK) {
617                                 _E("failed to get appid by sender_pid");
618                                 result = ES_R_ERROR;
619                                 goto out_1;
620                         }
621                 } else {
622                         _E("failed to get sender_pid");
623                         goto out_1;
624                 }
625
626                 pkgmgrinfo_cert_compare_result_type_e res;
627                 ret = pkgmgrinfo_pkginfo_compare_usr_app_cert_info(app_id, from_appid,
628                                 getuid(), &res);
629                 if (ret < 0) {
630                         _E("CheckCertificate() Failed");
631                         result = ES_R_ERROR;
632                         goto out_1;
633                 }
634
635                 if (res != PMINFO_CERT_COMPARE_MATCH) {
636                         _E("CheckCertificate() Failed : ERROR_CERTIFICATE_NOT_MATCH");
637                         result = ES_R_EINVAL;
638                         goto out_1;
639                 }
640
641                 result = 1;
642                 param = g_variant_new("(i)", result);
643 out_1:
644                 _D("app_id(%s), from_appid(%s), result(%d)", app_id, from_appid, result);
645                 g_dbus_method_invocation_return_value(invocation, param);
646         } else if (g_strcmp0(method_name, "CheckUserSendValidation") == 0) {
647                 char *event_name = NULL;
648                 char app_id[256] = {0, };
649                 char valid_name[1024];
650                 char *user_defined_name = NULL;
651                 int sender_pid = 0;
652                 int ret = 0;
653                 int len = 0;
654
655                 g_variant_get(parameters, "(s)", &event_name);
656
657                 _D("event_name(%s)", event_name);
658
659                 sender_pid = __get_sender_pid(connection, sender);
660
661                 if (sender_pid > 0) {
662                         ret = aul_app_get_appid_bypid(sender_pid, app_id, sizeof(app_id));
663                         if (ret != AUL_R_OK) {
664                                 _E("failed to get appid by sender_pid");
665                                 result = ES_R_ERROR;
666                                 goto out_2;
667                         }
668                 } else {
669                         _E("failed to get sender_pid");
670                         goto out_2;
671                 }
672
673                 snprintf(valid_name, 1024, "%s%s.", USER_EVENT_NAME_PREFIX, app_id);
674                 len = strlen(valid_name);
675
676                 _D("valid_name(%s)", valid_name);
677
678                 if (strncmp(event_name, valid_name, len) != 0) {
679                         _E("appid misamatch");
680                         result = ES_R_EINVAL;
681                         goto out_2;
682                 } else {
683                         user_defined_name = strdup(&event_name[len]);
684                         len = strlen(user_defined_name);
685                         if (len < 1 || len > 127) {
686                                 _E("Invalid Length of user-defined name");
687                                 result = ES_R_EINVAL;
688                                 goto out_2;
689                         }
690                         free(user_defined_name);
691                 }
692
693                 result = 1;
694                 param = g_variant_new("(i)", result);
695 out_2:
696                 _D("event_name(%s), result(%d)", event_name, result);
697                 g_dbus_method_invocation_return_value(invocation, param);
698         } else if (g_strcmp0(method_name, "RequestEventLaunch") == 0) {
699                 char *event_name = NULL;
700                 bundle_raw *raw = NULL;
701                 bundle *b = NULL;
702                 int len = 0;
703
704                 g_variant_get(parameters, "(ssi)", &event_name, &raw, &len);
705
706                 b = bundle_decode(raw, len);
707                 __esd_event_handler(event_name, b, NULL);
708                 bundle_free(b);
709
710                 result = 1;
711                 param = g_variant_new("(i)", result);
712
713                 _D("event_name(%s), result(%d)", event_name, result);
714                 g_dbus_method_invocation_return_value(invocation, param);
715         } else if (g_strcmp0(method_name, "RequestSendingEvent") == 0) {
716                 char *event_name = NULL;
717                 bundle_raw *raw = NULL;
718                 bundle *b = NULL;
719                 int len = 0;
720
721                 g_variant_get(parameters, "(ssi)", &event_name, &raw, &len);
722
723                 b = bundle_decode(raw, len);
724                 eventsystem_send_system_event(event_name, b);
725                 bundle_free(b);
726
727                 result = 1;
728                 param = g_variant_new("(i)", result);
729
730                 _D("event_name(%s), result(%d)", event_name, result);
731                 g_dbus_method_invocation_return_value(invocation, param);
732 #ifdef APPFW_EVENT_SYSTEM_EARLIER_FEATURE
733         } else if (g_strcmp0(method_name, "GetEarlierData") == 0) {
734                 char *event_name = NULL;
735                 bundle *b = NULL;
736                 bundle_raw *raw = NULL;
737                 int len = 0;
738
739                 g_variant_get(parameters, "(s)", &event_name);
740
741                 if (event_name && strlen(event_name) > 0) {
742                         _D("event_name(%s)", event_name);
743                         result = ES_R_OK;
744                 } else {
745                         _E("invalid appid(%s)", event_name);
746                         result = ES_R_ERROR;
747                 }
748
749                 earlier_item *item =
750                         (earlier_item *)g_hash_table_lookup(earlier_event_table, event_name);
751
752                 if (item != NULL) {
753                         if (item->earlier_data) {
754                                 b = bundle_dup(item->earlier_data);
755                                 bundle_add_str(b, "is_earlier_data", "true");
756                                 bundle_encode(b, &raw, &len);
757                                 bundle_free(b);
758                         }
759                 }
760
761                 param = g_variant_new("(iis)", result, len, raw);
762
763                 _D("result(%d), len(%d)", result, len);
764                 g_dbus_method_invocation_return_value(invocation, param);
765
766                 bundle_free_encoded_rawdata(&raw);
767 #endif
768         }
769 }
770
771 static const GDBusInterfaceVTable interface_vtable = {
772         handle_method_call,
773         NULL,
774         NULL
775 };
776
777 static void on_bus_acquired(GDBusConnection *connection,
778                 const gchar *name, gpointer user_data)
779 {
780         _D("on_bus_acquired(%s)", name);
781
782         guint reg_id = 0;
783         GError *error = NULL;
784
785         reg_id = g_dbus_connection_register_object(connection,
786                 ESD_OBJECT_PATH,
787                 introspection_data->interfaces[0],
788                 &interface_vtable,
789                 NULL, NULL, &error);
790         if (reg_id == 0) {
791                 _E("g_dbus_connection_register_object error(%s)", error->message);
792                 g_error_free (error);
793         }
794 }
795
796 static void on_name_acquired(GDBusConnection *connection,
797                 const gchar *name, gpointer user_data)
798 {
799         _D("on_name_acquired(%s)", name);
800
801         bundle *b = bundle_create();
802         bundle_add_str(b, EVT_KEY_ESD_STATUS, EVT_VAL_ESD_STARTED);
803         eventsystem_send_system_event(SYS_EVENT_ESD_STATUS, b);
804         bundle_free(b);
805 }
806
807 static void on_name_lost(GDBusConnection *connection,
808                 const gchar *name, gpointer user_data)
809 {
810         _D("on_name_lost(%s)", name);
811 }
812
813 static int __esd_before_loop(void)
814 {
815         GList *es_info = NULL;
816         GList *tmp_es_info = NULL;
817         int ret = 0;
818
819 #ifdef APPFW_EVENT_SYSTEM_EARLIER_FEATURE
820         guint subscription_id = 0;
821         int i, size;
822
823         earlier_event_table = g_hash_table_new(g_str_hash, g_str_equal);
824
825         _I("register events for earlier_data");
826         size = sizeof(earlier_event_list)/sizeof(*earlier_event_list);
827         for (i = 0; i < size; i++) {
828                 char *event_name = NULL;
829                 event_name = (char *)earlier_event_list[i];
830                 _I("event_name(%s)", event_name);
831
832                 earlier_item *item = calloc(1, sizeof(earlier_item));
833                 item->event_name = strdup(event_name);
834                 if (item->event_name == NULL) {
835                         _E("out of memory");
836                         return ES_R_ERROR;
837                 }
838                 g_hash_table_insert(earlier_event_table, event_name, item);
839
840                 eventsystem_register_event(item->event_name, &subscription_id,
841                                         (eventsystem_handler)__esd_earlier_event_handler, NULL);
842                 if (subscription_id == 0) {
843                         _E("signal subscription error, event_name(%s)", item->event_name);
844                         return ES_R_ERROR;
845                 } else {
846                         item->reg_id = subscription_id;
847                 }
848         }
849 #endif
850
851         event_launch_table = g_hash_table_new(g_str_hash, g_str_equal);
852
853         _I("get event launch list");
854         pkgmgrinfo_appinfo_get_usr_event_launch_list(&es_info, getuid());
855         if (es_info) {
856                 tmp_es_info = g_list_first(es_info);
857
858                 while (tmp_es_info != NULL) {
859                         eventsystem_info_s *esi = (eventsystem_info_s *)tmp_es_info->data;
860                         _I("appid(%s)-eventname(%s)", esi->appid, esi->event_name);
861
862                         if (!__esd_is_service_app(esi->appid)) {
863                                 _E("not service app");
864                         } else {
865                                 if (__esd_add_launch_item(esi->event_name, esi->appid) < 0) {
866                                         _E("failed to add item");
867                                         ret = ES_R_ERROR;
868                                         break;
869                                 }
870                         }
871
872                         tmp_es_info = g_list_next(tmp_es_info);
873                 }
874
875                 g_list_free_full(es_info, __esd_free_noti);
876                 esd_launch_table_print_items();
877
878                 if (ret < 0) {
879                         return ret;
880                 }
881         } else {
882                 _D("event list is null");
883         }
884
885         /* gdbus setup for method call */
886         GError *error = NULL;
887         guint owner_id = 0;
888         introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, &error);
889         if (!introspection_data) {
890                 _E("g_dbus_node_info_new_for_xml error(%s)", error->message);
891                 g_error_free (error);
892                 return ES_R_ERROR;
893         }
894
895         owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
896                 ESD_BUS_NAME,
897                 G_BUS_NAME_OWNER_FLAGS_NONE,
898                 on_bus_acquired,
899                 on_name_acquired,
900                 on_name_lost,
901                 NULL, NULL);
902         if (!owner_id) {
903                 _E("g_bus_own_name error");
904                 g_dbus_node_info_unref(introspection_data);
905                 return ES_R_ERROR;
906         }
907
908         return ES_R_OK;
909 }
910
911 static void esd_pkgmgr_event_free(esd_pkgmgr_event *pkg_event)
912 {
913         pkg_event->type = UNKNOWN;
914         if (pkg_event->pkgid) {
915                 free(pkg_event->pkgid);
916                 pkg_event->pkgid = NULL;
917         }
918 }
919
920 static int __esd_add_appinfo_handler(const pkgmgrinfo_appinfo_h handle, void *data)
921 {
922         char *appid = NULL;
923         GList *event_list = NULL;
924         int ret = 0;
925
926         ret = pkgmgrinfo_appinfo_get_appid(handle, &appid);
927         if (ret < 0) {
928                 _E("fail to get appinfo");
929                 return ES_R_ERROR;
930         }
931
932         _D("appid(%s)", appid);
933
934         if (!__esd_is_service_app(appid)) {
935                 _E("not service app");
936                 return ES_R_OK;
937         }
938
939         pkgmgrinfo_appinfo_get_usr_event_launch_list_by_appid(appid, &event_list, getuid());
940         if (event_list) {
941                 esd_print_event_list_of_app(event_list);
942                 esd_launch_table_add_items(appid, event_list);
943                 esd_launch_table_print_items();
944                 g_list_free_full(event_list, __esd_free_noti);
945         } else {
946                 _D("event_list is NULL");
947         }
948
949         return ES_R_OK;
950 }
951
952 static int esd_pkgmgr_event_callback(int req_id, const char *pkg_type,
953                 const char *pkgid, const char *key, const char *val,
954                 const void *pmsg, void *data)
955 {
956         esd_pkgmgr_event *pkg_event = (esd_pkgmgr_event *)data;
957         pkgmgrinfo_pkginfo_h handle = NULL;
958         int ret = 0;
959
960         _D("req_id(%d), pkg_type(%s), pkgid(%s), key(%s), val(%s)",
961                 req_id, pkg_type, pkgid, key, val);
962
963         if (strncmp(key, "start", strlen(key)) == 0) {
964                 if (strcmp(val, "install") == 0) {
965                         _D("install start");
966                         pkg_event->type = INSTALL;
967                 } else if (strcmp(val, "uninstall") == 0) {
968                         _D("unistall start");
969                         pkg_event->type = UNINSTALL;
970                 } else if (strcmp(val, "update") == 0) {
971                         _D("update start");
972                         pkg_event->type = UPDATE;
973                 } else {
974                         _D("val(%s) start", val);
975                         esd_pkgmgr_event_free(pkg_event);
976                 }
977         } else if (strcmp(key, "end") == 0 && strcmp(val, "ok") == 0) {
978                 if (pkg_event->type == INSTALL || pkg_event->type == UPDATE) {
979                         _D("install end (ok)");
980                         ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgid, &handle, getuid());
981                         if (ret < 0) {
982                                 _E("failed to get pkginfo");
983                                 esd_pkgmgr_event_free(pkg_event);
984                                 return 0;
985                         }
986                         ret = pkgmgrinfo_appinfo_get_list(handle,
987                                 PMINFO_ALL_APP, __esd_add_appinfo_handler, NULL);
988                         if (ret < 0) {
989                                 _E("failed to get appinfo");
990                                 esd_pkgmgr_event_free(pkg_event);
991                                 return 0;
992                         }
993                         ret = pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
994                         if (ret < 0) {
995                                 _E("failed to destroy pkginfo");
996                                 esd_pkgmgr_event_free(pkg_event);
997                                 return 0;
998                         }
999                 } else if (pkg_event->type == UNINSTALL) {
1000                         _D("uninstall end (ok)");
1001                         esd_launch_table_remove_items(pkgid);
1002                         esd_launch_table_print_items();
1003                 }
1004                 esd_pkgmgr_event_free(pkg_event);
1005         } else if (strcmp(key, "end") == 0 && strcmp(val, "fail") == 0) {
1006                 _E("pkg_event(%d) falied", pkg_event->type);
1007                 esd_pkgmgr_event_free(pkg_event);
1008         } else {
1009                 if (strcmp(key, "install_percent") != 0) {
1010                         esd_pkgmgr_event_free(pkg_event);
1011                 }
1012         }
1013
1014         return 0;
1015 }
1016
1017 static int __esd_init()
1018 {
1019         int req_id = 0;
1020         int ret = 0;
1021
1022         g_type_init();
1023         ecore_init();
1024
1025         pkgmgr_client *client = pkgmgr_client_new(PC_LISTENING);
1026         if (client == NULL) {
1027                 _E("set pkgmgr client failed");
1028                 return ES_R_ERROR;
1029         }
1030
1031         esd_pkgmgr_event *pkg_event = calloc(1, sizeof(esd_pkgmgr_event));
1032         if (pkg_event == NULL) {
1033                 _E("memory alloc failed");
1034                 ret = pkgmgr_client_free(client);
1035                 if (ret != PKGMGR_R_OK) {
1036                         _E("pkgmgr_client_free failed(%d)", ret);
1037                 }
1038                 return ES_R_ENOMEM;
1039         }
1040
1041         req_id = pkgmgr_client_listen_status(client, esd_pkgmgr_event_callback, pkg_event);
1042         if (req_id < 0) {
1043                 _E("pkgmgr client listen failed");
1044                 ret = pkgmgr_client_free(client);
1045                 if (ret != PKGMGR_R_OK) {
1046                         _E("pkgmgr_client_free failed(%d)", ret);
1047                 }
1048                 return ES_R_ERROR;
1049         }
1050
1051         s_info.client = client;
1052
1053         _D("ESD init done\n");
1054
1055         return 0;
1056 }
1057
1058 static void esd_remove_app_list(gpointer data, gpointer user_data)
1059 {
1060         esd_list_item_s *item = (esd_list_item_s *)data;
1061
1062         free(item->app_id);
1063         free(item->pkg_id);
1064 }
1065
1066 static void esd_finalize(void)
1067 {
1068         gpointer key, value;
1069         int ret = 0;
1070
1071         _D("esd finalize");
1072
1073 #ifdef APPFW_EVENT_SYSTEM_EARLIER_FEATURE
1074         if (earlier_event_table) {
1075                 GHashTableIter iter;
1076
1077                 g_hash_table_iter_init(&iter, earlier_event_table);
1078
1079                 while (g_hash_table_iter_next(&iter, &key, &value)) {
1080                         earlier_item *item = (earlier_item *)value;
1081                         if (item) {
1082                                 eventsystem_unregister_event(item->reg_id);
1083                                 free(item->event_name);
1084                                 bundle_free(item->earlier_data);
1085                                 free(item);
1086                         } else {
1087                                 LOGE("item is NULL");
1088                         }
1089                         g_hash_table_iter_remove(&iter);
1090                 }
1091                 g_hash_table_unref(earlier_event_table);
1092         }
1093 #endif
1094
1095         if (event_launch_table) {
1096                 GHashTableIter iter;
1097
1098                 g_hash_table_iter_init(&iter, event_launch_table);
1099
1100                 while (g_hash_table_iter_next(&iter, &key, &value)) {
1101                         event_launch_item *el_item = (event_launch_item *)value;
1102                         if (el_item) {
1103                                 eventsystem_unregister_event(el_item->reg_id);
1104                                 free(el_item->event_name);
1105                                 g_list_foreach(el_item->app_list_evtlaunch,
1106                                         esd_remove_app_list, NULL);
1107                                 g_list_free(el_item->app_list_evtlaunch);
1108                                 free(el_item);
1109                         } else {
1110                                 LOGE("item is NULL");
1111                         }
1112                         g_hash_table_iter_remove(&iter);
1113                 }
1114                 g_hash_table_unref(event_launch_table);
1115         }
1116
1117         if (introspection_data) {
1118                 g_dbus_node_info_unref(introspection_data);
1119         }
1120
1121         if (s_info.client) {
1122                 ret = pkgmgr_client_free(s_info.client);
1123                 if (ret != PKGMGR_R_OK) {
1124                         _E("pkgmgr_client_free failed(%d)", ret);
1125                 }
1126         }
1127 }
1128
1129 int main(int argc, char *argv[])
1130 {
1131         _D("event system daemon : main()\n");
1132
1133         if (__esd_init() != 0) {
1134                 _E("ESD Initialization failed!\n");
1135                 assert(0);
1136                 return ES_R_ERROR;
1137         }
1138
1139         if (__esd_before_loop() < 0) {
1140                 _E("ESD failed!\n");
1141                 esd_finalize();
1142                 assert(0);
1143                 return ES_R_ERROR;
1144         }
1145
1146         ecore_main_loop_begin();
1147
1148         _E("shutdown");
1149
1150         esd_finalize();
1151
1152         ecore_shutdown();
1153
1154         return 0;
1155 }