Remove Profile Build Dependency: Do it at runtime
[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 #include <system_info.h>
36
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
46 #define SQLITE_FLUSH_MAX                (1024*1024)
47
48 #define PATH_LOCALE "locale"
49
50 static struct appcore core;
51 static pid_t _pid;
52
53 static enum appcore_event to_ae[SE_MAX] = {
54         APPCORE_EVENT_UNKNOWN,  /* SE_UNKNOWN */
55         APPCORE_EVENT_LOW_MEMORY,       /* SE_LOWMEM */
56         APPCORE_EVENT_LOW_BATTERY,      /* SE_LOWBAT */
57         APPCORE_EVENT_LANG_CHANGE,      /* SE_LANGCGH */
58         APPCORE_EVENT_REGION_CHANGE,
59         APPCORE_EVENT_SUSPENDED_STATE_CHANGE,
60         APPCORE_EVENT_UPDATE_REQUESTED,
61 };
62
63 static int appcore_event_initialized[SE_MAX] = {0,};
64
65 enum cb_type {                  /* callback */
66         _CB_NONE,
67         _CB_SYSNOTI,
68         _CB_APPNOTI,
69         _CB_VCONF,
70 };
71
72 struct evt_ops {
73         enum cb_type type;
74         union {
75                 enum appcore_event sys;
76                 enum app_event app;
77                 const char *vkey;
78         } key;
79
80         int (*cb_pre) (void *);
81         int (*cb) (void *);
82         int (*cb_post) (void *);
83
84         int (*vcb_pre) (void *, void *);
85         int (*vcb) (void *, void *);
86         int (*vcb_post) (void *, void *);
87 };
88
89 struct open_s {
90         int (*callback) (void *);
91         void *cbdata;
92 };
93
94 static struct open_s open;
95
96 static int __app_terminate(void *data);
97 static int __app_resume(void *data);
98 static int __app_reset(void *data, bundle *k);
99
100 static int __sys_lowmem_post(void *data, void *evt);
101 static int __sys_lowmem(void *data, void *evt);
102 static int __sys_lowbatt(void *data, void *evt);
103 static int __sys_langchg_pre(void *data, void *evt);
104 static int __sys_langchg(void *data, void *evt);
105 static int __sys_regionchg_pre(void *data, void *evt);
106 static int __sys_regionchg(void *data, void *evt);
107 extern void aul_finalize();
108
109
110 static struct evt_ops evtops[] = {
111         {
112          .type = _CB_VCONF,
113          .key.vkey = VCONFKEY_SYSMAN_LOW_MEMORY,
114          .vcb_post = __sys_lowmem_post,
115          .vcb = __sys_lowmem,
116          },
117         {
118          .type = _CB_VCONF,
119          .key.vkey = VCONFKEY_SYSMAN_BATTERY_STATUS_LOW,
120          .vcb = __sys_lowbatt,
121          },
122         {
123          .type = _CB_VCONF,
124          .key.vkey = VCONFKEY_LANGSET,
125          .vcb_pre = __sys_langchg_pre,
126          .vcb = __sys_langchg,
127          },
128         {
129          .type = _CB_VCONF,
130          .key.vkey = VCONFKEY_REGIONFORMAT,
131          .vcb_pre = __sys_regionchg_pre,
132          .vcb = __sys_regionchg,
133          },
134         {
135          .type = _CB_VCONF,
136          .key.vkey = VCONFKEY_REGIONFORMAT_TIME1224,
137          .vcb = __sys_regionchg,
138          },
139 };
140
141 static GDBusConnection *bus;
142 static guint __suspend_dbus_handler_initialized;
143
144 static int __get_locale_resource_dir(char *locale_dir, int size)
145 {
146         const char *res_path;
147
148         res_path = aul_get_app_resource_path();
149         if (res_path == NULL) {
150                 _ERR("Failed to get resource path");
151                 return -1;
152         }
153
154         snprintf(locale_dir, size, "%s" PATH_LOCALE, res_path);
155         if (access(locale_dir, R_OK) != 0)
156                 return -1;
157
158         return 0;
159 }
160
161 static int __app_terminate(void *data)
162 {
163         struct appcore *ac = data;
164
165         _retv_if(ac == NULL || ac->ops == NULL, -1);
166         _retv_if(ac->ops->cb_app == NULL, 0);
167
168         ac->ops->cb_app(AE_TERMINATE, ac->ops->data, NULL);
169
170         return 0;
171 }
172
173 static int __bgapp_terminate(void *data)
174 {
175         struct appcore *ac = data;
176
177         _retv_if(ac == NULL || ac->ops == NULL, -1);
178         _retv_if(ac->ops->cb_app == NULL, 0);
179
180         ac->ops->cb_app(AE_TERMINATE_BGAPP, ac->ops->data, NULL);
181
182         return 0;
183 }
184
185 static gboolean __prt_ltime(gpointer data)
186 {
187         int msec;
188
189         msec = appcore_measure_time_from(NULL);
190         if (msec)
191                 _DBG("[APP %d] first idle after reset: %d msec", _pid, msec);
192
193         return FALSE;
194 }
195
196 static int __app_reset(void *data, bundle * k)
197 {
198         struct appcore *ac = data;
199         _retv_if(ac == NULL || ac->ops == NULL, -1);
200         _retv_if(ac->ops->cb_app == NULL, 0);
201
202         g_idle_add(__prt_ltime, ac);
203
204         ac->ops->cb_app(AE_RESET, ac->ops->data, k);
205
206         return 0;
207 }
208
209 static int __app_resume(void *data)
210 {
211         struct appcore *ac = data;
212         _retv_if(ac == NULL || ac->ops == NULL, -1);
213         _retv_if(ac->ops->cb_app == NULL, 0);
214
215         ac->ops->cb_app(AE_RAISE, ac->ops->data, NULL);
216         return 0;
217 }
218
219 static int __app_pause(void *data)
220 {
221         struct appcore *ac = data;
222         _retv_if(ac == NULL || ac->ops == NULL, -1);
223         _retv_if(ac->ops->cb_app == NULL, 0);
224
225         ac->ops->cb_app(AE_LOWER, ac->ops->data, NULL);
226         return 0;
227 }
228
229 static int __app_update_requested(void *data)
230 {
231         struct appcore *ac = data;
232
233         _retv_if(ac == NULL || ac->ops == NULL, -1);
234         _retv_if(ac->ops->cb_app == NULL, 0);
235         ac->ops->cb_app(AE_UPDATE_REQUESTED, ac->ops->data, NULL);
236
237         return 0;
238 }
239
240 static int __sys_do_default(struct appcore *ac, enum sys_event event)
241 {
242         int r;
243
244         switch (event) {
245         case SE_LOWBAT:
246                 /*r = __def_lowbatt(ac);*/
247                 r = 0;
248                 break;
249         default:
250                 r = 0;
251                 break;
252         };
253
254         return r;
255 }
256
257 static int __sys_do(struct appcore *ac, void *event_info, enum sys_event event)
258 {
259         struct sys_op *op;
260
261         _retv_if(ac == NULL || event >= SE_MAX, -1);
262
263         op = &ac->sops[event];
264
265         if (op->func == NULL)
266                 return __sys_do_default(ac, event);
267
268         return op->func(event_info, op->data);
269 }
270
271 static int __sys_lowmem_post(void *data, void *evt)
272 {
273         keynode_t *key = evt;
274         int val;
275
276         val = vconf_keynode_get_int(key);
277
278         if (val >= VCONFKEY_SYSMAN_LOW_MEMORY_SOFT_WARNING)     {
279 #if defined(MEMORY_FLUSH_ACTIVATE)
280                 struct appcore *ac = data;
281                 ac->ops->cb_app(AE_LOWMEM_POST, ac->ops->data, NULL);
282 #else
283                 malloc_trim(0);
284 #endif
285         }
286         return 0;
287 }
288
289 static int __sys_lowmem(void *data, void *evt)
290 {
291         keynode_t *key = evt;
292         int val;
293
294         val = vconf_keynode_get_int(key);
295
296         if (val >= VCONFKEY_SYSMAN_LOW_MEMORY_SOFT_WARNING)
297                 return __sys_do(data, (void *)&val, SE_LOWMEM);
298
299         return 0;
300 }
301
302 static int __sys_lowbatt(void *data, void *evt)
303 {
304         keynode_t *key = evt;
305         int val;
306
307         val = vconf_keynode_get_int(key);
308
309         /* VCONFKEY_SYSMAN_BAT_CRITICAL_LOW or VCONFKEY_SYSMAN_POWER_OFF */
310         if (val <= VCONFKEY_SYSMAN_BAT_CRITICAL_LOW)
311                 return __sys_do(data, (void *)&val, SE_LOWBAT);
312
313         return 0;
314 }
315
316 static int __sys_langchg_pre(void *data, void *evt)
317 {
318         update_lang();
319         return 0;
320 }
321
322 static int __sys_langchg(void *data, void *evt)
323 {
324         keynode_t *key = evt;
325         char *val;
326
327         val = vconf_keynode_get_str(key);
328
329         return __sys_do(data, (void *)val, SE_LANGCHG);
330 }
331
332 static int __sys_regionchg_pre(void *data, void *evt)
333 {
334         update_region();
335         return 0;
336 }
337
338 static int __sys_regionchg(void *data, void *evt)
339 {
340         keynode_t *key = evt;
341         char *val = NULL;
342         const char *name;
343
344         name = vconf_keynode_get_name(key);
345         if (!strcmp(name, VCONFKEY_REGIONFORMAT))
346                 val = vconf_keynode_get_str(key);
347
348         return __sys_do(data, (void *)val, SE_REGIONCHG);
349 }
350
351 static void __vconf_do(struct evt_ops *eo, keynode_t * key, void *data)
352 {
353         _ret_if(eo == NULL);
354
355         if (eo->vcb_pre)
356                 eo->vcb_pre(data, key);
357
358         if (eo->vcb)
359                 eo->vcb(data, key);
360
361         if (eo->vcb_post)
362                 eo->vcb_post(data, key);
363 }
364
365 static void __vconf_cb(keynode_t *key, void *data)
366 {
367         int i;
368         const char *name;
369
370         name = vconf_keynode_get_name(key);
371         _ret_if(name == NULL);
372
373         _DBG("[APP %d] vconf changed: %s", _pid, name);
374
375         for (i = 0; i < sizeof(evtops) / sizeof(evtops[0]); i++) {
376                 struct evt_ops *eo = &evtops[i];
377
378                 switch (eo->type) {
379                 case _CB_VCONF:
380                         if (!strcmp(name, eo->key.vkey))
381                                 __vconf_do(eo, key, data);
382                         break;
383                 default:
384                         /* do nothing */
385                         break;
386                 }
387         }
388 }
389
390 static int __add_vconf(struct appcore *ac, enum sys_event se)
391 {
392         int r;
393
394         switch (se) {
395         case SE_LOWMEM:
396                 r = vconf_notify_key_changed(VCONFKEY_SYSMAN_LOW_MEMORY, __vconf_cb, ac);
397                 break;
398         case SE_LOWBAT:
399                 r = vconf_notify_key_changed(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, __vconf_cb, ac);
400                 break;
401         case SE_LANGCHG:
402                 r = vconf_notify_key_changed(VCONFKEY_LANGSET, __vconf_cb, ac);
403                 break;
404         case SE_REGIONCHG:
405                 r = vconf_notify_key_changed(VCONFKEY_REGIONFORMAT, __vconf_cb, ac);
406                 if (r < 0)
407                         break;
408
409                 r = vconf_notify_key_changed(VCONFKEY_REGIONFORMAT_TIME1224, __vconf_cb, ac);
410                 break;
411         default:
412                 r = -1;
413                 break;
414         }
415
416         return r;
417 }
418
419 static int __del_vconf(enum sys_event se)
420 {
421         int r;
422
423         switch (se) {
424         case SE_LOWMEM:
425                 r = vconf_ignore_key_changed(VCONFKEY_SYSMAN_LOW_MEMORY, __vconf_cb);
426                 break;
427         case SE_LOWBAT:
428                 r = vconf_ignore_key_changed(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, __vconf_cb);
429                 break;
430         case SE_LANGCHG:
431                 r = vconf_ignore_key_changed(VCONFKEY_LANGSET, __vconf_cb);
432                 break;
433         case SE_REGIONCHG:
434                 r = vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT, __vconf_cb);
435                 if (r < 0)
436                         break;
437
438                 r = vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT_TIME1224, __vconf_cb);
439                 break;
440         default:
441                 r = -1;
442                 break;
443         }
444
445         return r;
446 }
447
448 static int __del_vconf_list(void)
449 {
450         int r;
451         enum sys_event se;
452
453         for (se = SE_LOWMEM; se < SE_MAX; se++) {
454                 if (appcore_event_initialized[se]) {
455                         r = __del_vconf(se);
456                         if (r < 0)
457                                 _ERR("Delete vconf callback failed");
458                         else
459                                 appcore_event_initialized[se] = 0;
460                 }
461         }
462
463         return 0;
464 }
465
466 static gboolean __flush_memory(gpointer data)
467 {
468         int suspend = APPCORE_SUSPENDED_STATE_WILL_ENTER_SUSPEND;
469         struct appcore *ac = (struct appcore *)data;
470
471         appcore_flush_memory();
472
473         if (!ac)
474                 return FALSE;
475
476         ac->tid = 0;
477
478         if (!ac->allowed_bg && !ac->suspended_state) {
479                 _DBG("[__SUSPEND__] flush case");
480                 __sys_do(ac, &suspend, SE_SUSPENDED_STATE);
481                 ac->suspended_state = true;
482         }
483
484         return FALSE;
485 }
486
487 static void __add_suspend_timer(struct appcore *ac)
488 {
489         ac->tid = g_timeout_add_seconds(5, __flush_memory, ac);
490 }
491
492 static void __remove_suspend_timer(struct appcore *ac)
493 {
494         if (ac->tid > 0) {
495                 g_source_remove(ac->tid);
496                 ac->tid = 0;
497         }
498 }
499
500 static int __aul_handler(aul_type type, bundle *b, void *data)
501 {
502         int ret;
503         const char **tep_path = NULL;
504         int len = 0;
505         int i;
506         const char *bg = NULL;
507         struct appcore *ac = data;
508         int suspend = APPCORE_SUSPENDED_STATE_DID_EXIT_FROM_SUSPEND;
509
510         switch (type) {
511         case AUL_START:
512                 _DBG("[APP %d]     AUL event: AUL_START", _pid);
513                 tep_path = bundle_get_str_array(b, AUL_TEP_PATH, &len);
514                 if (tep_path) {
515                         for (i = 0; i < len; i++) {
516                                 ret = aul_check_tep_mount(tep_path[i]);
517                                 if (ret == -1) {
518                                         _ERR("mount request not completed within 1 sec");
519                                         exit(-1);
520                                 }
521                         }
522                 }
523
524                 if (_APPFW_FEATURE_BACKGROUND_MANAGEMENT) {
525                         bg = bundle_get_val(b, AUL_K_ALLOWED_BG);
526                         if (bg && strncmp(bg, "ALLOWED_BG", strlen("ALLOWED_BG")) == 0) {
527                                 _DBG("[__SUSPEND__] allowed background");
528                                 ac->allowed_bg = true;
529                                 __remove_suspend_timer(data);
530                         }
531                 }
532
533                 __app_reset(data, b);
534                 break;
535         case AUL_RESUME:
536                 _DBG("[APP %d]     AUL event: AUL_RESUME", _pid);
537                 if (_APPFW_FEATURE_BACKGROUND_MANAGEMENT) {
538                         bg = bundle_get_val(b, AUL_K_ALLOWED_BG);
539                         if (bg && strncmp(bg, "ALLOWED_BG", strlen("ALLOWED_BG")) == 0) {
540                                 _DBG("[__SUSPEND__] allowed background");
541                                 ac->allowed_bg = true;
542                                 __remove_suspend_timer(data);
543                         }
544                 }
545
546                 if (open.callback) {
547                         ret = open.callback(open.cbdata);
548                         if (ret == 0)
549                                 __app_resume(data);
550                 } else {
551                         __app_resume(data);
552                 }
553                 break;
554         case AUL_TERMINATE:
555                 _DBG("[APP %d]     AUL event: AUL_TERMINATE", _pid);
556                 if (_APPFW_FEATURE_BACKGROUND_MANAGEMENT && !ac->allowed_bg)
557                         __remove_suspend_timer(data);
558
559                 __app_terminate(data);
560                 break;
561         case AUL_TERMINATE_BGAPP:
562                 _DBG("[APP %d]     AUL event: AUL_TERMINATE_BGAPP", _pid);
563                 if (_APPFW_FEATURE_BACKGROUND_MANAGEMENT && !ac->allowed_bg)
564                         __remove_suspend_timer(data);
565
566                 __bgapp_terminate(data);
567                 break;
568         case AUL_PAUSE:
569                 _DBG("[APP %d]     AUL event: AUL_PAUSE", _pid);
570                 __app_pause(data);
571                 break;
572         case AUL_WAKE:
573                 if (_APPFW_FEATURE_BACKGROUND_MANAGEMENT) {
574                         _DBG("[APP %d]     AUL event: AUL_WAKE", _pid);
575                         if (!ac->allowed_bg && ac->suspended_state) {
576                                 __remove_suspend_timer(data);
577                                 __sys_do(ac, &suspend, SE_SUSPENDED_STATE);
578                                 ac->suspended_state = false;
579                         }
580                         if (b) {
581                                 bg = bundle_get_val(b, AUL_K_ALLOWED_BG);
582                                 if (bg && strcmp(bg, "ALLOWED_BG") == 0) {
583                                         _DBG("[__SUSPEND__] allowed background");
584                                         ac->allowed_bg = true;
585                                 }
586                         }
587                         break;
588                 }
589                 goto __default__;
590         case AUL_SUSPEND:
591                 if (_APPFW_FEATURE_BACKGROUND_MANAGEMENT) {
592                         _DBG("[APP %d]     AUL event: AUL_SUSPEND", _pid);
593                         ac->allowed_bg = false;
594                         if (!ac->suspended_state) {
595                                 __remove_suspend_timer(data);
596                                 __flush_memory((gpointer)ac);
597                         }
598                         break;
599                 }
600                 goto __default__;
601         case AUL_UPDATE_REQUESTED:
602                 _DBG("[APP %d]     AUL event: AUL_UPDATE_REQUESTED", _pid);
603                 __app_update_requested(data);
604                 break;
605 __default__:
606         default:
607                 _DBG("[APP %d]     AUL event: %d", _pid, type);
608                 /* do nothing */
609                 break;
610         }
611
612         return 0;
613 }
614
615
616 static void __clear(struct appcore *ac)
617 {
618         memset(ac, 0, sizeof(struct appcore));
619 }
620
621 EXPORT_API void appcore_get_app_core(struct appcore **ac)
622 {
623         *ac = &core;
624 }
625
626 EXPORT_API int appcore_set_open_cb(int (*cb) (void *),
627                                        void *data)
628 {
629         open.callback = cb;
630         open.cbdata = data;
631
632         return 0;
633 }
634
635 EXPORT_API int appcore_set_event_callback(enum appcore_event event,
636                                           int (*cb) (void *, void *), void *data)
637 {
638         struct appcore *ac = &core;
639         struct sys_op *op;
640         enum sys_event se;
641         int r = 0;
642
643         for (se = SE_UNKNOWN; se < SE_MAX; se++) {
644                 if (event == to_ae[se])
645                         break;
646         }
647
648         if (se == SE_UNKNOWN || se >= SE_MAX) {
649                 _ERR("Unregistered event");
650                 errno = EINVAL;
651                 return -1;
652         }
653
654         op = &ac->sops[se];
655
656         op->func = cb;
657         op->data = data;
658
659         if (op->func && !appcore_event_initialized[se]) {
660                 r = __add_vconf(ac, se);
661                 if (r < 0)
662                         _ERR("Add vconf callback failed");
663                 else
664                         appcore_event_initialized[se] = 1;
665         } else if (!op->func && appcore_event_initialized[se]) {
666                 r = __del_vconf(se);
667                 if (r < 0)
668                         _ERR("Delete vconf callback failed");
669                 else
670                         appcore_event_initialized[se] = 0;
671         }
672
673         return 0;
674 }
675
676 static gboolean __init_suspend(gpointer data)
677 {
678         int r;
679
680         r = __appcore_init_suspend_dbus_handler(&core);
681         if (r == -1) {
682                 _ERR("Initailzing suspended state handler failed");
683         }
684
685         return FALSE;
686 }
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         if (_APPFW_FEATURE_BACKGROUND_MANAGEMENT)
731                 g_idle_add(__init_suspend, NULL);
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                 if (_APPFW_FEATURE_BACKGROUND_MANAGEMENT) {
746                         __remove_suspend_timer(&core);
747                         __appcore_fini_suspend_dbus_handler();
748                 }
749         }
750         aul_finalize();
751 }
752
753 EXPORT_API int appcore_flush_memory(void)
754 {
755         int (*flush_fn) (int);
756
757         struct appcore *ac = &core;
758
759         if (!core.state) {
760                 _ERR("Appcore not initialized");
761                 return -1;
762         }
763
764         _DBG("[APP %d] Flushing memory ...", _pid);
765
766         if (ac->ops->cb_app)
767                 ac->ops->cb_app(AE_MEM_FLUSH, ac->ops->data, NULL);
768
769         flush_fn = dlsym(RTLD_DEFAULT, "sqlite3_release_memory");
770         if (flush_fn)
771                 flush_fn(SQLITE_FLUSH_MAX);
772
773         malloc_trim(0);
774         /*
775         *Disabled - the impact of stack_trim() is unclear
776         *stack_trim();
777         */
778
779         _DBG("[APP %d] Flushing memory DONE", _pid);
780
781         return 0;
782 }
783
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
848 void __appcore_fini_suspend_dbus_handler(void)
849 {
850         if (bus == NULL)
851                 return;
852
853         if (__suspend_dbus_handler_initialized) {
854                 g_dbus_connection_signal_unsubscribe(bus,
855                                 __suspend_dbus_handler_initialized);
856                 __suspend_dbus_handler_initialized = 0;
857         }
858
859         g_object_unref(bus);
860         bus = NULL;
861 }
862
863 tizen_profile_t _get_tizen_profile()
864 {
865         static tizen_profile_t profile = TIZEN_PROFILE_UNKNOWN;
866         if (__builtin_expect(profile != TIZEN_PROFILE_UNKNOWN, 1))
867                 return profile;
868
869         char *profileName;
870         system_info_get_platform_string("http://tizen.org/feature/profile", &profileName);
871         switch (*profileName) {
872         case 'm':
873         case 'M':
874                 profile = TIZEN_PROFILE_MOBILE;
875                 break;
876         case 'w':
877         case 'W':
878                 profile = TIZEN_PROFILE_WEARABLE;
879                 break;
880         case 't':
881         case 'T':
882                 profile = TIZEN_PROFILE_TV;
883                 break;
884         case 'i':
885         case 'I':
886                 profile = TIZEN_PROFILE_IVI;
887                 break;
888         default: // common or unTIZEN_nown ==> ALL ARE COMMON.
889                 profile = TIZEN_PROFILE_COMMON;
890         }
891         free(profileName);
892
893         return profile;
894 }