Release version 1.18.7
[platform/core/appfw/app-core.git] / legacy / src / base / appcore_base.c
1 /*
2  * Copyright (c) 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 <stdbool.h>
21 #include <errno.h>
22 #include <string.h>
23 #include <stdlib.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <unistd.h>
27 #include <malloc.h>
28 #include <locale.h>
29 #include <libintl.h>
30 #include <linux/limits.h>
31 #include <glib.h>
32 #include <gio/gio.h>
33 #include <sys/time.h>
34 #include <dlfcn.h>
35 #include <vconf.h>
36 #include <aul.h>
37 #include <aul_app_lifecycle.h>
38 #include <bundle_internal.h>
39 #include <sensor_internal.h>
40 #include <ttrace.h>
41 #include <system_info.h>
42
43 #include "appcore_base.h"
44 #include "appcore_base_private.h"
45 #include "appcore_watchdog.h"
46 #include "appcore_base_control.h"
47
48 #define PATH_LOCALE "locale"
49 #define RESOURCED_FREEZER_PATH "/Org/Tizen/ResourceD/Freezer"
50 #define RESOURCED_FREEZER_INTERFACE "org.tizen.resourced.freezer"
51 #define RESOURCED_FREEZER_SIGNAL "FreezerState"
52 #define SQLITE_FLUSH_MAX (1024 * 1024)
53
54 typedef struct _appcore_base_context {
55         appcore_base_ops ops;
56         void *data;
57         int argc;
58         char **argv;
59         unsigned int tid;
60         bool suspended_state;
61         bool allowed_bg;
62         bool dirty;
63         guint sid;
64         int display_state;
65 } appcore_base_context;
66
67 typedef struct _appcore_base_event_node {
68         int type;
69         appcore_base_event_cb cb;
70         void *data;
71         void *prev_event;
72 } appcore_base_event_node;
73
74 typedef struct _appcore_base_rotation {
75         int conn;
76         int lock;
77         int ref;
78         enum appcore_base_rm rm;
79         int charger_status;
80         bool initialized;
81 } appcore_base_rotation;
82
83 struct lang_info_s {
84         char *parent;
85         GList *list;
86 };
87
88 static appcore_base_context __context;
89 static GList *__events;
90 static GDBusConnection *__bus;
91 static guint __suspend_dbus_handler_initialized;
92 static char *__locale_dir;
93 static appcore_base_rotation __rotation;
94
95 appcore_base_tizen_profile_t appcore_base_get_tizen_profile(void)
96 {
97         static appcore_base_tizen_profile_t profile = TIZEN_PROFILE_UNKNOWN;
98         char *profile_name = NULL;
99
100         if (__builtin_expect(profile != TIZEN_PROFILE_UNKNOWN, 1))
101                 return profile;
102
103         system_info_get_platform_string("http://tizen.org/feature/profile",
104                         &profile_name);
105         if (profile_name == NULL)
106                 return profile;
107
108         switch (*profile_name) {
109         case 'm':
110         case 'M':
111                 profile = TIZEN_PROFILE_MOBILE;
112                 break;
113         case 'w':
114         case 'W':
115                 profile = TIZEN_PROFILE_WEARABLE;
116                 break;
117         case 't':
118         case 'T':
119                 profile = TIZEN_PROFILE_TV;
120                 break;
121         case 'i':
122         case 'I':
123                 profile = TIZEN_PROFILE_IVI;
124                 break;
125         default:
126                 profile = TIZEN_PROFILE_COMMON;
127                 break;
128         }
129         free(profile_name);
130
131         return profile;
132 }
133
134 static int __compare_event(void *prev_event, void *curr_event, int type)
135 {
136         char *curr_strval;
137         char *prev_strval;
138         int curr_intval;
139         int prev_intval;
140         int ret = -1;
141
142         switch (type) {
143         case APPCORE_BASE_EVENT_LOW_MEMORY:
144         case APPCORE_BASE_EVENT_LOW_BATTERY:
145         case APPCORE_BASE_EVENT_DEVICE_ORIENTATION_CHANGED:
146         case APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE:
147                 prev_intval = GPOINTER_TO_INT(prev_event);
148                 curr_intval = *(int *)curr_event;
149                 if (prev_intval == curr_intval)
150                         ret = 0;
151                 break;
152         case APPCORE_BASE_EVENT_LANG_CHANGE:
153         case APPCORE_BASE_EVENT_REGION_CHANGE:
154                 prev_strval = prev_event;
155                 curr_strval = curr_event;
156                 if (prev_strval && curr_strval &&
157                                 !strcmp(prev_strval, curr_strval))
158                         ret = 0;
159                 break;
160         default:
161                 break;
162         }
163
164         return ret;
165 }
166
167 static void __unset_prev_event(void **prev_event, int type)
168 {
169         if (type == APPCORE_BASE_EVENT_LANG_CHANGE ||
170                         type == APPCORE_BASE_EVENT_REGION_CHANGE)
171                 free(*prev_event);
172         *prev_event = NULL;
173 }
174
175 static void __set_prev_event(void **prev_event, void *curr_event, int type)
176 {
177         int curr_intval;
178         char *curr_strval;
179
180         switch (type) {
181         case APPCORE_BASE_EVENT_LOW_MEMORY:
182         case APPCORE_BASE_EVENT_LOW_BATTERY:
183         case APPCORE_BASE_EVENT_DEVICE_ORIENTATION_CHANGED:
184         case APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE:
185                 curr_intval = *(int *)curr_event;
186                 *prev_event = GINT_TO_POINTER(curr_intval);
187                 break;
188         case APPCORE_BASE_EVENT_LANG_CHANGE:
189         case APPCORE_BASE_EVENT_REGION_CHANGE:
190                 curr_strval = curr_event;
191                 if (curr_strval)
192                         *prev_event = strdup(curr_strval);
193                 break;
194         default:
195                 break;
196         }
197 }
198
199 static void __invoke_callback(void *event, int type)
200 {
201         GList *iter = __events;
202
203         while (iter) {
204                 appcore_base_event_node *node = iter->data;
205                 iter = g_list_next(iter);
206
207                 if (node->type != type)
208                         continue;
209
210                 if (__compare_event(node->prev_event, event, type)) {
211                         node->cb(event, node->data);
212                         __unset_prev_event(&node->prev_event, type);
213                         __set_prev_event(&node->prev_event, event, type);
214                 }
215         }
216 }
217
218 static bool __exist_callback(int type)
219 {
220         GList *iter = __events;
221
222         while (iter) {
223                 appcore_base_event_node *node = iter->data;
224
225                 if (node->type == type)
226                         return true;
227
228                 iter = g_list_next(iter);
229         }
230
231         return false;
232 }
233
234 static enum appcore_base_rm __get_rm(sensor_data_t data)
235 {
236         int event;
237         enum appcore_base_rm rm;
238
239         if (data.value_count <= 0) {
240                 _ERR("Failed to get sensor data");
241                 return APPCORE_BASE_RM_UNKNOWN;
242         }
243
244         event = data.values[0];
245         switch (event) {
246         case AUTO_ROTATION_DEGREE_0:
247                 rm = APPCORE_BASE_RM_PORTRAIT_NORMAL;
248                 break;
249         case AUTO_ROTATION_DEGREE_90:
250                 rm = APPCORE_BASE_RM_LANDSCAPE_NORMAL;
251                 break;
252         case AUTO_ROTATION_DEGREE_180:
253                 rm = APPCORE_BASE_RM_PORTRAIT_REVERSE;
254                 break;
255         case AUTO_ROTATION_DEGREE_270:
256                 rm = APPCORE_BASE_RM_LANDSCAPE_REVERSE;
257                 break;
258         default:
259                 rm = APPCORE_BASE_RM_UNKNOWN;
260                 break;
261         }
262
263         return rm;
264 }
265
266 static void __lock_cb(keynode_t *node, void *user_data)
267 {
268         bool r;
269         sensor_data_t data;
270         enum appcore_base_rm rm;
271
272         __rotation.lock = !vconf_keynode_get_bool(node);
273         if (__rotation.lock) {
274                 _DBG("Rotation locked");
275                 rm = APPCORE_BASE_RM_PORTRAIT_NORMAL;
276         } else {
277                 _DBG("Rotation unlocked");
278                 r = sensord_get_data(__rotation.conn, AUTO_ROTATION_SENSOR, &data);
279                 if (!r) {
280                         _ERR("Failed to get sensor data");
281                         return;
282                 }
283
284                 rm = __get_rm(data);
285                 if (rm == APPCORE_BASE_RM_UNKNOWN) {
286                         _ERR("Unknown mode");
287                         return;
288                 }
289         }
290
291         if (__rotation.rm == rm)
292                 return;
293
294         _DBG("Rotation: %d -> %d", __rotation.rm, rm);
295         __rotation.rm = rm;
296         __invoke_callback((void *)&__rotation.rm, APPCORE_BASE_EVENT_DEVICE_ORIENTATION_CHANGED);
297 }
298
299 static void __auto_rotation_changed_cb(sensor_t sensor, unsigned int event_type,
300                 sensor_data_t *data, void *user_data)
301 {
302         enum appcore_base_rm rm;
303
304         if (data == NULL)
305                 return;
306
307         if (__rotation.lock)
308                 return;
309
310         if (event_type != AUTO_ROTATION_CHANGE_STATE_EVENT)
311                 return;
312
313         rm = __get_rm(*data);
314         if (rm == APPCORE_BASE_RM_UNKNOWN) {
315                 _ERR("Unknown mode");
316                 return;
317         }
318
319         _DBG("Rotation: %d -> %d", __rotation.rm, rm);
320         __rotation.rm = rm;
321         __invoke_callback((void *)&__rotation.rm, APPCORE_BASE_EVENT_DEVICE_ORIENTATION_CHANGED);
322 }
323
324 static void __fini_rotation(void)
325 {
326         if (!__rotation.initialized)
327                 return;
328
329         vconf_ignore_key_changed(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, __lock_cb);
330         sensord_unregister_event(__rotation.conn, AUTO_ROTATION_CHANGE_STATE_EVENT);
331         sensord_stop(__rotation.conn);
332         sensord_disconnect(__rotation.conn);
333
334         __rotation.lock = 0;
335         __rotation.initialized = false;
336 }
337
338 static void __init_rotation(void)
339 {
340         sensor_t sensor;
341         int lock;
342         bool r;
343
344         if (__rotation.initialized)
345                 return;
346
347         sensor = sensord_get_sensor(AUTO_ROTATION_SENSOR);
348         __rotation.conn = sensord_connect(sensor);
349         if (__rotation.conn < 0) {
350                 _ERR("Failed to connect sensord");
351                 return;
352         }
353
354         r = sensord_register_event(__rotation.conn, AUTO_ROTATION_CHANGE_STATE_EVENT,
355                         SENSOR_INTERVAL_NORMAL, 0, __auto_rotation_changed_cb, NULL);
356         if (!r) {
357                 _ERR("Failed to register auto rotation change event");
358                 sensord_disconnect(__rotation.conn);
359                 return;
360         }
361
362         r = sensord_start(__rotation.conn, 0);
363         if (!r) {
364                 _ERR("Failed to start sensord");
365                 sensord_unregister_event(__rotation.conn, AUTO_ROTATION_CHANGE_STATE_EVENT);
366                 sensord_disconnect(__rotation.conn);
367                 return;
368         }
369
370         lock = 0;
371         vconf_get_bool(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, &lock);
372         vconf_notify_key_changed(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, __lock_cb, NULL);
373
374         __rotation.lock = !lock;
375         __rotation.initialized = true;
376 }
377
378 static void __charger_status_changed_cb(keynode_t *keynode, void *user_data)
379 {
380         if (TIZEN_FEATURE_CHARGER_STATUS) {
381                 __rotation.charger_status = vconf_keynode_get_int(keynode);
382                 if (__rotation.charger_status) {
383                         if (__rotation.ref)
384                                 __init_rotation();
385                 } else {
386                         if (__rotation.ref)
387                                 __fini_rotation();
388                 }
389                 _DBG("charger status(%d)", __rotation.charger_status);
390         }
391 }
392
393 static void __unregister_rotation_changed_event(void)
394 {
395         if (!__rotation.ref)
396                 return;
397
398         __rotation.ref--;
399         if (__rotation.ref > 1)
400                 return;
401
402         __fini_rotation();
403         if (TIZEN_FEATURE_CHARGER_STATUS) {
404                 vconf_ignore_key_changed(VCONFKEY_SYSMAN_CHARGER_STATUS,
405                                 __charger_status_changed_cb);
406         }
407
408         __rotation.ref = 0;
409 }
410
411 static void __register_rotation_changed_event(void)
412 {
413         if (__rotation.ref) {
414                 __rotation.ref++;
415                 return;
416         }
417
418         if (TIZEN_FEATURE_CHARGER_STATUS) {
419                 vconf_get_int(VCONFKEY_SYSMAN_CHARGER_STATUS,
420                                 &__rotation.charger_status);
421                 vconf_notify_key_changed(VCONFKEY_SYSMAN_CHARGER_STATUS,
422                                 __charger_status_changed_cb, NULL);
423                 if (__rotation.charger_status)
424                         __init_rotation();
425         } else {
426                 __init_rotation();
427         }
428
429         __rotation.ref++;
430 }
431
432 static void __on_low_memory(keynode_t *key, void *data)
433 {
434         int val;
435
436         val = vconf_keynode_get_int(key);
437
438         if (val >= VCONFKEY_SYSMAN_LOW_MEMORY_SOFT_WARNING) {
439                 __invoke_callback(&val, APPCORE_BASE_EVENT_LOW_MEMORY);
440                 malloc_trim(0);
441         }
442 }
443
444 static void __on_low_battery(keynode_t *key, void *data)
445 {
446         int val;
447
448         val = vconf_keynode_get_int(key);
449
450         if (val <= VCONFKEY_SYSMAN_BAT_CRITICAL_LOW)
451                 __invoke_callback(&val, APPCORE_BASE_EVENT_LOW_BATTERY);
452 }
453
454 static void __destroy_lang_info(gpointer data)
455 {
456         struct lang_info_s *info = (struct lang_info_s *)data;
457
458         if (info == NULL)
459                 return;
460
461         if (info->list)
462                 g_list_free_full(info->list, free);
463         if (info->parent)
464                 free(info->parent);
465         free(info);
466 }
467
468 static struct lang_info_s *__create_lang_info(const char *lang)
469 {
470         struct lang_info_s *info;
471
472         info = calloc(1, sizeof(struct lang_info_s));
473         if (info == NULL) {
474                 _ERR("Out of memory");
475                 return NULL;
476         }
477
478         info->parent = strdup(lang);
479         if (info->parent == NULL) {
480                 _ERR("Out of memory");
481                 free(info);
482                 return NULL;
483         }
484
485         return info;
486 }
487
488 static gint __compare_langs(gconstpointer a, gconstpointer b)
489 {
490         if (!a || !b)
491                 return -1;
492
493         return strcmp(a, b);
494 }
495
496 static char *__get_string_before(const char *str, const char *delim)
497 {
498         char *new_str;
499         char *dup_str;
500         char *token;
501
502         dup_str = strdup(str);
503         if (dup_str == NULL)
504                 return NULL;
505
506         token = strtok(dup_str, delim);
507         if (token == NULL) {
508                 free(dup_str);
509                 return NULL;
510         }
511
512         new_str = strdup(token);
513         free(dup_str);
514
515         return new_str;
516 }
517
518 static GHashTable *__get_lang_table(void)
519 {
520         GHashTable *table;
521         DIR *dp;
522         struct dirent *dentry;
523         char buf[PATH_MAX];
524         struct stat stat_buf;
525         int ret;
526         char *parent_lang;
527         struct lang_info_s *info;
528
529         if (__locale_dir == NULL || __locale_dir[0] == '\0')
530                 return NULL;
531
532         table = g_hash_table_new_full(g_str_hash, g_str_equal,
533                         NULL, __destroy_lang_info);
534         if (table == NULL) {
535                 _ERR("Out of memory");
536                 return NULL;
537         }
538
539         dp = opendir(__locale_dir);
540         if (dp == NULL) {
541                 g_hash_table_destroy(table);
542                 return NULL;
543         }
544
545         while ((dentry = readdir(dp)) != NULL) {
546                 if (!strcmp(dentry->d_name, ".") ||
547                                 !strcmp(dentry->d_name, ".."))
548                         continue;
549
550                 snprintf(buf, sizeof(buf), "%s/%s",
551                                 __locale_dir, dentry->d_name);
552                 ret = stat(buf, &stat_buf);
553                 if (ret != 0 || !S_ISDIR(stat_buf.st_mode))
554                         continue;
555
556                 parent_lang = __get_string_before(dentry->d_name, "_");
557                 if (parent_lang == NULL) {
558                         _ERR("Out of memory");
559                         break;
560                 }
561
562                 info = g_hash_table_lookup(table, parent_lang);
563                 if (info == NULL) {
564                         info = __create_lang_info(parent_lang);
565                         if (info == NULL) {
566                                 free(parent_lang);
567                                 break;
568                         }
569                         g_hash_table_insert(table, info->parent, info);
570                 }
571                 info->list = g_list_append(info->list, strdup(dentry->d_name));
572                 free(parent_lang);
573         }
574         closedir(dp);
575
576         return table;
577 }
578
579 static GList *__append_langs(const char *lang, GList *list, GHashTable *table)
580 {
581         struct lang_info_s *info;
582         GList *found;
583         char *parent_lang = NULL;
584         char *extract_lang;
585
586         if (lang == NULL)
587                 return list;
588
589         list = g_list_append(list, strdup(lang));
590
591         extract_lang = __get_string_before(lang, ".");
592         if (extract_lang == NULL)
593                 return list;
594
595         found = g_list_find_custom(list, extract_lang, __compare_langs);
596         if (found) {
597                 list = g_list_remove_link(list, found);
598                 list = g_list_concat(list, found);
599                 goto end;
600         }
601
602         parent_lang = __get_string_before(extract_lang, "_");
603         if (parent_lang == NULL)
604                 goto end;
605
606         info = g_hash_table_lookup(table, parent_lang);
607         if (info == NULL)
608                 goto end;
609
610         found = g_list_find_custom(info->list, extract_lang, __compare_langs);
611         if (found) {
612                 info->list = g_list_remove_link(info->list, found);
613                 list = g_list_concat(list, found);
614                 goto end;
615         }
616
617         found = g_list_find_custom(info->list, parent_lang, __compare_langs);
618         if (found) {
619                 info->list = g_list_remove_link(info->list, found);
620                 list = g_list_concat(list, found);
621                 goto end;
622         }
623
624         found = g_list_first(info->list);
625         if (found) {
626                 info->list = g_list_remove_link(info->list, found);
627                 list = g_list_concat(list, found);
628         }
629
630 end:
631         if (extract_lang)
632                 free(extract_lang);
633         if (parent_lang)
634                 free(parent_lang);
635
636         return list;
637 }
638
639 static GList *__split_language(const char *lang)
640 {
641         GList *list = NULL;
642         char *dup_lang;
643         char *token;
644
645         dup_lang = strdup(lang);
646         if (dup_lang == NULL) {
647                 _ERR("Out of memory");
648                 return NULL;
649         }
650
651         token = strtok(dup_lang, ":");
652         while (token != NULL) {
653                 list = g_list_append(list, strdup(token));
654                 token = strtok(NULL, ":");
655         }
656         free(dup_lang);
657
658         return list;
659 }
660
661 static GList *__append_default_langs(GList *list)
662 {
663         const char *langs[] = {"en_US", "en_GB", "en"};
664         unsigned int i;
665         GList *found;
666
667         for (i = 0; i < (sizeof(langs) / sizeof(langs[0])); i++) {
668                 found = g_list_find_custom(list, langs[i], __compare_langs);
669                 if (found == NULL)
670                         list = g_list_append(list, strdup(langs[i]));
671         }
672
673         return list;
674 }
675
676 static char *__get_language(const char *lang)
677 {
678         GHashTable *table;
679         GList *list;
680         GList *lang_list = NULL;
681         GList *iter;
682         char *language;
683         char buf[LINE_MAX] = {'\0'};
684         size_t n;
685
686         list = __split_language(lang);
687         if (list == NULL)
688                 return NULL;
689
690         table = __get_lang_table();
691         if (table == NULL) {
692                 g_list_free_full(list, free);
693                 return NULL;
694         }
695
696         iter = g_list_first(list);
697         while (iter) {
698                 language = (char *)iter->data;
699                 lang_list = __append_langs(language, lang_list, table);
700                 iter = g_list_next(iter);
701         }
702         g_list_free_full(list, free);
703         g_hash_table_destroy(table);
704
705         lang_list = __append_default_langs(lang_list);
706         iter = g_list_first(lang_list);
707         while (iter) {
708                 language = (char *)iter->data;
709                 if (language) {
710                         if (buf[0] == '\0') {
711                                 snprintf(buf, sizeof(buf), "%s", language);
712                         } else {
713                                 n = sizeof(buf) - strlen(buf) - 1;
714                                 strncat(buf, ":", n);
715                                 n = sizeof(buf) - strlen(buf) - 1;
716                                 strncat(buf, language, n);
717                         }
718                 }
719                 iter = g_list_next(iter);
720         }
721         g_list_free_full(lang_list, free);
722
723         return strdup(buf);
724 }
725
726 static void __update_lang(void)
727 {
728         char *language;
729         char *lang;
730         char *r;
731
732         lang = vconf_get_str(VCONFKEY_LANGSET);
733         if (lang) {
734                 /* TODO: Use VCONFKEY_SETAPPL_LANGUAGES key */
735                 language = __get_language(lang);
736                 if (language) {
737                         _DBG("*****language(%s)", language);
738                         setenv("LANGUAGE", language, 1);
739                         free(language);
740                 } else {
741                         setenv("LANGUAGE", lang, 1);
742                 }
743                 setenv("LANG", lang, 1);
744                 setenv("LC_MESSAGES", lang, 1);
745                 setenv("LC_ALL", lang, 1);
746                 r = setlocale(LC_ALL, "");
747                 if (r == NULL) {
748                         r = setlocale(LC_ALL, "en_US.UTF-8");
749                         if (r != NULL) {
750                                 _DBG("*****appcore setlocale=%s\n", r);
751                         } else {
752                                 _DBG("*****appcore setlocale=\"C\"");
753                                 setenv("LC_ALL", "C", 1);
754                                 r = setlocale(LC_ALL, "");
755                                 if (r == NULL)
756                                         _ERR("failed to setlocale");
757                         }
758                 }
759                 free(lang);
760         }
761 }
762
763 static void __update_region(void)
764 {
765         char *region;
766         char *r;
767
768         region = vconf_get_str(VCONFKEY_REGIONFORMAT);
769         if (region) {
770                 setenv("LC_CTYPE", region, 1);
771                 setenv("LC_NUMERIC", region, 1);
772                 setenv("LC_TIME", region, 1);
773                 setenv("LC_COLLATE", region, 1);
774                 setenv("LC_MONETARY", region, 1);
775                 setenv("LC_PAPER", region, 1);
776                 setenv("LC_NAME", region, 1);
777                 setenv("LC_ADDRESS", region, 1);
778                 setenv("LC_TELEPHONE", region, 1);
779                 setenv("LC_MEASUREMENT", region, 1);
780                 setenv("LC_IDENTIFICATION", region, 1);
781                 r = setlocale(LC_ALL, "");
782                 if (r != NULL) {
783                         _DBG("*****appcore setlocale=%s\n", r);
784                 } else {
785                         _DBG("*****appcore setlocale=\"C\"");
786                         setenv("LC_ALL", "C", 1);
787                         r = setlocale(LC_ALL, "");
788                         if (r == NULL)
789                                 _ERR("failed to setlocale");
790                 }
791
792                 free(region);
793         }
794 }
795
796 static void __on_language_change(keynode_t *key, void *data)
797 {
798         char *val;
799
800         if (__context.sid) {
801                 g_source_remove(__context.sid);
802                 __context.sid = 0;
803         }
804
805         val = vconf_keynode_get_str(key);
806
807         __update_lang();
808         __invoke_callback((void *)val, APPCORE_BASE_EVENT_LANG_CHANGE);
809 }
810
811 static void __on_region_change(keynode_t *key, void *data)
812 {
813         char *val;
814         const char *name;
815
816         name = vconf_keynode_get_name(key);
817         if (name == NULL)
818                 return;
819
820         if (strcmp(name, VCONFKEY_REGIONFORMAT) &&
821                         strcmp(name, VCONFKEY_REGIONFORMAT_TIME1224))
822                 return;
823
824         val = vconf_get_str(VCONFKEY_REGIONFORMAT);
825
826         __update_region();
827         __invoke_callback((void *)val, APPCORE_BASE_EVENT_REGION_CHANGE);
828         free(val);
829 }
830
831 static gboolean __invoke_lang_change(gpointer data)
832 {
833         const char *lang;
834
835         __context.sid = 0;
836
837         lang = getenv("LANG");
838         if (!lang)
839                 return G_SOURCE_REMOVE;
840
841         __invoke_callback((void *)lang, APPCORE_BASE_EVENT_LANG_CHANGE);
842
843         return G_SOURCE_REMOVE;
844 }
845
846 static void __verify_language(void)
847 {
848         char *lang;
849         const char *env_lang;
850
851         env_lang = getenv("LANG");
852         if (!env_lang)
853                 return;
854
855         lang = vconf_get_str(VCONFKEY_LANGSET);
856         if (!lang)
857                 return;
858
859         if (strcmp(env_lang, lang) != 0) {
860                 _INFO("LANG(%s), LANGSET(%s)", env_lang, lang);
861                 __context.sid = g_idle_add(__invoke_lang_change, NULL);
862         }
863
864         free(lang);
865 }
866
867 static gboolean __flush_memory(gpointer data)
868 {
869         int suspend = APPCORE_BASE_SUSPENDED_STATE_WILL_ENTER_SUSPEND;
870
871         if (__context.ops.trim_memory)
872                 __context.ops.trim_memory(__context.data);
873
874         __context.tid = 0;
875
876         if (!__context.allowed_bg && !__context.suspended_state) {
877                 _DBG("[__SUSPEND__] flush case");
878                 __invoke_callback((void *)&suspend, APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE);
879                 __context.suspended_state = true;
880         }
881
882         return FALSE;
883 }
884
885 static void __add_suspend_timer(void)
886 {
887         __context.tid = g_timeout_add_seconds(5, __flush_memory, NULL);
888 }
889
890 static void __remove_suspend_timer(void)
891 {
892         if (__context.tid > 0) {
893                 g_source_remove(__context.tid);
894                 __context.tid = 0;
895         }
896 }
897
898 static void __on_receive_suspend_signal(GDBusConnection *connection,
899                                         const gchar *sender_name,
900                                         const gchar *object_path,
901                                         const gchar *interface_name,
902                                         const gchar *signal_name,
903                                         GVariant *parameters,
904                                         gpointer user_data)
905 {
906         gint suspend = APPCORE_BASE_SUSPENDED_STATE_DID_EXIT_FROM_SUSPEND;
907         gint pid;
908         gint status;
909
910         if (g_strcmp0(signal_name, RESOURCED_FREEZER_SIGNAL) == 0) {
911                 g_variant_get(parameters, "(ii)", &status, &pid);
912                 if (pid == getpid() && status == 0) {
913                         if (!__context.allowed_bg && __context.suspended_state) {
914                                 __remove_suspend_timer();
915                                 __invoke_callback((void *)&suspend, APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE);
916                                 __context.suspended_state = false;
917                                 __add_suspend_timer();
918                         }
919                 }
920         }
921 }
922
923 static int __init_suspend_dbus_handler(void)
924 {
925         GError *err = NULL;
926
927         if (__suspend_dbus_handler_initialized)
928                 return 0;
929
930         if (!__bus) {
931                 __bus = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
932                 if (!__bus) {
933                         _ERR("Failed to connect to the D-BUS daemon: %s",
934                                                 err->message);
935                         g_error_free(err);
936                         return -1;
937                 }
938         }
939
940         __suspend_dbus_handler_initialized = g_dbus_connection_signal_subscribe(
941                                                 __bus,
942                                                 NULL,
943                                                 RESOURCED_FREEZER_INTERFACE,
944                                                 RESOURCED_FREEZER_SIGNAL,
945                                                 RESOURCED_FREEZER_PATH,
946                                                 NULL,
947                                                 G_DBUS_SIGNAL_FLAGS_NONE,
948                                                 __on_receive_suspend_signal,
949                                                 NULL,
950                                                 NULL);
951         if (__suspend_dbus_handler_initialized == 0) {
952                 _ERR("g_dbus_connection_signal_subscribe() is failed.");
953                 return -1;
954         }
955
956         _DBG("[__SUSPEND__] suspend signal initialized");
957
958         return 0;
959 }
960
961 static void __fini_suspend_dbus_handler(void)
962 {
963         if (__bus == NULL)
964                 return;
965
966         if (__suspend_dbus_handler_initialized) {
967                 g_dbus_connection_signal_unsubscribe(__bus,
968                                 __suspend_dbus_handler_initialized);
969                 __suspend_dbus_handler_initialized = 0;
970         }
971
972         g_object_unref(__bus);
973         __bus = NULL;
974 }
975
976 static gboolean __init_suspend(gpointer data)
977 {
978         __init_suspend_dbus_handler();
979         return G_SOURCE_REMOVE;
980 }
981
982 static int __get_locale_resource_dir(char *locale_dir, int size)
983 {
984         const char *res_path;
985
986         res_path = aul_get_app_resource_path();
987         if (res_path == NULL) {
988                 _ERR("Failed to get resource path");
989                 return -1;
990         }
991
992         snprintf(locale_dir, size, "%s" PATH_LOCALE, res_path);
993         return 0;
994 }
995
996 static int __get_app_name(const char *appid, char **name)
997 {
998         char *name_token = NULL;
999
1000         if (appid == NULL)
1001                 return -1;
1002
1003         /* com.vendor.name -> name */
1004         name_token = strrchr(appid, '.');
1005         if (name_token == NULL) {
1006                 *name = strdup(appid);
1007                 return 0;
1008         }
1009
1010         name_token++;
1011
1012         *name = strdup(name_token);
1013         if (*name == NULL)
1014                 return -1;
1015
1016         return 0;
1017 }
1018
1019 static int __set_i18n(const char *domain, const char *dir)
1020 {
1021         char *r;
1022
1023         if (domain == NULL) {
1024                 errno = EINVAL;
1025                 return -1;
1026         }
1027
1028         if (dir) {
1029                 if (__locale_dir)
1030                         free(__locale_dir);
1031                 __locale_dir = strdup(dir);
1032         }
1033
1034         __update_lang();
1035         __update_region();
1036
1037         r = setlocale(LC_ALL, "");
1038         /* if locale is not set properly, try to set "en_US" again */
1039         if (r == NULL) {
1040                 r = setlocale(LC_ALL, "en_US.UTF-8");
1041                 if (r != NULL)
1042                         _DBG("*****appcore setlocale=%s\n", r);
1043         }
1044         if (r == NULL) {
1045                 _ERR("appcore: setlocale() error");
1046                 _DBG("*****appcore setlocale=\"C\"");
1047                 setenv("LC_ALL", "C", 1);
1048                 r = setlocale(LC_ALL, "");
1049                 if (r == NULL)
1050                         _ERR("failed to setlocale");
1051         }
1052
1053         r = bindtextdomain(domain, dir);
1054         if (r == NULL)
1055                 _ERR("appcore: bindtextdomain() error");
1056
1057         r = textdomain(domain);
1058         if (r == NULL)
1059                 _ERR("appcore: textdomain() error");
1060
1061         return 0;
1062 }
1063
1064 EXPORT_API int appcore_base_on_set_i18n(void)
1065 {
1066         int r;
1067         char locale_dir[PATH_MAX];
1068         char appid[PATH_MAX];
1069         char *name = NULL;
1070
1071         r = aul_app_get_appid_bypid(getpid(), appid, PATH_MAX);
1072         if (r < 0) {
1073                 _ERR("Failed to get application ID - pid(%d)", getpid());
1074                 return -1;
1075         }
1076
1077         r = __get_app_name(appid, &name);
1078         if (r < 0)
1079                 return -1;
1080
1081         r = __get_locale_resource_dir(locale_dir, sizeof(locale_dir));
1082         if (r < 0) {
1083                 free(name);
1084                 return -1;
1085         }
1086
1087         r = __set_i18n(name, locale_dir);
1088         if (r < 0) {
1089                 free(name);
1090                 return -1;
1091         }
1092
1093         free(name);
1094
1095         return 0;
1096 }
1097
1098 EXPORT_API int appcore_base_set_i18n(const char *domain_name, const char *dir_name)
1099 {
1100         return __set_i18n(domain_name, dir_name);
1101 }
1102
1103 static void __set_default_events(void)
1104 {
1105         int r;
1106
1107         vconf_notify_key_changed(VCONFKEY_LANGSET, __on_language_change, NULL);
1108         r = vconf_notify_key_changed(VCONFKEY_REGIONFORMAT, __on_region_change, NULL);
1109         if (r == 0)
1110                 vconf_notify_key_changed(VCONFKEY_REGIONFORMAT_TIME1224, __on_region_change, NULL);
1111         vconf_notify_key_changed(VCONFKEY_SYSMAN_LOW_MEMORY, __on_low_memory, NULL);
1112 }
1113
1114 static void __unset_default_events(void)
1115 {
1116         int r;
1117
1118         vconf_ignore_key_changed(VCONFKEY_LANGSET, __on_language_change);
1119         r = vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT, __on_region_change);
1120         if (r == 0)
1121                 vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT_TIME1224, __on_region_change);
1122         vconf_ignore_key_changed(VCONFKEY_SYSMAN_LOW_MEMORY, __on_low_memory);
1123 }
1124
1125 EXPORT_API int appcore_base_init(appcore_base_ops ops, int argc, char **argv, void *data)
1126 {
1127         int i;
1128         int r;
1129
1130         __context.ops = ops;
1131         __context.argc = argc;
1132         __context.argv = argv;
1133         __context.data = data;
1134         __context.tid = 0;
1135         __context.suspended_state = false;
1136         __context.allowed_bg = false;
1137
1138         traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:OPS_INIT");
1139         if (__context.ops.init)
1140                 __context.ops.init(argc, argv, data);
1141         traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1142
1143         if (TIZEN_FEATURE_BACKGROUND_MANAGEMENT)
1144                 g_idle_add(__init_suspend, NULL);
1145
1146         traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:SET_SYSTEM_EVENT");
1147         if (!__context.dirty) {
1148                 __context.dirty = true;
1149
1150                 for (i = APPCORE_BASE_EVENT_START + 1; i < APPCORE_BASE_EVENT_MAX; i++) {
1151                         if (__exist_callback(i)) {
1152                                 if (__context.ops.set_event)
1153                                         __context.ops.set_event(i, __context.data);
1154                         }
1155                 }
1156         }
1157         traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1158
1159         traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:VERIFY_LANG");
1160         __verify_language();
1161         traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1162         traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:SET_DEFAULT_EVENTS");
1163         __set_default_events();
1164         traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1165         if (__context.ops.set_i18n)
1166                 __context.ops.set_i18n(__context.data);
1167         aul_app_lifecycle_update_state(AUL_APP_LIFECYCLE_STATE_INITIALIZED);
1168
1169         if (__context.ops.create) {
1170                 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:CREATE");
1171                 r = __context.ops.create(__context.data);
1172                 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1173                 aul_app_lifecycle_update_state(AUL_APP_LIFECYCLE_STATE_CREATED);
1174                 if (r < 0) {
1175                         aul_status_update(STATUS_DYING);
1176                         return 0;
1177                 }
1178         }
1179
1180         if (__context.ops.run)
1181                 __context.ops.run(__context.data);
1182
1183         return 0;
1184 }
1185
1186 EXPORT_API void appcore_base_fini(void)
1187 {
1188         int i;
1189
1190         aul_status_update(STATUS_DYING);
1191         appcore_watchdog_disable();
1192         if (__context.ops.terminate) {
1193                 aul_app_lifecycle_update_state(AUL_APP_LIFECYCLE_STATE_DESTROYED);
1194                 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:TERMINATE");
1195                 __context.ops.terminate(__context.data);
1196                 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1197         }
1198
1199         for (i = APPCORE_BASE_EVENT_START + 1; i < APPCORE_BASE_EVENT_MAX; i++) {
1200                 if (__exist_callback(i)) {
1201                         if (__context.ops.unset_event)
1202                                 __context.ops.unset_event(i, __context.data);
1203                 }
1204         }
1205
1206         appcore_base_control_fini();
1207         __unset_default_events();
1208
1209         if (__context.sid) {
1210                 g_source_remove(__context.sid);
1211                 __context.sid = 0;
1212         }
1213
1214         __remove_suspend_timer();
1215
1216         g_list_free_full(__events, free);
1217         __events = NULL;
1218
1219         if (TIZEN_FEATURE_BACKGROUND_MANAGEMENT)
1220                 __fini_suspend_dbus_handler();
1221
1222         if (__locale_dir) {
1223                 free(__locale_dir);
1224                 __locale_dir = NULL;
1225         }
1226
1227         __context.dirty = false;
1228
1229         if (__context.ops.finish)
1230                 __context.ops.finish();
1231 }
1232
1233 EXPORT_API int appcore_base_flush_memory(void)
1234 {
1235         if (__context.ops.trim_memory)
1236                 __context.ops.trim_memory(__context.data);
1237
1238         return 0;
1239 }
1240
1241 EXPORT_API int appcore_base_on_receive(aul_type type, bundle *b)
1242 {
1243         const char *bg;
1244         int dummy = 0;
1245
1246         switch (type) {
1247         case AUL_START:
1248                 _DBG("[APP %d]     AUL event: AUL_START", getpid());
1249                 if (TIZEN_FEATURE_BACKGROUND_MANAGEMENT) {
1250                         bg = bundle_get_val(b, AUL_K_ALLOWED_BG);
1251                         if (bg && !strcmp(bg, "ALLOWED_BG")) {
1252                                 _DBG("[__SUSPEND__] allowed background");
1253                                 __context.allowed_bg = true;
1254                                 __remove_suspend_timer();
1255                         }
1256                 }
1257
1258                 if (__context.ops.control) {
1259                         traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:RESET");
1260                         __context.ops.control(b, __context.data);
1261                         traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1262                 }
1263                 break;
1264         case AUL_RESUME:
1265                 _DBG("[APP %d]     AUL event: AUL_RESUME", getpid());
1266                 if (TIZEN_FEATURE_BACKGROUND_MANAGEMENT) {
1267                         bg = bundle_get_val(b, AUL_K_ALLOWED_BG);
1268                         if (bg && !strcmp(bg, "ALLOWED_BG")) {
1269                                 _DBG("[__SUSPEND__] allowed background");
1270                                 __context.allowed_bg = true;
1271                                 __remove_suspend_timer();
1272                         }
1273                 }
1274                 break;
1275         case AUL_TERMINATE:
1276                 _DBG("[APP %d]     AUL event: AUL_TERMINATE", getpid());
1277                 aul_status_update(STATUS_DYING);
1278                 if (!__context.allowed_bg)
1279                         __remove_suspend_timer();
1280
1281                 if (__context.ops.exit)
1282                         __context.ops.exit(__context.data);
1283                 break;
1284         case AUL_TERMINATE_INST:
1285         case AUL_TERMINATE_BG_INST:
1286         case AUL_TERMINATE_BGAPP:
1287                 _DBG("[APP %d]     AUL event: %d", getpid(), type);
1288                 if (!__context.allowed_bg)
1289                         __remove_suspend_timer();
1290                 break;
1291         case AUL_WAKE:
1292                 _DBG("[APP %d]     AUL event: AUL_WAKE", getpid());
1293                 if (TIZEN_FEATURE_BACKGROUND_MANAGEMENT) {
1294                         if (!__context.allowed_bg &&
1295                                         __context.suspended_state) {
1296                                 int suspend = APPCORE_BASE_SUSPENDED_STATE_DID_EXIT_FROM_SUSPEND;
1297                                 __remove_suspend_timer();
1298                                 __invoke_callback((void *)&suspend, APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE);
1299                                 __context.suspended_state = false;
1300                         }
1301                 }
1302                 break;
1303         case AUL_SUSPEND:
1304                 _DBG("[APP %d]     AUL event: AUL_SUSPEND", getpid());
1305                 if (TIZEN_FEATURE_BACKGROUND_MANAGEMENT) {
1306                         if (!__context.allowed_bg &&
1307                                         !__context.suspended_state) {
1308                                 __remove_suspend_timer();
1309                                 __flush_memory(NULL);
1310                         }
1311                 }
1312                 break;
1313         case AUL_UPDATE_REQUESTED:
1314                 _DBG("[APP %d]     AUL event: AUL_UPDATE_REQUESTED", getpid());
1315                 __invoke_callback((void *)&dummy, APPCORE_BASE_EVENT_UPDATE_REQUESTED);
1316                 break;
1317         default:
1318                 _DBG("[APP %d]     AUL event: %d", getpid(), type);
1319                 /* do nothing */
1320                 break;
1321         }
1322
1323         return 0;
1324 }
1325
1326 EXPORT_API int appcore_base_on_create(void)
1327 {
1328         int r;
1329
1330         r = aul_launch_init(__context.ops.receive, __context.data);
1331         if (r < 0 && r != AUL_R_ECANCELED) {
1332                 _ERR("Aul init failed: %d", r);
1333                 return -1;
1334         }
1335
1336         r = aul_launch_argv_handler(__context.argc, __context.argv);
1337         if (r < 0) {
1338                 _ERR("Aul argv handler failed: %d", r);
1339                 return -1;
1340         }
1341
1342         return 0;
1343 }
1344
1345 EXPORT_API int appcore_base_on_control(bundle *b)
1346 {
1347         appcore_base_control_invoke(b);
1348
1349         return 0;
1350 }
1351
1352 EXPORT_API int appcore_base_on_terminate()
1353 {
1354         aul_finalize();
1355
1356         return 0;
1357 }
1358
1359 EXPORT_API void appcore_base_on_set_event(enum appcore_base_event event)
1360 {
1361         switch (event) {
1362         case APPCORE_BASE_EVENT_LOW_BATTERY:
1363                 vconf_notify_key_changed(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, __on_low_battery, NULL);
1364                 break;
1365         case APPCORE_BASE_EVENT_DEVICE_ORIENTATION_CHANGED:
1366                 __register_rotation_changed_event();
1367                 break;
1368         case APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE:
1369                 break;
1370
1371         default:
1372                 break;
1373         }
1374
1375 }
1376
1377 EXPORT_API void appcore_base_on_unset_event(enum appcore_base_event event)
1378 {
1379         switch (event) {
1380         case APPCORE_BASE_EVENT_LOW_BATTERY:
1381                 vconf_ignore_key_changed(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, __on_low_battery);
1382                 break;
1383         case APPCORE_BASE_EVENT_DEVICE_ORIENTATION_CHANGED:
1384                 __unregister_rotation_changed_event();
1385                 break;
1386         case APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE:
1387                 break;
1388         default:
1389                 break;
1390         }
1391 }
1392
1393 EXPORT_API int appcore_base_on_trim_memory(void)
1394 {
1395         int (*sqlite3_free_heap_memory)(int);
1396
1397         sqlite3_free_heap_memory = dlsym(RTLD_DEFAULT,
1398                         "sqlite3_release_memory");
1399         if (sqlite3_free_heap_memory)
1400                 sqlite3_free_heap_memory(SQLITE_FLUSH_MAX);
1401
1402         malloc_trim(0);
1403
1404         return 0;
1405 }
1406
1407 EXPORT_API appcore_base_event_h appcore_base_add_event(enum appcore_base_event event,
1408                 appcore_base_event_cb cb, void *data)
1409 {
1410         appcore_base_event_node *node;
1411
1412         if (__context.dirty && !__exist_callback(event)) {
1413                 if (__context.ops.set_event)
1414                         __context.ops.set_event(event, __context.data);
1415         }
1416
1417         node = malloc(sizeof(appcore_base_event_node));
1418
1419         if (node == NULL)
1420                 return NULL;
1421
1422         node->cb = cb;
1423         node->type = event;
1424         node->data = data;
1425
1426         if (event == APPCORE_BASE_EVENT_LANG_CHANGE ||
1427                         event == APPCORE_BASE_EVENT_REGION_CHANGE)
1428                 node->prev_event = NULL;
1429         else
1430                 node->prev_event = GINT_TO_POINTER(-1);
1431         __events = g_list_append(__events, node);
1432
1433         return node;
1434 }
1435
1436 EXPORT_API int appcore_base_remove_event(appcore_base_event_h handle)
1437 {
1438         appcore_base_event_node *node = handle;
1439         enum appcore_base_event event;
1440
1441         if (!node || !g_list_find(__events, node))
1442                 return -1;
1443
1444         event = node->type;
1445         __events = g_list_remove(__events, node);
1446         __unset_prev_event(&node->prev_event, event);
1447         free(node);
1448         if (__context.dirty && !__exist_callback(event)) {
1449                 if (__context.ops.unset_event)
1450                         __context.ops.unset_event(event, __context.data);
1451         }
1452
1453         return 0;
1454 }
1455
1456 EXPORT_API int appcore_base_raise_event(void *event, enum appcore_base_event type)
1457 {
1458         __invoke_callback(event, type);
1459         return 0;
1460 }
1461
1462 EXPORT_API int appcore_base_get_rotation_state(enum appcore_base_rm *curr)
1463 {
1464         if (curr == NULL)
1465                 return -1;
1466
1467         if (!__rotation.ref)
1468                 return -1;
1469
1470         *curr = __rotation.rm;
1471         return 0;
1472 }
1473
1474 EXPORT_API bool appcore_base_is_bg_allowed(void)
1475 {
1476         return __context.allowed_bg;
1477 }
1478
1479 EXPORT_API bool appcore_base_is_suspended(void)
1480 {
1481         return __context.suspended_state;
1482 }
1483
1484 EXPORT_API void appcore_base_toggle_suspended_state(void)
1485 {
1486         __context.suspended_state ^= __context.suspended_state;
1487 }
1488
1489 EXPORT_API void appcore_base_exit(void)
1490 {
1491         aul_status_update(STATUS_DYING);
1492         if (__context.ops.exit)
1493                 __context.ops.exit(__context.data);
1494 }
1495
1496 EXPORT_API void appcore_base_add_suspend_timer(void)
1497 {
1498         __add_suspend_timer();
1499 }
1500
1501 EXPORT_API void appcore_base_remove_suspend_timer(void)
1502 {
1503         __remove_suspend_timer();
1504 }
1505
1506 EXPORT_API void appcore_base_set_display_state(int display_state)
1507 {
1508         __context.display_state = display_state;
1509 }
1510
1511 EXPORT_API int appcore_base_get_display_state(void)
1512 {
1513         return __context.display_state;
1514 }
1515
1516 static int __on_receive(aul_type type, bundle *b, void *data)
1517 {
1518         return appcore_base_on_receive(type, b);
1519 }
1520
1521 static int __on_create(void *data)
1522 {
1523         return appcore_base_on_create();
1524 }
1525
1526 static int __on_control(bundle *b, void *data)
1527 {
1528         return appcore_base_on_control(b);
1529 }
1530
1531 static int __on_terminate(void *data)
1532 {
1533         return appcore_base_on_terminate();
1534 }
1535
1536 static int __on_set_i18n(void *data)
1537 {
1538         return appcore_base_on_set_i18n();
1539 }
1540
1541 static void __on_set_event(enum appcore_base_event event, void *data)
1542 {
1543         appcore_base_on_set_event(event);
1544 }
1545
1546 static void __on_unset_event(enum appcore_base_event event, void *data)
1547 {
1548         appcore_base_on_unset_event(event);
1549 }
1550
1551 static void __on_trim_memory(void *data)
1552 {
1553         appcore_base_on_trim_memory();
1554 }
1555
1556 EXPORT_API appcore_base_ops appcore_base_get_default_ops(void)
1557 {
1558         appcore_base_ops ops;
1559
1560         ops.create = __on_create;
1561         ops.control = __on_control;
1562         ops.terminate = __on_terminate;
1563         ops.receive = __on_receive;
1564         ops.set_i18n = __on_set_i18n;
1565         ops.init = NULL;
1566         ops.finish = NULL;
1567         ops.run = NULL;
1568         ops.exit = NULL;
1569         ops.set_event = __on_set_event;
1570         ops.unset_event = __on_unset_event;
1571         ops.trim_memory = __on_trim_memory;
1572
1573         return ops;
1574 }