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