2 * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
24 #include <sys/types.h>
30 #include <linux/limits.h>
37 #include <aul_app_lifecycle.h>
38 #include <bundle_internal.h>
39 #include <sensor_internal.h>
41 #include <system_info.h>
43 #include "appcore_base.h"
44 #include "appcore_base_private.h"
45 #include "appcore_watchdog.h"
46 #include "appcore_base_control.h"
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)
54 typedef struct _appcore_base_context {
65 } appcore_base_context;
67 typedef struct _appcore_base_event_node {
69 appcore_base_event_cb cb;
72 } appcore_base_event_node;
74 typedef struct _appcore_base_rotation {
78 enum appcore_base_rm rm;
81 } appcore_base_rotation;
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;
95 appcore_base_tizen_profile_t appcore_base_get_tizen_profile(void)
97 static appcore_base_tizen_profile_t profile = TIZEN_PROFILE_UNKNOWN;
98 char *profile_name = NULL;
100 if (__builtin_expect(profile != TIZEN_PROFILE_UNKNOWN, 1))
103 system_info_get_platform_string("http://tizen.org/feature/profile",
105 if (profile_name == NULL)
108 switch (*profile_name) {
111 profile = TIZEN_PROFILE_MOBILE;
115 profile = TIZEN_PROFILE_WEARABLE;
119 profile = TIZEN_PROFILE_TV;
123 profile = TIZEN_PROFILE_IVI;
126 profile = TIZEN_PROFILE_COMMON;
134 static int __compare_event(void *prev_event, void *curr_event, int 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)
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))
167 static void __unset_prev_event(void **prev_event, int type)
169 if (type == APPCORE_BASE_EVENT_LANG_CHANGE ||
170 type == APPCORE_BASE_EVENT_REGION_CHANGE)
175 static void __set_prev_event(void **prev_event, void *curr_event, int 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);
188 case APPCORE_BASE_EVENT_LANG_CHANGE:
189 case APPCORE_BASE_EVENT_REGION_CHANGE:
190 curr_strval = curr_event;
192 *prev_event = strdup(curr_strval);
199 static void __invoke_callback(void *event, int type)
201 GList *iter = __events;
204 appcore_base_event_node *node = iter->data;
205 iter = g_list_next(iter);
207 if (node->type != type)
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);
218 static bool __exist_callback(int type)
220 GList *iter = __events;
223 appcore_base_event_node *node = iter->data;
225 if (node->type == type)
228 iter = g_list_next(iter);
234 static enum appcore_base_rm __get_rm(sensor_data_t data)
237 enum appcore_base_rm rm;
239 if (data.value_count <= 0) {
240 _ERR("Failed to get sensor data");
241 return APPCORE_BASE_RM_UNKNOWN;
244 event = data.values[0];
246 case AUTO_ROTATION_DEGREE_0:
247 rm = APPCORE_BASE_RM_PORTRAIT_NORMAL;
249 case AUTO_ROTATION_DEGREE_90:
250 rm = APPCORE_BASE_RM_LANDSCAPE_NORMAL;
252 case AUTO_ROTATION_DEGREE_180:
253 rm = APPCORE_BASE_RM_PORTRAIT_REVERSE;
255 case AUTO_ROTATION_DEGREE_270:
256 rm = APPCORE_BASE_RM_LANDSCAPE_REVERSE;
259 rm = APPCORE_BASE_RM_UNKNOWN;
266 static void __lock_cb(keynode_t *node, void *user_data)
270 enum appcore_base_rm rm;
272 __rotation.lock = !vconf_keynode_get_bool(node);
273 if (__rotation.lock) {
274 _DBG("Rotation locked");
275 rm = APPCORE_BASE_RM_PORTRAIT_NORMAL;
277 _DBG("Rotation unlocked");
278 r = sensord_get_data(__rotation.conn, AUTO_ROTATION_SENSOR, &data);
280 _ERR("Failed to get sensor data");
285 if (rm == APPCORE_BASE_RM_UNKNOWN) {
286 _ERR("Unknown mode");
291 if (__rotation.rm == rm)
294 _DBG("Rotation: %d -> %d", __rotation.rm, rm);
296 __invoke_callback((void *)&__rotation.rm, APPCORE_BASE_EVENT_DEVICE_ORIENTATION_CHANGED);
299 static void __auto_rotation_changed_cb(sensor_t sensor, unsigned int event_type,
300 sensor_data_t *data, void *user_data)
302 enum appcore_base_rm rm;
310 if (event_type != AUTO_ROTATION_CHANGE_STATE_EVENT)
313 rm = __get_rm(*data);
314 if (rm == APPCORE_BASE_RM_UNKNOWN) {
315 _ERR("Unknown mode");
319 _DBG("Rotation: %d -> %d", __rotation.rm, rm);
321 __invoke_callback((void *)&__rotation.rm, APPCORE_BASE_EVENT_DEVICE_ORIENTATION_CHANGED);
324 static void __fini_rotation(void)
326 if (!__rotation.initialized)
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);
335 __rotation.initialized = false;
338 static void __init_rotation(void)
344 if (__rotation.initialized)
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");
354 r = sensord_register_event(__rotation.conn, AUTO_ROTATION_CHANGE_STATE_EVENT,
355 SENSOR_INTERVAL_NORMAL, 0, __auto_rotation_changed_cb, NULL);
357 _ERR("Failed to register auto rotation change event");
358 sensord_disconnect(__rotation.conn);
362 r = sensord_start(__rotation.conn, 0);
364 _ERR("Failed to start sensord");
365 sensord_unregister_event(__rotation.conn, AUTO_ROTATION_CHANGE_STATE_EVENT);
366 sensord_disconnect(__rotation.conn);
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);
374 __rotation.lock = !lock;
375 __rotation.initialized = true;
378 static void __charger_status_changed_cb(keynode_t *keynode, void *user_data)
380 if (TIZEN_FEATURE_CHARGER_STATUS) {
381 __rotation.charger_status = vconf_keynode_get_int(keynode);
382 if (__rotation.charger_status) {
389 _DBG("charger status(%d)", __rotation.charger_status);
393 static void __unregister_rotation_changed_event(void)
399 if (__rotation.ref > 1)
403 if (TIZEN_FEATURE_CHARGER_STATUS) {
404 vconf_ignore_key_changed(VCONFKEY_SYSMAN_CHARGER_STATUS,
405 __charger_status_changed_cb);
411 static void __register_rotation_changed_event(void)
413 if (__rotation.ref) {
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)
432 static void __on_low_memory(keynode_t *key, void *data)
436 val = vconf_keynode_get_int(key);
438 if (val >= VCONFKEY_SYSMAN_LOW_MEMORY_SOFT_WARNING) {
439 __invoke_callback(&val, APPCORE_BASE_EVENT_LOW_MEMORY);
444 static void __on_low_battery(keynode_t *key, void *data)
448 val = vconf_keynode_get_int(key);
450 if (val <= VCONFKEY_SYSMAN_BAT_CRITICAL_LOW)
451 __invoke_callback(&val, APPCORE_BASE_EVENT_LOW_BATTERY);
454 static void __destroy_lang_info(gpointer data)
456 struct lang_info_s *info = (struct lang_info_s *)data;
462 g_list_free_full(info->list, free);
468 static struct lang_info_s *__create_lang_info(const char *lang)
470 struct lang_info_s *info;
472 info = calloc(1, sizeof(struct lang_info_s));
474 _ERR("Out of memory");
478 info->parent = strdup(lang);
479 if (info->parent == NULL) {
480 _ERR("Out of memory");
488 static gint __compare_langs(gconstpointer a, gconstpointer b)
496 static char *__get_string_before(const char *str, const char *delim)
502 dup_str = strdup(str);
506 token = strtok(dup_str, delim);
512 new_str = strdup(token);
518 static GHashTable *__get_lang_table(void)
522 struct dirent *dentry;
524 struct stat stat_buf;
527 struct lang_info_s *info;
529 if (__locale_dir == NULL || __locale_dir[0] == '\0')
532 table = g_hash_table_new_full(g_str_hash, g_str_equal,
533 NULL, __destroy_lang_info);
535 _ERR("Out of memory");
539 dp = opendir(__locale_dir);
541 g_hash_table_destroy(table);
545 while ((dentry = readdir(dp)) != NULL) {
546 if (!strcmp(dentry->d_name, ".") ||
547 !strcmp(dentry->d_name, ".."))
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))
556 parent_lang = __get_string_before(dentry->d_name, "_");
557 if (parent_lang == NULL) {
558 _ERR("Out of memory");
562 info = g_hash_table_lookup(table, parent_lang);
564 info = __create_lang_info(parent_lang);
569 g_hash_table_insert(table, info->parent, info);
571 info->list = g_list_append(info->list, strdup(dentry->d_name));
579 static GList *__append_langs(const char *lang, GList *list, GHashTable *table)
581 struct lang_info_s *info;
583 char *parent_lang = NULL;
589 list = g_list_append(list, strdup(lang));
591 extract_lang = __get_string_before(lang, ".");
592 if (extract_lang == NULL)
595 found = g_list_find_custom(list, extract_lang, __compare_langs);
597 list = g_list_remove_link(list, found);
598 list = g_list_concat(list, found);
602 parent_lang = __get_string_before(extract_lang, "_");
603 if (parent_lang == NULL)
606 info = g_hash_table_lookup(table, parent_lang);
610 found = g_list_find_custom(info->list, extract_lang, __compare_langs);
612 info->list = g_list_remove_link(info->list, found);
613 list = g_list_concat(list, found);
617 found = g_list_find_custom(info->list, parent_lang, __compare_langs);
619 info->list = g_list_remove_link(info->list, found);
620 list = g_list_concat(list, found);
624 found = g_list_first(info->list);
626 info->list = g_list_remove_link(info->list, found);
627 list = g_list_concat(list, found);
639 static GList *__split_language(const char *lang)
645 dup_lang = strdup(lang);
646 if (dup_lang == NULL) {
647 _ERR("Out of memory");
651 token = strtok(dup_lang, ":");
652 while (token != NULL) {
653 list = g_list_append(list, strdup(token));
654 token = strtok(NULL, ":");
661 static GList *__append_default_langs(GList *list)
663 const char *langs[] = {"en_US", "en_GB", "en"};
667 for (i = 0; i < (sizeof(langs) / sizeof(langs[0])); i++) {
668 found = g_list_find_custom(list, langs[i], __compare_langs);
670 list = g_list_append(list, strdup(langs[i]));
676 static char *__get_language(const char *lang)
680 GList *lang_list = NULL;
683 char buf[LINE_MAX] = {'\0'};
686 list = __split_language(lang);
690 table = __get_lang_table();
692 g_list_free_full(list, free);
696 iter = g_list_first(list);
698 language = (char *)iter->data;
699 lang_list = __append_langs(language, lang_list, table);
700 iter = g_list_next(iter);
702 g_list_free_full(list, free);
703 g_hash_table_destroy(table);
705 lang_list = __append_default_langs(lang_list);
706 iter = g_list_first(lang_list);
708 language = (char *)iter->data;
710 if (buf[0] == '\0') {
711 snprintf(buf, sizeof(buf), "%s", language);
713 n = sizeof(buf) - strlen(buf) - 1;
714 strncat(buf, ":", n);
715 n = sizeof(buf) - strlen(buf) - 1;
716 strncat(buf, language, n);
719 iter = g_list_next(iter);
721 g_list_free_full(lang_list, free);
726 static void __update_lang(void)
732 lang = vconf_get_str(VCONFKEY_LANGSET);
734 /* TODO: Use VCONFKEY_SETAPPL_LANGUAGES key */
735 language = __get_language(lang);
737 _DBG("*****language(%s)", language);
738 setenv("LANGUAGE", language, 1);
741 setenv("LANGUAGE", lang, 1);
743 setenv("LANG", lang, 1);
744 setenv("LC_MESSAGES", lang, 1);
745 setenv("LC_ALL", lang, 1);
746 r = setlocale(LC_ALL, "");
748 r = setlocale(LC_ALL, "en_US.UTF-8");
750 _DBG("*****appcore setlocale=%s\n", r);
752 _DBG("*****appcore setlocale=\"C\"");
753 setenv("LC_ALL", "C", 1);
754 r = setlocale(LC_ALL, "");
756 _ERR("failed to setlocale");
763 static void __update_region(void)
768 region = vconf_get_str(VCONFKEY_REGIONFORMAT);
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, "");
783 _DBG("*****appcore setlocale=%s\n", r);
785 _DBG("*****appcore setlocale=\"C\"");
786 setenv("LC_ALL", "C", 1);
787 r = setlocale(LC_ALL, "");
789 _ERR("failed to setlocale");
796 static void __on_language_change(keynode_t *key, void *data)
801 g_source_remove(__context.sid);
805 val = vconf_keynode_get_str(key);
808 __invoke_callback((void *)val, APPCORE_BASE_EVENT_LANG_CHANGE);
811 static void __on_region_change(keynode_t *key, void *data)
816 name = vconf_keynode_get_name(key);
820 if (strcmp(name, VCONFKEY_REGIONFORMAT) &&
821 strcmp(name, VCONFKEY_REGIONFORMAT_TIME1224))
824 val = vconf_get_str(VCONFKEY_REGIONFORMAT);
827 __invoke_callback((void *)val, APPCORE_BASE_EVENT_REGION_CHANGE);
831 static gboolean __invoke_lang_change(gpointer data)
837 lang = getenv("LANG");
839 return G_SOURCE_REMOVE;
841 __invoke_callback((void *)lang, APPCORE_BASE_EVENT_LANG_CHANGE);
843 return G_SOURCE_REMOVE;
846 static void __verify_language(void)
849 const char *env_lang;
851 env_lang = getenv("LANG");
855 lang = vconf_get_str(VCONFKEY_LANGSET);
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);
867 static gboolean __flush_memory(gpointer data)
869 int suspend = APPCORE_BASE_SUSPENDED_STATE_WILL_ENTER_SUSPEND;
871 if (__context.ops.trim_memory)
872 __context.ops.trim_memory(__context.data);
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;
885 static void __add_suspend_timer(void)
887 __context.tid = g_timeout_add_seconds(5, __flush_memory, NULL);
890 static void __remove_suspend_timer(void)
892 if (__context.tid > 0) {
893 g_source_remove(__context.tid);
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,
906 gint suspend = APPCORE_BASE_SUSPENDED_STATE_DID_EXIT_FROM_SUSPEND;
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();
923 static int __init_suspend_dbus_handler(void)
927 if (__suspend_dbus_handler_initialized)
931 __bus = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
933 _ERR("Failed to connect to the D-BUS daemon: %s",
940 __suspend_dbus_handler_initialized = g_dbus_connection_signal_subscribe(
943 RESOURCED_FREEZER_INTERFACE,
944 RESOURCED_FREEZER_SIGNAL,
945 RESOURCED_FREEZER_PATH,
947 G_DBUS_SIGNAL_FLAGS_NONE,
948 __on_receive_suspend_signal,
951 if (__suspend_dbus_handler_initialized == 0) {
952 _ERR("g_dbus_connection_signal_subscribe() is failed.");
956 _DBG("[__SUSPEND__] suspend signal initialized");
961 static void __fini_suspend_dbus_handler(void)
966 if (__suspend_dbus_handler_initialized) {
967 g_dbus_connection_signal_unsubscribe(__bus,
968 __suspend_dbus_handler_initialized);
969 __suspend_dbus_handler_initialized = 0;
972 g_object_unref(__bus);
976 static gboolean __init_suspend(gpointer data)
978 __init_suspend_dbus_handler();
979 return G_SOURCE_REMOVE;
982 static int __get_locale_resource_dir(char *locale_dir, int size)
984 const char *res_path;
986 res_path = aul_get_app_resource_path();
987 if (res_path == NULL) {
988 _ERR("Failed to get resource path");
992 snprintf(locale_dir, size, "%s" PATH_LOCALE, res_path);
996 static int __get_app_name(const char *appid, char **name)
998 char *name_token = NULL;
1003 /* com.vendor.name -> name */
1004 name_token = strrchr(appid, '.');
1005 if (name_token == NULL) {
1006 *name = strdup(appid);
1012 *name = strdup(name_token);
1019 static int __set_i18n(const char *domain, const char *dir)
1023 if (domain == NULL) {
1031 __locale_dir = strdup(dir);
1037 r = setlocale(LC_ALL, "");
1038 /* if locale is not set properly, try to set "en_US" again */
1040 r = setlocale(LC_ALL, "en_US.UTF-8");
1042 _DBG("*****appcore setlocale=%s\n", r);
1045 _ERR("appcore: setlocale() error");
1046 _DBG("*****appcore setlocale=\"C\"");
1047 setenv("LC_ALL", "C", 1);
1048 r = setlocale(LC_ALL, "");
1050 _ERR("failed to setlocale");
1053 r = bindtextdomain(domain, dir);
1055 _ERR("appcore: bindtextdomain() error");
1057 r = textdomain(domain);
1059 _ERR("appcore: textdomain() error");
1064 EXPORT_API int appcore_base_on_set_i18n(void)
1067 char locale_dir[PATH_MAX];
1068 char appid[PATH_MAX];
1071 r = aul_app_get_appid_bypid(getpid(), appid, PATH_MAX);
1073 _ERR("Failed to get application ID - pid(%d)", getpid());
1077 r = __get_app_name(appid, &name);
1081 r = __get_locale_resource_dir(locale_dir, sizeof(locale_dir));
1087 r = __set_i18n(name, locale_dir);
1098 EXPORT_API int appcore_base_set_i18n(const char *domain_name, const char *dir_name)
1100 return __set_i18n(domain_name, dir_name);
1103 static void __set_default_events(void)
1107 vconf_notify_key_changed(VCONFKEY_LANGSET, __on_language_change, NULL);
1108 r = vconf_notify_key_changed(VCONFKEY_REGIONFORMAT, __on_region_change, NULL);
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);
1114 static void __unset_default_events(void)
1118 vconf_ignore_key_changed(VCONFKEY_LANGSET, __on_language_change);
1119 r = vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT, __on_region_change);
1121 vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT_TIME1224, __on_region_change);
1122 vconf_ignore_key_changed(VCONFKEY_SYSMAN_LOW_MEMORY, __on_low_memory);
1125 EXPORT_API int appcore_base_init(appcore_base_ops ops, int argc, char **argv, void *data)
1130 __context.ops = ops;
1131 __context.argc = argc;
1132 __context.argv = argv;
1133 __context.data = data;
1135 __context.suspended_state = false;
1136 __context.allowed_bg = false;
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);
1143 if (TIZEN_FEATURE_BACKGROUND_MANAGEMENT)
1144 g_idle_add(__init_suspend, NULL);
1146 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:SET_SYSTEM_EVENT");
1147 if (!__context.dirty) {
1148 __context.dirty = true;
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);
1157 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
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);
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);
1175 aul_status_update(STATUS_DYING);
1180 if (__context.ops.run)
1181 __context.ops.run(__context.data);
1186 EXPORT_API void appcore_base_fini(void)
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);
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);
1206 appcore_base_control_fini();
1207 __unset_default_events();
1209 if (__context.sid) {
1210 g_source_remove(__context.sid);
1214 __remove_suspend_timer();
1216 g_list_free_full(__events, free);
1219 if (TIZEN_FEATURE_BACKGROUND_MANAGEMENT)
1220 __fini_suspend_dbus_handler();
1224 __locale_dir = NULL;
1227 __context.dirty = false;
1229 if (__context.ops.finish)
1230 __context.ops.finish();
1233 EXPORT_API int appcore_base_flush_memory(void)
1235 if (__context.ops.trim_memory)
1236 __context.ops.trim_memory(__context.data);
1241 EXPORT_API int appcore_base_on_receive(aul_type type, bundle *b)
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();
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);
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();
1276 _DBG("[APP %d] AUL event: AUL_TERMINATE", getpid());
1277 aul_status_update(STATUS_DYING);
1278 if (!__context.allowed_bg)
1279 __remove_suspend_timer();
1281 if (__context.ops.exit)
1282 __context.ops.exit(__context.data);
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();
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;
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);
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);
1318 _DBG("[APP %d] AUL event: %d", getpid(), type);
1326 EXPORT_API int appcore_base_on_create(void)
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);
1336 r = aul_launch_argv_handler(__context.argc, __context.argv);
1338 _ERR("Aul argv handler failed: %d", r);
1345 EXPORT_API int appcore_base_on_control(bundle *b)
1347 appcore_base_control_invoke(b);
1352 EXPORT_API int appcore_base_on_terminate()
1359 EXPORT_API void appcore_base_on_set_event(enum appcore_base_event event)
1362 case APPCORE_BASE_EVENT_LOW_BATTERY:
1363 vconf_notify_key_changed(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, __on_low_battery, NULL);
1365 case APPCORE_BASE_EVENT_DEVICE_ORIENTATION_CHANGED:
1366 __register_rotation_changed_event();
1368 case APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE:
1377 EXPORT_API void appcore_base_on_unset_event(enum appcore_base_event event)
1380 case APPCORE_BASE_EVENT_LOW_BATTERY:
1381 vconf_ignore_key_changed(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, __on_low_battery);
1383 case APPCORE_BASE_EVENT_DEVICE_ORIENTATION_CHANGED:
1384 __unregister_rotation_changed_event();
1386 case APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE:
1393 EXPORT_API int appcore_base_on_trim_memory(void)
1395 int (*sqlite3_free_heap_memory)(int);
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);
1407 EXPORT_API appcore_base_event_h appcore_base_add_event(enum appcore_base_event event,
1408 appcore_base_event_cb cb, void *data)
1410 appcore_base_event_node *node;
1412 if (__context.dirty && !__exist_callback(event)) {
1413 if (__context.ops.set_event)
1414 __context.ops.set_event(event, __context.data);
1417 node = malloc(sizeof(appcore_base_event_node));
1426 if (event == APPCORE_BASE_EVENT_LANG_CHANGE ||
1427 event == APPCORE_BASE_EVENT_REGION_CHANGE)
1428 node->prev_event = NULL;
1430 node->prev_event = GINT_TO_POINTER(-1);
1431 __events = g_list_append(__events, node);
1436 EXPORT_API int appcore_base_remove_event(appcore_base_event_h handle)
1438 appcore_base_event_node *node = handle;
1439 enum appcore_base_event event;
1441 if (!node || !g_list_find(__events, node))
1445 __events = g_list_remove(__events, node);
1446 __unset_prev_event(&node->prev_event, event);
1448 if (__context.dirty && !__exist_callback(event)) {
1449 if (__context.ops.unset_event)
1450 __context.ops.unset_event(event, __context.data);
1456 EXPORT_API int appcore_base_raise_event(void *event, enum appcore_base_event type)
1458 __invoke_callback(event, type);
1462 EXPORT_API int appcore_base_get_rotation_state(enum appcore_base_rm *curr)
1467 if (!__rotation.ref)
1470 *curr = __rotation.rm;
1474 EXPORT_API bool appcore_base_is_bg_allowed(void)
1476 return __context.allowed_bg;
1479 EXPORT_API bool appcore_base_is_suspended(void)
1481 return __context.suspended_state;
1484 EXPORT_API void appcore_base_toggle_suspended_state(void)
1486 __context.suspended_state ^= __context.suspended_state;
1489 EXPORT_API void appcore_base_exit(void)
1491 aul_status_update(STATUS_DYING);
1492 if (__context.ops.exit)
1493 __context.ops.exit(__context.data);
1496 EXPORT_API void appcore_base_add_suspend_timer(void)
1498 __add_suspend_timer();
1501 EXPORT_API void appcore_base_remove_suspend_timer(void)
1503 __remove_suspend_timer();
1506 EXPORT_API void appcore_base_set_display_state(int display_state)
1508 __context.display_state = display_state;
1511 EXPORT_API int appcore_base_get_display_state(void)
1513 return __context.display_state;
1516 static int __on_receive(aul_type type, bundle *b, void *data)
1518 return appcore_base_on_receive(type, b);
1521 static int __on_create(void *data)
1523 return appcore_base_on_create();
1526 static int __on_control(bundle *b, void *data)
1528 return appcore_base_on_control(b);
1531 static int __on_terminate(void *data)
1533 return appcore_base_on_terminate();
1536 static int __on_set_i18n(void *data)
1538 return appcore_base_on_set_i18n();
1541 static void __on_set_event(enum appcore_base_event event, void *data)
1543 appcore_base_on_set_event(event);
1546 static void __on_unset_event(enum appcore_base_event event, void *data)
1548 appcore_base_on_unset_event(event);
1551 static void __on_trim_memory(void *data)
1553 appcore_base_on_trim_memory();
1556 EXPORT_API appcore_base_ops appcore_base_get_default_ops(void)
1558 appcore_base_ops ops;
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;
1569 ops.set_event = __on_set_event;
1570 ops.unset_event = __on_unset_event;
1571 ops.trim_memory = __on_trim_memory;