Merge tizen 2.4 into tizen
[platform/core/appfw/app-core.git] / src / appcore.c
1 /*
2  *  app-core
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22
23 #define _GNU_SOURCE
24
25 #include <errno.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <sys/types.h>
29 #include <unistd.h>
30 #include <malloc.h>
31 #include <locale.h>
32 #include <linux/limits.h>
33 #include <glib.h>
34 #include <sys/time.h>
35 #include <dlfcn.h>
36 #include <vconf.h>
37 #include <aul.h>
38 #include <tzplatform_config.h>
39 #include "appcore-internal.h"
40
41 #ifdef _APPFW_FEATURE_BACKGROUND_MANAGEMENT
42 #include <dbus/dbus.h>
43 #include <dbus/dbus-glib-lowlevel.h>
44
45 #define RESOURCED_FREEZER_PATH "/Org/Tizen/Resourced/Freezer"
46 #define RESOURCED_FREEZER_INTERFACE "org.tizen.resourced.freezer"
47 #define RESOURCED_FREEZER_SIGNAL "FreezerState"
48 #endif
49
50 #define SQLITE_FLUSH_MAX                (1024*1024)
51
52 #define PKGNAME_MAX 256
53 #define PATH_APP_ROOT tzplatform_getenv(TZ_USER_APP)
54 #define PATH_RO_APP_ROOT tzplatform_getenv(TZ_SYS_RO_APP)
55 #define PATH_RES "/res"
56 #define PATH_LOCALE "/locale"
57
58 static struct appcore core;
59 static pid_t _pid;
60
61 static enum appcore_event to_ae[SE_MAX] = {
62         APPCORE_EVENT_UNKNOWN,  /* SE_UNKNOWN */
63         APPCORE_EVENT_LOW_MEMORY,       /* SE_LOWMEM */
64         APPCORE_EVENT_LOW_BATTERY,      /* SE_LOWBAT */
65         APPCORE_EVENT_LANG_CHANGE,      /* SE_LANGCGH */
66         APPCORE_EVENT_REGION_CHANGE,
67 };
68
69
70 enum cb_type {                  /* callback */
71         _CB_NONE,
72         _CB_SYSNOTI,
73         _CB_APPNOTI,
74         _CB_VCONF,
75 };
76
77 struct evt_ops {
78         enum cb_type type;
79         union {
80                 enum appcore_event sys;
81                 enum app_event app;
82                 const char *vkey;
83         } key;
84
85         int (*cb_pre) (void *);
86         int (*cb) (void *);
87         int (*cb_post) (void *);
88
89         int (*vcb_pre) (void *, void *);
90         int (*vcb) (void *, void *);
91         int (*vcb_post) (void *, void *);
92 };
93
94 struct open_s {
95         int (*callback) (void *);
96         void *cbdata;
97 };
98
99 static struct open_s open;
100
101 static int __app_terminate(void *data);
102 static int __app_resume(void *data);
103 static int __app_reset(void *data, bundle *k);
104
105 static int __sys_lowmem_post(void *data, void *evt);
106 static int __sys_lowmem(void *data, void *evt);
107 static int __sys_lowbatt(void *data, void *evt);
108 static int __sys_langchg_pre(void *data, void *evt);
109 static int __sys_langchg(void *data, void *evt);
110 static int __sys_regionchg_pre(void *data, void *evt);
111 static int __sys_regionchg(void *data, void *evt);
112 extern void aul_finalize();
113
114
115 static struct evt_ops evtops[] = {
116         {
117          .type = _CB_VCONF,
118          .key.vkey = VCONFKEY_SYSMAN_LOW_MEMORY,
119          .vcb_post = __sys_lowmem_post,
120          .vcb = __sys_lowmem,
121          },
122         {
123          .type = _CB_VCONF,
124          .key.vkey = VCONFKEY_SYSMAN_BATTERY_STATUS_LOW,
125          .vcb = __sys_lowbatt,
126          },
127         {
128          .type = _CB_VCONF,
129          .key.vkey = VCONFKEY_LANGSET,
130          .vcb_pre = __sys_langchg_pre,
131          .vcb = __sys_langchg,
132          },
133         {
134          .type = _CB_VCONF,
135          .key.vkey = VCONFKEY_REGIONFORMAT,
136          .vcb_pre = __sys_regionchg_pre,
137          .vcb = __sys_regionchg,
138          },
139         {
140          .type = _CB_VCONF,
141          .key.vkey = VCONFKEY_REGIONFORMAT_TIME1224,
142          .vcb = __sys_regionchg,
143          },
144 };
145
146 #ifdef _APPFW_FEATURE_BACKGROUND_MANAGEMENT
147 static DBusConnection *bus = NULL;
148 static int __suspend_dbus_handler_initialized = 0;
149 #endif
150
151 static int __get_dir_name(char *dirname)
152 {
153         char pkg_name[PKGNAME_MAX];
154         int r;
155         int pid;
156
157         pid = getpid();
158         if (pid < 0)
159                 return -1;
160
161         if (aul_app_get_pkgname_bypid(pid, pkg_name, PKGNAME_MAX) != AUL_R_OK)
162                 return -1;
163
164         r = snprintf(dirname, PATH_MAX, "%s/%s" PATH_RES PATH_LOCALE,
165                         PATH_APP_ROOT, pkg_name);
166         if (r < 0)
167                 return -1;
168         if (access(dirname, R_OK) == 0) return 0;
169         r = snprintf(dirname, PATH_MAX, "%s/%s" PATH_RES PATH_LOCALE,
170                         PATH_RO_APP_ROOT, pkg_name);
171         if (r < 0)
172                 return -1;
173
174         return 0;
175 }
176
177 static int __app_terminate(void *data)
178 {
179         struct appcore *ac = data;
180
181         _retv_if(ac == NULL || ac->ops == NULL, -1);
182         _retv_if(ac->ops->cb_app == NULL, 0);
183
184         ac->ops->cb_app(AE_TERMINATE, ac->ops->data, NULL);
185
186         return 0;
187 }
188
189 static int __bgapp_terminate(void *data)
190 {
191         struct appcore *ac = data;
192
193         _retv_if(ac == NULL || ac->ops == NULL, -1);
194         _retv_if(ac->ops->cb_app == NULL, 0);
195
196         ac->ops->cb_app(AE_TERMINATE_BGAPP, ac->ops->data, NULL);
197
198         return 0;
199 }
200
201 static gboolean __prt_ltime(gpointer data)
202 {
203         int msec;
204
205         msec = appcore_measure_time_from(NULL);
206         if (msec)
207                 _DBG("[APP %d] first idle after reset: %d msec", _pid, msec);
208
209         return FALSE;
210 }
211
212 static int __app_reset(void *data, bundle * k)
213 {
214         struct appcore *ac = data;
215         _retv_if(ac == NULL || ac->ops == NULL, -1);
216         _retv_if(ac->ops->cb_app == NULL, 0);
217
218         g_idle_add(__prt_ltime, ac);
219
220         ac->ops->cb_app(AE_RESET, ac->ops->data, k);
221
222         return 0;
223 }
224
225 static int __app_resume(void *data)
226 {
227         struct appcore *ac = data;
228         _retv_if(ac == NULL || ac->ops == NULL, -1);
229         _retv_if(ac->ops->cb_app == NULL, 0);
230
231         ac->ops->cb_app(AE_RAISE, ac->ops->data, NULL);
232         return 0;
233 }
234
235 static int __app_pause(void *data)
236 {
237         struct appcore *ac = data;
238         _retv_if(ac == NULL || ac->ops == NULL, -1);
239         _retv_if(ac->ops->cb_app == NULL, 0);
240
241         ac->ops->cb_app(AE_LOWER, ac->ops->data, NULL);
242         return 0;
243 }
244
245 static int __sys_do_default(struct appcore *ac, enum sys_event event)
246 {
247         int r;
248
249         switch (event) {
250         case SE_LOWBAT:
251                 /*r = __def_lowbatt(ac);*/
252                 r = 0;
253                 break;
254         default:
255                 r = 0;
256                 break;
257         };
258
259         return r;
260 }
261
262 static int __sys_do(struct appcore *ac, void *event_info, enum sys_event event)
263 {
264         struct sys_op *op;
265
266         _retv_if(ac == NULL || event >= SE_MAX, -1);
267
268         op = &ac->sops[event];
269
270         if (op->func == NULL)
271                 return __sys_do_default(ac, event);
272
273         return op->func(event_info, op->data);
274 }
275
276 static int __sys_lowmem_post(void *data, void *evt)
277 {
278         keynode_t *key = evt;
279         int val;
280
281         val = vconf_keynode_get_int(key);
282
283         if (val >= VCONFKEY_SYSMAN_LOW_MEMORY_SOFT_WARNING)     {
284 #if defined(MEMORY_FLUSH_ACTIVATE)
285                 struct appcore *ac = data;
286                 ac->ops->cb_app(AE_LOWMEM_POST, ac->ops->data, NULL);
287 #else
288                 malloc_trim(0);
289 #endif
290         }
291         return 0;
292 }
293
294 static int __sys_lowmem(void *data, void *evt)
295 {
296         keynode_t *key = evt;
297         int val;
298
299         val = vconf_keynode_get_int(key);
300
301         if (val >= VCONFKEY_SYSMAN_LOW_MEMORY_SOFT_WARNING)
302                 return __sys_do(data, (void *)&val, SE_LOWMEM);
303
304         return 0;
305 }
306
307 static int __sys_lowbatt(void *data, void *evt)
308 {
309         keynode_t *key = evt;
310         int val;
311
312         val = vconf_keynode_get_int(key);
313
314         /* VCONFKEY_SYSMAN_BAT_CRITICAL_LOW or VCONFKEY_SYSMAN_POWER_OFF */
315         if (val <= VCONFKEY_SYSMAN_BAT_CRITICAL_LOW)
316                 return __sys_do(data, (void *)&val, SE_LOWBAT);
317
318         return 0;
319 }
320
321 static int __sys_langchg_pre(void *data, void *evt)
322 {
323         update_lang();
324         return 0;
325 }
326
327 static int __sys_langchg(void *data, void *evt)
328 {
329         keynode_t *key = evt;
330         char *val;
331
332         val = vconf_keynode_get_str(key);
333
334         return __sys_do(data, (void *)val, SE_LANGCHG);
335 }
336
337 static int __sys_regionchg_pre(void *data, void *evt)
338 {
339         update_region();
340         return 0;
341 }
342
343 static int __sys_regionchg(void *data, void *evt)
344 {
345         keynode_t *key = evt;
346         char *val = NULL;
347         const char *name;
348
349         name = vconf_keynode_get_name(key);
350         if (!strcmp(name, VCONFKEY_REGIONFORMAT))
351                 val = vconf_keynode_get_str(key);
352
353         return __sys_do(data, (void *)val, SE_REGIONCHG);
354 }
355
356 static void __vconf_do(struct evt_ops *eo, keynode_t * key, void *data)
357 {
358         _ret_if(eo == NULL);
359
360         if (eo->vcb_pre)
361                 eo->vcb_pre(data, key);
362
363         if (eo->vcb)
364                 eo->vcb(data, key);
365
366         if (eo->vcb_post)
367                 eo->vcb_post(data, key);
368 }
369
370 static void __vconf_cb(keynode_t *key, void *data)
371 {
372         int i;
373         const char *name;
374
375         name = vconf_keynode_get_name(key);
376         _ret_if(name == NULL);
377
378         _DBG("[APP %d] vconf changed: %s", _pid, name);
379
380         for (i = 0; i < sizeof(evtops) / sizeof(evtops[0]); i++) {
381                 struct evt_ops *eo = &evtops[i];
382
383                 switch (eo->type) {
384                 case _CB_VCONF:
385                         if (!strcmp(name, eo->key.vkey))
386                                 __vconf_do(eo, key, data);
387                         break;
388                 default:
389                         /* do nothing */
390                         break;
391                 }
392         }
393 }
394
395 static int __add_vconf(struct appcore *ac)
396 {
397         int i;
398         int r;
399
400         for (i = 0; i < sizeof(evtops) / sizeof(evtops[0]); i++) {
401                 struct evt_ops *eo = &evtops[i];
402
403                 switch (eo->type) {
404                 case _CB_VCONF:
405                         r = vconf_notify_key_changed(eo->key.vkey, __vconf_cb,
406                                                      ac);
407                         break;
408                 default:
409                         /* do nothing */
410                         break;
411                 }
412         }
413
414         return 0;
415 }
416
417 static int __del_vconf(void)
418 {
419         int i;
420         int r;
421
422         for (i = 0; i < sizeof(evtops) / sizeof(evtops[0]); i++) {
423                 struct evt_ops *eo = &evtops[i];
424
425                 switch (eo->type) {
426                 case _CB_VCONF:
427                         r = vconf_ignore_key_changed(eo->key.vkey, __vconf_cb);
428                         break;
429                 default:
430                         /* do nothing */
431                         break;
432                 }
433         }
434
435         return 0;
436 }
437
438 #ifdef _APPFW_FEATURE_BACKGROUND_MANAGEMENT
439 static gboolean __flush_memory(gpointer data)
440 {
441         int suspend = APPCORE_SUSPENDED_STATE_WILL_ENTER_SUSPEND;
442         struct appcore *ac = (struct appcore *)data;
443
444         appcore_flush_memory();
445
446         if (!ac) {
447                 return FALSE;
448         }
449         ac->tid = 0;
450
451         if (!ac->allowed_bg && !ac->suspended_state) {
452                 _DBG("[__SUSPEND__] flush case");
453                 __sys_do(ac, &suspend, SE_SUSPENDED_STATE);
454                 ac->suspended_state = true;
455         }
456
457         return FALSE;
458 }
459
460 static void __add_suspend_timer(struct appcore *ac)
461 {
462         ac->tid = g_timeout_add_seconds(5, __flush_memory, ac);
463 }
464
465 static void __remove_suspend_timer(struct appcore *ac)
466 {
467         if (ac->tid > 0) {
468                 g_source_remove(ac->tid);
469                 ac->tid = 0;
470         }
471 }
472 #endif
473
474 static int __aul_handler(aul_type type, bundle *b, void *data)
475 {
476         int ret;
477 #ifdef _APPFW_FEATURE_BACKGROUND_MANAGEMENT
478         const char *bg = NULL;
479         struct appcore *ac = data;
480 #endif
481
482         switch (type) {
483         case AUL_START:
484                 _DBG("[APP %d]     AUL event: AUL_START", _pid);
485 #ifdef _APPFW_FEATURE_BACKGROUND_MANAGEMENT
486                 bg = bundle_get_val(b, AUL_K_ALLOWED_BG);
487                 if (bg && strncmp(bg, "ALLOWED_BG", strlen("ALLOWGED_BG")) == 0) {
488                         _DBG("[__SUSPEND__] allowed background");
489                         ac->allowed_bg = true;
490                         __remove_suspend_timer(data);
491                 }
492 #endif
493
494                 __app_reset(data, b);
495                 break;
496         case AUL_RESUME:
497                 _DBG("[APP %d]     AUL event: AUL_RESUME", _pid);
498 #ifdef _APPFW_FEATURE_BACKGROUND_MANAGEMENT
499                 bg = bundle_get_val(b, AUL_K_ALLOWED_BG);
500                 if (bg && strncmp(bg, "ALLOWED_BG", strlen("ALLOWED_BG")) == 0) {
501                         _DBG("[__SUSPEND__] allowed background");
502                         ac->allowed_bg = true;
503                         __remove_suspend_timer(data);
504                 }
505 #endif
506
507                 if (open.callback) {
508                         ret = open.callback(open.cbdata);
509                         if (ret == 0)
510                                 __app_resume(data);
511                 } else {
512                         __app_resume(data);
513                 }
514                 break;
515         case AUL_TERMINATE:
516                 _DBG("[APP %d]     AUL event: AUL_TERMINATE", _pid);
517 #ifdef _APPFW_FEATURE_BACKGROUND_MANAGEMENT
518                 if (!ac->allowed_bg)
519                         __remove_suspend_timer(data);
520 #endif
521
522                 __app_terminate(data);
523                 break;
524         case AUL_TERMINATE_BGAPP:
525                 _DBG("[APP %d]     AUL event: AUL_TERMINATE_BGAPP", _pid);
526 #ifdef _APPFW_FEATURE_BACKGROUND_MANAGEMENT
527                 if (!ac->allowed_bg)
528                         __remove_suspend_timer(data);
529 #endif
530
531                 __bgapp_terminate(data);
532                 break;
533         case AUL_PAUSE:
534                 _DBG("[APP %d]     AUL event: AUL_PAUSE", _pid);
535                 __app_pause(data);
536                 break;
537 #ifdef _APPFW_FEATURE_BACKGROUND_MANAGEMENT
538         case AUL_WAKE:
539                 _DBG("[APP %d]     AUL event: AUL_WAKE", _pid);
540                 if (!ac->allowed_bg && ac->suspended_state) {
541                         int suspend = APPCORE_SUSPENDED_STATE_DID_EXIT_FROM_SUSPEND;
542                         __remove_suspend_timer(data);
543                         __sys_do(ac, &suspend, SE_SUSPENDED_STATE);
544                         ac->suspended_state = false;
545                 }
546                 break;
547         case AUL_SUSPEND:
548                 _DBG("[APP %d]     AUL event: AUL_SUSPEND", _pid);
549                 if (!ac->allowed_bg && !ac->suspended_state) {
550                         __remove_suspend_timer(data);
551                         __flush_memory((gpointer)ac);
552                 }
553                 break;
554 #endif
555         default:
556                 _DBG("[APP %d]     AUL event: %d", _pid, type);
557                 /* do nothing */
558                 break;
559         }
560
561         return 0;
562 }
563
564
565 static void __clear(struct appcore *ac)
566 {
567         memset(ac, 0, sizeof(struct appcore));
568 }
569
570 void appcore_get_app_core(struct appcore **ac)
571 {
572         *ac = &core;
573 }
574
575 EXPORT_API int appcore_set_open_cb(int (*cb) (void *),
576                                        void *data)
577 {
578         open.callback = cb;
579         open.cbdata = data;
580
581         return 0;
582 }
583
584 EXPORT_API int appcore_set_event_callback(enum appcore_event event,
585                                           int (*cb) (void *, void *), void *data)
586 {
587         struct appcore *ac = &core;
588         struct sys_op *op;
589         enum sys_event se;
590
591         for (se = SE_UNKNOWN; se < SE_MAX; se++) {
592                 if (event == to_ae[se])
593                         break;
594         }
595
596         if (se == SE_UNKNOWN || se >= SE_MAX) {
597                 _ERR("Unregistered event");
598                 errno = EINVAL;
599                 return -1;
600         }
601
602         op = &ac->sops[se];
603
604         op->func = cb;
605         op->data = data;
606
607         return 0;
608 }
609
610
611
612 EXPORT_API int appcore_init(const char *name, const struct ui_ops *ops,
613                             int argc, char **argv)
614 {
615         int r;
616         char dirname[PATH_MAX];
617
618         if (core.state != 0) {
619                 _ERR("Already in use");
620                 errno = EALREADY;
621                 return -1;
622         }
623
624         if (ops == NULL || ops->cb_app == NULL) {
625                 _ERR("ops or callback function is null");
626                 errno = EINVAL;
627                 return -1;
628         }
629
630         r = __get_dir_name(dirname);
631         r = set_i18n(name, dirname);
632         _retv_if(r == -1, -1);
633
634 #ifdef _APPFW_FEATURE_BACKGROUND_MANAGEMENT
635         r = _appcore_init_suspend_dbus_handler(&core);
636         if (r == -1) {
637                 _ERR("Initailzing suspended state handler failed");
638                 goto err;
639         }
640 #endif
641
642         r = __add_vconf(&core);
643         if (r == -1) {
644                 _ERR("Add vconf callback failed");
645                 goto err;
646         }
647
648         r = aul_launch_init(__aul_handler, &core);
649         if (r < 0) {
650                 _ERR("Aul init failed: %d", r);
651                 goto err;
652         }
653
654         r = aul_launch_argv_handler(argc, argv);
655         if (r < 0) {
656                 _ERR("Aul argv handler failed: %d", r);
657                 goto err;
658         }
659
660         core.ops = ops;
661         core.state = 1;         /* TODO: use enum value */
662         core.tid = 0;
663         core.suspended_state = false;
664         core.allowed_bg = false;
665
666         _pid = getpid();
667
668         return 0;
669  err:
670         __del_vconf();
671         __clear(&core);
672         return -1;
673 }
674
675 EXPORT_API void appcore_exit(void)
676 {
677         if (core.state) {
678                 __del_vconf();
679                 __clear(&core);
680 #ifdef _APPFW_FEATURE_BACKGROUND_MANAGEMENT
681                 __remove_suspend_timer(&core);
682 #endif
683         }
684         aul_finalize();
685 }
686
687 EXPORT_API int appcore_flush_memory(void)
688 {
689         int (*flush_fn) (int);
690         int size = 0;
691
692         struct appcore *ac = &core;
693
694         if (!core.state) {
695                 _ERR("Appcore not initialized");
696                 return -1;
697         }
698
699         _DBG("[APP %d] Flushing memory ...", _pid);
700
701         if (ac->ops->cb_app) {
702                 ac->ops->cb_app(AE_MEM_FLUSH, ac->ops->data, NULL);
703         }
704
705         flush_fn = dlsym(RTLD_DEFAULT, "sqlite3_release_memory");
706         if (flush_fn) {
707                 size = flush_fn(SQLITE_FLUSH_MAX);
708         }
709
710         malloc_trim(0);
711         /*
712         *Disabled - the impact of stack_trim() is unclear
713         *stack_trim();
714         */
715
716         _DBG("[APP %d] Flushing memory DONE", _pid);
717
718         return 0;
719 }
720
721 #ifdef _APPFW_FEATURE_BACKGROUND_MANAGEMENT
722 static DBusHandlerResult __suspend_dbus_signal_filter(DBusConnection *conn,
723                                         DBusMessage *message, void *user_data)
724 {
725         const char *sender;
726         const char *interface;
727         int pid;
728         int state;
729         int suspend;
730
731         DBusError error;
732         dbus_error_init(&error);
733
734         sender = dbus_message_get_sender(message);
735         if (sender == NULL)
736                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
737
738         interface = dbus_message_get_interface(message);
739         if (interface == NULL) {
740                 _ERR("reject by security issue - no interface\n");
741                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
742         }
743
744         if (dbus_message_is_signal(message, interface, RESOURCED_FREEZER_SIGNAL)) {
745                 if (dbus_message_get_args(message, &error, DBUS_TYPE_INT32, &state,
746                                         DBUS_TYPE_INT32, &pid, DBUS_TYPE_INVALID) == FALSE) {
747                         _ERR("Failed to get data: %s", error.message);
748                         dbus_error_free(&error);
749                         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
750                 }
751
752                 if (pid == getpid() && state == 0) { //thawed
753                         suspend = APPCORE_SUSPENDED_STATE_DID_EXIT_FROM_SUSPEND;
754                         SECURE_LOGD("[__SUSPEND__] state: %d (0: thawed, 1: frozen), pid: %d", state, pid);
755
756                         struct appcore *ac = (struct appcore *)user_data;
757                         if (!ac->allowed_bg && ac->suspended_state) {
758                                 __remove_suspend_timer(ac);
759                                 __sys_do(user_data, &suspend, SE_SUSPENDED_STATE);
760                                 ac->suspended_state = false;
761                                 __add_suspend_timer(ac);
762                         }
763                 }
764         }
765
766         return DBUS_HANDLER_RESULT_HANDLED;
767 }
768
769 int _appcore_init_suspend_dbus_handler(void *data)
770 {
771         DBusError error;
772         char rule[MAX_LOCAL_BUFSZ];
773
774         if (__suspend_dbus_handler_initialized)
775                 return 0;
776
777         dbus_error_init(&error);
778         if (!bus) {
779                 bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
780                 if (!bus) {
781                         _ERR("Failed to connect to the D-BUS daemon: %s", error.message);
782                         dbus_error_free(&error);
783                         return -1;
784                 }
785         }
786         dbus_connection_setup_with_g_main(bus, NULL);
787
788         snprintf(rule, MAX_LOCAL_BUFSZ,
789                         "path='%s',type='signal',interface='%s'", RESOURCED_FREEZER_PATH, RESOURCED_FREEZER_INTERFACE);
790         /* listening to messages */
791         dbus_bus_add_match(bus, rule, &error);
792         if (dbus_error_is_set(&error)) {
793                 _ERR("Fail to rule set: %s", error.message);
794                 dbus_error_free(&error);
795                 return -1;
796         }
797
798         if (dbus_connection_add_filter(bus, __suspend_dbus_signal_filter, data, NULL) == FALSE) {
799                 _ERR("add filter fail");
800                 return -1;
801         }
802
803         __suspend_dbus_handler_initialized = 1;
804         _DBG("[__SUSPEND__] suspend signal initialized");
805
806         return 0;
807 }
808 #endif