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