X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fbase%2Fappcore_base.c;h=b45ddf93a9919f4cff3f280075dd0cb340a35ab4;hb=aa40b5c9434ed8e5a2888903ad1e0a71f438e7ea;hp=93e2f56d8faeeeec1306f7490ecbbed4e94c7c02;hpb=3bf5d1fcfc19bdf65b08edb9a701af2078e03a75;p=platform%2Fcore%2Fappfw%2Fapp-core.git diff --git a/src/base/appcore_base.c b/src/base/appcore_base.c index 93e2f56..b45ddf9 100644 --- a/src/base/appcore_base.c +++ b/src/base/appcore_base.c @@ -35,13 +35,20 @@ #include #include #include +#include +#include +#include + #include "appcore_base.h" #include "appcore_base_private.h" +#include "appcore_watchdog.h" +#include "appcore_base_control.h" #define PATH_LOCALE "locale" -#define RESOURCED_FREEZER_PATH "/Org/Tizen/Resourced/Freezer" +#define RESOURCED_FREEZER_PATH "/Org/Tizen/ResourceD/Freezer" #define RESOURCED_FREEZER_INTERFACE "org.tizen.resourced.freezer" #define RESOURCED_FREEZER_SIGNAL "FreezerState" +#define SQLITE_FLUSH_MAX (1024 * 1024) typedef struct _appcore_base_context { appcore_base_ops ops; @@ -51,19 +58,142 @@ typedef struct _appcore_base_context { unsigned int tid; bool suspended_state; bool allowed_bg; + bool dirty; + guint sid; + int display_state; } appcore_base_context; typedef struct _appcore_base_event_node { int type; appcore_base_event_cb cb; void *data; + void *prev_event; } appcore_base_event_node; +typedef struct _appcore_base_rotation { + int conn; + int lock; + int ref; + enum appcore_base_rm rm; + int charger_status; + bool initialized; +} appcore_base_rotation; + +struct lang_info_s { + char *parent; + GList *list; +}; + static appcore_base_context __context; static GList *__events; static GDBusConnection *__bus; static guint __suspend_dbus_handler_initialized; static char *__locale_dir; +static appcore_base_rotation __rotation; + +appcore_base_tizen_profile_t appcore_base_get_tizen_profile(void) +{ + static appcore_base_tizen_profile_t profile = TIZEN_PROFILE_UNKNOWN; + char *profile_name = NULL; + + if (__builtin_expect(profile != TIZEN_PROFILE_UNKNOWN, 1)) + return profile; + + system_info_get_platform_string("http://tizen.org/feature/profile", + &profile_name); + if (profile_name == NULL) + return profile; + + switch (*profile_name) { + case 'm': + case 'M': + profile = TIZEN_PROFILE_MOBILE; + break; + case 'w': + case 'W': + profile = TIZEN_PROFILE_WEARABLE; + break; + case 't': + case 'T': + profile = TIZEN_PROFILE_TV; + break; + case 'i': + case 'I': + profile = TIZEN_PROFILE_IVI; + break; + default: + profile = TIZEN_PROFILE_COMMON; + break; + } + free(profile_name); + + return profile; +} + +static int __compare_event(void *prev_event, void *curr_event, int type) +{ + char *curr_strval; + char *prev_strval; + int curr_intval; + int prev_intval; + int ret = -1; + + switch (type) { + case APPCORE_BASE_EVENT_LOW_MEMORY: + case APPCORE_BASE_EVENT_LOW_BATTERY: + case APPCORE_BASE_EVENT_DEVICE_ORIENTATION_CHANGED: + case APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE: + prev_intval = GPOINTER_TO_INT(prev_event); + curr_intval = *(int *)curr_event; + if (prev_intval == curr_intval) + ret = 0; + break; + case APPCORE_BASE_EVENT_LANG_CHANGE: + case APPCORE_BASE_EVENT_REGION_CHANGE: + prev_strval = prev_event; + curr_strval = curr_event; + if (prev_strval && curr_strval && + !strcmp(prev_strval, curr_strval)) + ret = 0; + break; + default: + break; + } + + return ret; +} + +static void __unset_prev_event(void **prev_event, int type) +{ + if (type == APPCORE_BASE_EVENT_LANG_CHANGE || + type == APPCORE_BASE_EVENT_REGION_CHANGE) + free(*prev_event); + *prev_event = NULL; +} + +static void __set_prev_event(void **prev_event, void *curr_event, int type) +{ + int curr_intval; + char *curr_strval; + + switch (type) { + case APPCORE_BASE_EVENT_LOW_MEMORY: + case APPCORE_BASE_EVENT_LOW_BATTERY: + case APPCORE_BASE_EVENT_DEVICE_ORIENTATION_CHANGED: + case APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE: + curr_intval = *(int *)curr_event; + *prev_event = GINT_TO_POINTER(curr_intval); + break; + case APPCORE_BASE_EVENT_LANG_CHANGE: + case APPCORE_BASE_EVENT_REGION_CHANGE: + curr_strval = curr_event; + if (curr_strval) + *prev_event = strdup(curr_strval); + break; + default: + break; + } +} static void __invoke_callback(void *event, int type) { @@ -71,10 +201,16 @@ static void __invoke_callback(void *event, int type) while (iter) { appcore_base_event_node *node = iter->data; + iter = g_list_next(iter); - if (node->type == type) + if (node->type != type) + continue; + + if (__compare_event(node->prev_event, event, type)) { node->cb(event, node->data); - iter = g_list_next(iter); + __unset_prev_event(&node->prev_event, type); + __set_prev_event(&node->prev_event, event, type); + } } } @@ -94,6 +230,204 @@ static bool __exist_callback(int type) return false; } +static enum appcore_base_rm __get_rm(sensor_data_t data) +{ + int event; + enum appcore_base_rm rm; + + if (data.value_count <= 0) { + _ERR("Failed to get sensor data"); + return APPCORE_BASE_RM_UNKNOWN; + } + + event = data.values[0]; + switch (event) { + case AUTO_ROTATION_DEGREE_0: + rm = APPCORE_BASE_RM_PORTRAIT_NORMAL; + break; + case AUTO_ROTATION_DEGREE_90: + rm = APPCORE_BASE_RM_LANDSCAPE_NORMAL; + break; + case AUTO_ROTATION_DEGREE_180: + rm = APPCORE_BASE_RM_PORTRAIT_REVERSE; + break; + case AUTO_ROTATION_DEGREE_270: + rm = APPCORE_BASE_RM_LANDSCAPE_REVERSE; + break; + default: + rm = APPCORE_BASE_RM_UNKNOWN; + break; + } + + return rm; +} + +static void __lock_cb(keynode_t *node, void *user_data) +{ + bool r; + sensor_data_t data; + enum appcore_base_rm rm; + + __rotation.lock = !vconf_keynode_get_bool(node); + if (__rotation.lock) { + _DBG("Rotation locked"); + rm = APPCORE_BASE_RM_PORTRAIT_NORMAL; + } else { + _DBG("Rotation unlocked"); + r = sensord_get_data(__rotation.conn, AUTO_ROTATION_SENSOR, &data); + if (!r) { + _ERR("Failed to get sensor data"); + return; + } + + rm = __get_rm(data); + if (rm == APPCORE_BASE_RM_UNKNOWN) { + _ERR("Unknown mode"); + return; + } + } + + if (__rotation.rm == rm) + return; + + _DBG("Rotation: %d -> %d", __rotation.rm, rm); + __rotation.rm = rm; + __invoke_callback((void *)&__rotation.rm, APPCORE_BASE_EVENT_DEVICE_ORIENTATION_CHANGED); +} + +static void __auto_rotation_changed_cb(sensor_t sensor, unsigned int event_type, + sensor_data_t *data, void *user_data) +{ + enum appcore_base_rm rm; + + if (data == NULL) + return; + + if (__rotation.lock) + return; + + if (event_type != AUTO_ROTATION_CHANGE_STATE_EVENT) + return; + + rm = __get_rm(*data); + if (rm == APPCORE_BASE_RM_UNKNOWN) { + _ERR("Unknown mode"); + return; + } + + _DBG("Rotation: %d -> %d", __rotation.rm, rm); + __rotation.rm = rm; + __invoke_callback((void *)&__rotation.rm, APPCORE_BASE_EVENT_DEVICE_ORIENTATION_CHANGED); +} + +static void __fini_rotation(void) +{ + if (!__rotation.initialized) + return; + + vconf_ignore_key_changed(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, __lock_cb); + sensord_unregister_event(__rotation.conn, AUTO_ROTATION_CHANGE_STATE_EVENT); + sensord_stop(__rotation.conn); + sensord_disconnect(__rotation.conn); + + __rotation.lock = 0; + __rotation.initialized = false; +} + +static void __init_rotation(void) +{ + sensor_t sensor; + int lock; + bool r; + + if (__rotation.initialized) + return; + + sensor = sensord_get_sensor(AUTO_ROTATION_SENSOR); + __rotation.conn = sensord_connect(sensor); + if (__rotation.conn < 0) { + _ERR("Failed to connect sensord"); + return; + } + + r = sensord_register_event(__rotation.conn, AUTO_ROTATION_CHANGE_STATE_EVENT, + SENSOR_INTERVAL_NORMAL, 0, __auto_rotation_changed_cb, NULL); + if (!r) { + _ERR("Failed to register auto rotation change event"); + sensord_disconnect(__rotation.conn); + return; + } + + r = sensord_start(__rotation.conn, 0); + if (!r) { + _ERR("Failed to start sensord"); + sensord_unregister_event(__rotation.conn, AUTO_ROTATION_CHANGE_STATE_EVENT); + sensord_disconnect(__rotation.conn); + return; + } + + lock = 0; + vconf_get_bool(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, &lock); + vconf_notify_key_changed(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, __lock_cb, NULL); + + __rotation.lock = !lock; + __rotation.initialized = true; +} + +static void __charger_status_changed_cb(keynode_t *keynode, void *user_data) +{ + if (TIZEN_FEATURE_CHARGER_STATUS) { + __rotation.charger_status = vconf_keynode_get_int(keynode); + if (__rotation.charger_status) { + if (__rotation.ref) + __init_rotation(); + } else { + if (__rotation.ref) + __fini_rotation(); + } + _DBG("charger status(%d)", __rotation.charger_status); + } +} + +static void __unregister_rotation_changed_event(void) +{ + if (!__rotation.ref) + return; + + __rotation.ref--; + if (__rotation.ref > 1) + return; + + __fini_rotation(); + if (TIZEN_FEATURE_CHARGER_STATUS) { + vconf_ignore_key_changed(VCONFKEY_SYSMAN_CHARGER_STATUS, + __charger_status_changed_cb); + } + + __rotation.ref = 0; +} + +static void __register_rotation_changed_event(void) +{ + if (__rotation.ref) { + __rotation.ref++; + return; + } + + if (TIZEN_FEATURE_CHARGER_STATUS) { + vconf_get_int(VCONFKEY_SYSMAN_CHARGER_STATUS, + &__rotation.charger_status); + vconf_notify_key_changed(VCONFKEY_SYSMAN_CHARGER_STATUS, + __charger_status_changed_cb, NULL); + if (__rotation.charger_status) + __init_rotation(); + } else { + __init_rotation(); + } + + __rotation.ref++; +} + static void __on_low_memory(keynode_t *key, void *data) { int val; @@ -101,7 +435,7 @@ static void __on_low_memory(keynode_t *key, void *data) val = vconf_keynode_get_int(key); if (val >= VCONFKEY_SYSMAN_LOW_MEMORY_SOFT_WARNING) { - __invoke_callback(key, APPCORE_BASE_EVENT_LOW_MEMORY); + __invoke_callback(&val, APPCORE_BASE_EVENT_LOW_MEMORY); malloc_trim(0); } } @@ -113,24 +447,73 @@ static void __on_low_battery(keynode_t *key, void *data) val = vconf_keynode_get_int(key); if (val <= VCONFKEY_SYSMAN_BAT_CRITICAL_LOW) - __invoke_callback(key, APPCORE_BASE_EVENT_LOW_BATTERY); + __invoke_callback(&val, APPCORE_BASE_EVENT_LOW_BATTERY); } -static void __free_children_langs(gpointer data) +static void __destroy_lang_info(gpointer data) { - GList *list = (GList *)data; + struct lang_info_s *info = (struct lang_info_s *)data; - if (list == NULL) + if (info == NULL) return; - g_list_free_full(list, (GDestroyNotify)free); + if (info->list) + g_list_free_full(info->list, free); + if (info->parent) + free(info->parent); + free(info); +} + +static struct lang_info_s *__create_lang_info(const char *lang) +{ + struct lang_info_s *info; + + info = calloc(1, sizeof(struct lang_info_s)); + if (info == NULL) { + _ERR("Out of memory"); + return NULL; + } + + info->parent = strdup(lang); + if (info->parent == NULL) { + _ERR("Out of memory"); + free(info); + return NULL; + } + + return info; } static gint __compare_langs(gconstpointer a, gconstpointer b) { + if (!a || !b) + return -1; + return strcmp(a, b); } +static char *__get_string_before(const char *str, const char *delim) +{ + char *new_str; + char *dup_str; + char *token; + + dup_str = strdup(str); + if (dup_str == NULL) + return NULL; + + token = strtok(dup_str, delim); + if (token == NULL) { + free(dup_str); + return NULL; + } + + new_str = strdup(token); + free(dup_str); + + return new_str; +} + static GHashTable *__get_lang_table(void) { GHashTable *table; @@ -139,15 +522,14 @@ static GHashTable *__get_lang_table(void) char buf[PATH_MAX]; struct stat stat_buf; int ret; - char *dup_lang; - char *token; - GList *list; + char *parent_lang; + struct lang_info_s *info; if (__locale_dir == NULL || __locale_dir[0] == '\0') return NULL; table = g_hash_table_new_full(g_str_hash, g_str_equal, - free, __free_children_langs); + NULL, __destroy_lang_info); if (table == NULL) { _ERR("Out of memory"); return NULL; @@ -170,128 +552,86 @@ static GHashTable *__get_lang_table(void) if (ret != 0 || !S_ISDIR(stat_buf.st_mode)) continue; - dup_lang = strdup(dentry->d_name); - if (dup_lang == NULL) { + parent_lang = __get_string_before(dentry->d_name, "_"); + if (parent_lang == NULL) { _ERR("Out of memory"); break; } - token = strtok(dup_lang, "_"); - if (token == NULL) { - free(dup_lang); - continue; - } - - list = (GList *)g_hash_table_lookup(table, token); - if (list == NULL) { - list = g_list_append(list, strdup(dentry->d_name)); - g_hash_table_insert(table, strdup(token), list); - } else { - list = g_list_append(list, strdup(dentry->d_name)); + info = g_hash_table_lookup(table, parent_lang); + if (info == NULL) { + info = __create_lang_info(parent_lang); + if (info == NULL) { + free(parent_lang); + break; + } + g_hash_table_insert(table, info->parent, info); } - free(dup_lang); + info->list = g_list_append(info->list, strdup(dentry->d_name)); + free(parent_lang); } closedir(dp); return table; } -static char *__get_string_before(const char *str, const char *delim) -{ - char *new_str; - char *dup_str; - char *token; - - dup_str = strdup(str); - if (dup_str == NULL) - return NULL; - - token = strtok(dup_str, delim); - if (token == NULL) { - free(dup_str); - return NULL; - } - - new_str = strdup(token); - free(dup_str); - - return new_str; -} - static GList *__append_langs(const char *lang, GList *list, GHashTable *table) { - GList *child_list; - GList *child_iter; + struct lang_info_s *info; GList *found; - char *child_lang; - char *parent_lang; + char *parent_lang = NULL; char *extract_lang; - char *tmp; if (lang == NULL) return list; - found = g_list_find_custom(g_list_first(list), lang, - __compare_langs); - if (found) { - tmp = (char *)found->data; - list = g_list_remove(list, tmp); - list = g_list_append(list, tmp); - return list; - } + list = g_list_append(list, strdup(lang)); extract_lang = __get_string_before(lang, "."); if (extract_lang == NULL) return list; - parent_lang = __get_string_before(extract_lang, "_"); - if (parent_lang == NULL) { - free(extract_lang); - return list; + found = g_list_find_custom(list, extract_lang, __compare_langs); + if (found) { + list = g_list_remove_link(list, found); + list = g_list_concat(list, found); + goto end; } - child_list = g_hash_table_lookup(table, parent_lang); - if (child_list == NULL) { - free(parent_lang); - free(extract_lang); - return list; - } + parent_lang = __get_string_before(extract_lang, "_"); + if (parent_lang == NULL) + goto end; - found = g_list_find_custom(g_list_first(child_list), - extract_lang, __compare_langs); + info = g_hash_table_lookup(table, parent_lang); + if (info == NULL) + goto end; + + found = g_list_find_custom(info->list, extract_lang, __compare_langs); if (found) { - tmp = (char *)found->data; - child_list = g_list_remove(child_list, tmp); - list = g_list_append(list, tmp); - free(parent_lang); - free(extract_lang); - return list; + info->list = g_list_remove_link(info->list, found); + list = g_list_concat(list, found); + goto end; } - free(extract_lang); - found = g_list_find_custom(g_list_first(child_list), - parent_lang, __compare_langs); + found = g_list_find_custom(info->list, parent_lang, __compare_langs); if (found) { - tmp = (char *)found->data; - child_list = g_list_remove(child_list, tmp); - list = g_list_append(list, tmp); - free(parent_lang); - return list; + info->list = g_list_remove_link(info->list, found); + list = g_list_concat(list, found); + goto end; } - free(parent_lang); - child_iter = g_list_first(child_list); - while (child_iter) { - child_lang = (char *)child_iter->data; - child_iter = g_list_next(child_iter); - if (child_lang) { - list = g_list_append(list, strdup(child_lang)); - child_list = g_list_remove(child_list, child_lang); - free(child_lang); - break; - } + found = g_list_first(info->list); + if (found) { + info->list = g_list_remove_link(info->list, found); + list = g_list_concat(list, found); } +end: + if (extract_lang) + free(extract_lang); + if (parent_lang) + free(parent_lang); + return list; } @@ -324,8 +664,7 @@ static GList *__append_default_langs(GList *list) GList *found; for (i = 0; i < (sizeof(langs) / sizeof(langs[0])); i++) { - found = g_list_find_custom(g_list_first(list), langs[i], - __compare_langs); + found = g_list_find_custom(list, langs[i], __compare_langs); if (found == NULL) list = g_list_append(list, strdup(langs[i])); } @@ -402,11 +741,19 @@ static void __update_lang(void) } setenv("LANG", lang, 1); setenv("LC_MESSAGES", lang, 1); + setenv("LC_ALL", lang, 1); r = setlocale(LC_ALL, ""); if (r == NULL) { - r = setlocale(LC_ALL, lang); - if (r != NULL) + r = setlocale(LC_ALL, "en_US.UTF-8"); + if (r != NULL) { _DBG("*****appcore setlocale=%s\n", r); + } else { + _DBG("*****appcore setlocale=\"C\""); + setenv("LC_ALL", "C", 1); + r = setlocale(LC_ALL, ""); + if (r == NULL) + _ERR("failed to setlocale"); + } } free(lang); } @@ -431,8 +778,15 @@ static void __update_region(void) setenv("LC_MEASUREMENT", region, 1); setenv("LC_IDENTIFICATION", region, 1); r = setlocale(LC_ALL, ""); - if (r != NULL) + if (r != NULL) { _DBG("*****appcore setlocale=%s\n", r); + } else { + _DBG("*****appcore setlocale=\"C\""); + setenv("LC_ALL", "C", 1); + r = setlocale(LC_ALL, ""); + if (r == NULL) + _ERR("failed to setlocale"); + } free(region); } @@ -442,6 +796,11 @@ static void __on_language_change(keynode_t *key, void *data) { char *val; + if (__context.sid) { + g_source_remove(__context.sid); + __context.sid = 0; + } + val = vconf_keynode_get_str(key); __update_lang(); @@ -450,22 +809,67 @@ static void __on_language_change(keynode_t *key, void *data) static void __on_region_change(keynode_t *key, void *data) { - char *val = NULL; + char *val; const char *name; name = vconf_keynode_get_name(key); - if (!strcmp(name, VCONFKEY_REGIONFORMAT)) - val = vconf_keynode_get_str(key); + if (name == NULL) + return; + + if (strcmp(name, VCONFKEY_REGIONFORMAT) && + strcmp(name, VCONFKEY_REGIONFORMAT_TIME1224)) + return; + + val = vconf_get_str(VCONFKEY_REGIONFORMAT); __update_region(); __invoke_callback((void *)val, APPCORE_BASE_EVENT_REGION_CHANGE); + free(val); +} + +static gboolean __invoke_lang_change(gpointer data) +{ + const char *lang; + + __context.sid = 0; + + lang = getenv("LANG"); + if (!lang) + return G_SOURCE_REMOVE; + + __invoke_callback((void *)lang, APPCORE_BASE_EVENT_LANG_CHANGE); + + return G_SOURCE_REMOVE; +} + +static void __verify_language(void) +{ + char *lang; + const char *env_lang; + + env_lang = getenv("LANG"); + if (!env_lang) + return; + + lang = vconf_get_str(VCONFKEY_LANGSET); + if (!lang) + return; + + if (strcmp(env_lang, lang) != 0) { + _INFO("LANG(%s), LANGSET(%s)", env_lang, lang); + __context.sid = g_idle_add(__invoke_lang_change, NULL); + } + + free(lang); } static gboolean __flush_memory(gpointer data) { int suspend = APPCORE_BASE_SUSPENDED_STATE_WILL_ENTER_SUSPEND; - appcore_base_flush_memory(); + if (__context.ops.trim_memory) + __context.ops.trim_memory(__context.data); + __context.tid = 0; if (!__context.allowed_bg && !__context.suspended_state) { @@ -568,6 +972,12 @@ static void __fini_suspend_dbus_handler(void) __bus = NULL; } +static gboolean __init_suspend(gpointer data) +{ + __init_suspend_dbus_handler(); + return G_SOURCE_REMOVE; +} + static int __get_locale_resource_dir(char *locale_dir, int size) { const char *res_path; @@ -580,7 +990,7 @@ static int __get_locale_resource_dir(char *locale_dir, int size) snprintf(locale_dir, size, "%s" PATH_LOCALE, res_path); if (access(locale_dir, R_OK) != 0) - return -1; + _DBG("%s does not exist", locale_dir); return 0; } @@ -609,7 +1019,6 @@ static int __get_app_name(const char *appid, char **name) static int __set_i18n(const char *domain, const char *dir) { char *r; - char *lan; if (domain == NULL) { errno = EINVAL; @@ -626,17 +1035,20 @@ static int __set_i18n(const char *domain, const char *dir) __update_region(); r = setlocale(LC_ALL, ""); - /* if locale is not set properly, try again to set as language base */ + /* if locale is not set properly, try to set "en_US" again */ if (r == NULL) { - lan = vconf_get_str(VCONFKEY_LANGSET); - if (lan != NULL) { - r = setlocale(LC_ALL, lan); + r = setlocale(LC_ALL, "en_US.UTF-8"); + if (r != NULL) _DBG("*****appcore setlocale=%s\n", r); - free(lan); - } } - if (r == NULL) + if (r == NULL) { _ERR("appcore: setlocale() error"); + _DBG("*****appcore setlocale=\"C\""); + setenv("LC_ALL", "C", 1); + r = setlocale(LC_ALL, ""); + if (r == NULL) + _ERR("failed to setlocale"); + } r = bindtextdomain(domain, dir); if (r == NULL) @@ -657,8 +1069,10 @@ EXPORT_API int appcore_base_on_set_i18n(void) char *name = NULL; r = aul_app_get_appid_bypid(getpid(), appid, PATH_MAX); - if (r < 0) + if (r < 0) { + _ERR("Failed to get application ID - pid(%d)", getpid()); return -1; + } r = __get_app_name(appid, &name); if (r < 0) @@ -681,8 +1095,38 @@ EXPORT_API int appcore_base_on_set_i18n(void) return 0; } +EXPORT_API int appcore_base_set_i18n(const char *domain_name, const char *dir_name) +{ + return __set_i18n(domain_name, dir_name); +} + +static void __set_default_events(void) +{ + int r; + + vconf_notify_key_changed(VCONFKEY_LANGSET, __on_language_change, NULL); + r = vconf_notify_key_changed(VCONFKEY_REGIONFORMAT, __on_region_change, NULL); + if (r == 0) + vconf_notify_key_changed(VCONFKEY_REGIONFORMAT_TIME1224, __on_region_change, NULL); + vconf_notify_key_changed(VCONFKEY_SYSMAN_LOW_MEMORY, __on_low_memory, NULL); +} + +static void __unset_default_events(void) +{ + int r; + + vconf_ignore_key_changed(VCONFKEY_LANGSET, __on_language_change); + r = vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT, __on_region_change); + if (r == 0) + vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT_TIME1224, __on_region_change); + vconf_ignore_key_changed(VCONFKEY_SYSMAN_LOW_MEMORY, __on_low_memory); +} + EXPORT_API int appcore_base_init(appcore_base_ops ops, int argc, char **argv, void *data) { + int i; + int r; + __context.ops = ops; __context.argc = argc; __context.argv = argv; @@ -691,14 +1135,36 @@ EXPORT_API int appcore_base_init(appcore_base_ops ops, int argc, char **argv, vo __context.suspended_state = false; __context.allowed_bg = false; + if (__context.ops.init) + __context.ops.init(argc, argv, data); + + if (TIZEN_FEATURE_BACKGROUND_MANAGEMENT) + g_idle_add(__init_suspend, NULL); + + if (!__context.dirty) { + __context.dirty = true; + + for (i = APPCORE_BASE_EVENT_START + 1; i < APPCORE_BASE_EVENT_MAX; i++) { + if (__exist_callback(i)) { + if (__context.ops.set_event) + __context.ops.set_event(i, __context.data); + } + } + } + + __verify_language(); + __set_default_events(); if (__context.ops.set_i18n) __context.ops.set_i18n(__context.data); - __init_suspend_dbus_handler(); - - if (__context.ops.create && __context.ops.create(__context.data) < 0) { - aul_status_update(STATUS_DYING); - return 0; + if (__context.ops.create) { + traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:CREATE"); + r = __context.ops.create(__context.data); + traceEnd(TTRACE_TAG_APPLICATION_MANAGER); + if (r < 0) { + aul_status_update(STATUS_DYING); + return 0; + } } if (__context.ops.run) @@ -711,6 +1177,14 @@ EXPORT_API void appcore_base_fini(void) { int i; + aul_status_update(STATUS_DYING); + appcore_watchdog_disable(); + if (__context.ops.terminate) { + traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:TERMINATE"); + __context.ops.terminate(__context.data); + traceEnd(TTRACE_TAG_APPLICATION_MANAGER); + } + for (i = APPCORE_BASE_EVENT_START + 1; i < APPCORE_BASE_EVENT_MAX; i++) { if (__exist_callback(i)) { if (__context.ops.unset_event) @@ -718,66 +1192,71 @@ EXPORT_API void appcore_base_fini(void) } } + appcore_base_control_fini(); + __unset_default_events(); + + if (__context.sid) { + g_source_remove(__context.sid); + __context.sid = 0; + } + g_list_free_full(__events, free); __events = NULL; - __fini_suspend_dbus_handler(); - aul_status_update(STATUS_DYING); - if (__context.ops.terminate) - __context.ops.terminate(__context.data); + if (TIZEN_FEATURE_BACKGROUND_MANAGEMENT) + __fini_suspend_dbus_handler(); if (__locale_dir) { free(__locale_dir); __locale_dir = NULL; } + + __context.dirty = false; + + if (__context.ops.finish) + __context.ops.finish(); } EXPORT_API int appcore_base_flush_memory(void) { - malloc_trim(0); + if (__context.ops.trim_memory) + __context.ops.trim_memory(__context.data); + return 0; } EXPORT_API int appcore_base_on_receive(aul_type type, bundle *b) { - int ret; - const char **tep_path; - int len = 0; - int i; const char *bg; int dummy = 0; switch (type) { case AUL_START: _DBG("[APP %d] AUL event: AUL_START", getpid()); - tep_path = bundle_get_str_array(b, AUL_TEP_PATH, &len); - if (tep_path) { - for (i = 0; i < len; i++) { - ret = aul_check_tep_mount(tep_path[i]); - if (ret == -1) { - _ERR("mount request not completed within 1 sec"); - exit(-1); - } + if (TIZEN_FEATURE_BACKGROUND_MANAGEMENT) { + bg = bundle_get_val(b, AUL_K_ALLOWED_BG); + if (bg && !strcmp(bg, "ALLOWED_BG")) { + _DBG("[__SUSPEND__] allowed background"); + __context.allowed_bg = true; + __remove_suspend_timer(); } } - bg = bundle_get_val(b, AUL_K_ALLOWED_BG); - if (bg && strncmp(bg, "ALLOWED_BG", strlen("ALLOWED_BG")) == 0) { - _DBG("[__SUSPEND__] allowed background"); - __context.allowed_bg = true; - __remove_suspend_timer(); + if (__context.ops.control) { + traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:RESET"); + __context.ops.control(b, __context.data); + traceEnd(TTRACE_TAG_APPLICATION_MANAGER); } - - if (__context.ops.control) - __context.ops.control(b, __context.data); break; case AUL_RESUME: _DBG("[APP %d] AUL event: AUL_RESUME", getpid()); - bg = bundle_get_val(b, AUL_K_ALLOWED_BG); - if (bg && strncmp(bg, "ALLOWED_BG", strlen("ALLOWED_BG")) == 0) { - _DBG("[__SUSPEND__] allowed background"); - __context.allowed_bg = true; - __remove_suspend_timer(); + if (TIZEN_FEATURE_BACKGROUND_MANAGEMENT) { + bg = bundle_get_val(b, AUL_K_ALLOWED_BG); + if (bg && !strcmp(bg, "ALLOWED_BG")) { + _DBG("[__SUSPEND__] allowed background"); + __context.allowed_bg = true; + __remove_suspend_timer(); + } } break; case AUL_TERMINATE: @@ -789,25 +1268,33 @@ EXPORT_API int appcore_base_on_receive(aul_type type, bundle *b) if (__context.ops.exit) __context.ops.exit(__context.data); break; + case AUL_TERMINATE_INST: + case AUL_TERMINATE_BG_INST: case AUL_TERMINATE_BGAPP: - _DBG("[APP %d] AUL event: AUL_TERMINATE_BGAPP", getpid()); + _DBG("[APP %d] AUL event: %d", getpid(), type); if (!__context.allowed_bg) __remove_suspend_timer(); break; case AUL_WAKE: _DBG("[APP %d] AUL event: AUL_WAKE", getpid()); - if (!__context.allowed_bg && __context.suspended_state) { - int suspend = APPCORE_BASE_SUSPENDED_STATE_DID_EXIT_FROM_SUSPEND; - __remove_suspend_timer(); - __invoke_callback((void *)&suspend, APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE); - __context.suspended_state = false; + if (TIZEN_FEATURE_BACKGROUND_MANAGEMENT) { + if (!__context.allowed_bg && + __context.suspended_state) { + int suspend = APPCORE_BASE_SUSPENDED_STATE_DID_EXIT_FROM_SUSPEND; + __remove_suspend_timer(); + __invoke_callback((void *)&suspend, APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE); + __context.suspended_state = false; + } } break; case AUL_SUSPEND: _DBG("[APP %d] AUL event: AUL_SUSPEND", getpid()); - if (!__context.allowed_bg && !__context.suspended_state) { - __remove_suspend_timer(); - __flush_memory(NULL); + if (TIZEN_FEATURE_BACKGROUND_MANAGEMENT) { + if (!__context.allowed_bg && + !__context.suspended_state) { + __remove_suspend_timer(); + __flush_memory(NULL); + } } break; case AUL_UPDATE_REQUESTED: @@ -826,7 +1313,8 @@ EXPORT_API int appcore_base_on_receive(aul_type type, bundle *b) EXPORT_API int appcore_base_on_create(void) { int r; - r = aul_launch_init(__context.ops.receive, NULL); + + r = aul_launch_init(__context.ops.receive, __context.data); if (r < 0) { _ERR("Aul init failed: %d", r); return -1; @@ -843,38 +1331,26 @@ EXPORT_API int appcore_base_on_create(void) EXPORT_API int appcore_base_on_control(bundle *b) { + appcore_base_control_invoke(b); + return 0; } EXPORT_API int appcore_base_on_terminate() { aul_finalize(); - if (__context.ops.exit) - __context.ops.exit(__context.data); return 0; } EXPORT_API void appcore_base_on_set_event(enum appcore_base_event event) { - int r; - switch (event) { - case APPCORE_BASE_EVENT_LOW_MEMORY: - vconf_notify_key_changed(VCONFKEY_SYSMAN_LOW_MEMORY, __on_low_memory, NULL); - break; case APPCORE_BASE_EVENT_LOW_BATTERY: vconf_notify_key_changed(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, __on_low_battery, NULL); break; - case APPCORE_BASE_EVENT_LANG_CHANGE: - vconf_notify_key_changed(VCONFKEY_LANGSET, __on_language_change, NULL); - break; - case APPCORE_BASE_EVENT_REGION_CHANGE: - r = vconf_notify_key_changed(VCONFKEY_REGIONFORMAT, __on_region_change, NULL); - if (r < 0) - break; - - vconf_notify_key_changed(VCONFKEY_REGIONFORMAT_TIME1224, __on_region_change, NULL); + case APPCORE_BASE_EVENT_DEVICE_ORIENTATION_CHANGED: + __register_rotation_changed_event(); break; case APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE: break; @@ -887,23 +1363,12 @@ EXPORT_API void appcore_base_on_set_event(enum appcore_base_event event) EXPORT_API void appcore_base_on_unset_event(enum appcore_base_event event) { - int r; - switch (event) { - case APPCORE_BASE_EVENT_LOW_MEMORY: - vconf_ignore_key_changed(VCONFKEY_SYSMAN_LOW_MEMORY, __on_low_memory); - break; case APPCORE_BASE_EVENT_LOW_BATTERY: vconf_ignore_key_changed(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, __on_low_battery); break; - case APPCORE_BASE_EVENT_LANG_CHANGE: - vconf_ignore_key_changed(VCONFKEY_LANGSET, __on_language_change); - break; - case APPCORE_BASE_EVENT_REGION_CHANGE: - r = vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT, __on_region_change); - if (r < 0) - break; - vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT_TIME1224, __on_region_change); + case APPCORE_BASE_EVENT_DEVICE_ORIENTATION_CHANGED: + __unregister_rotation_changed_event(); break; case APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE: break; @@ -912,12 +1377,26 @@ EXPORT_API void appcore_base_on_unset_event(enum appcore_base_event event) } } +EXPORT_API int appcore_base_on_trim_memory(void) +{ + int (*sqlite3_free_heap_memory)(int); + + sqlite3_free_heap_memory = dlsym(RTLD_DEFAULT, + "sqlite3_release_memory"); + if (sqlite3_free_heap_memory) + sqlite3_free_heap_memory(SQLITE_FLUSH_MAX); + + malloc_trim(0); + + return 0; +} + EXPORT_API appcore_base_event_h appcore_base_add_event(enum appcore_base_event event, appcore_base_event_cb cb, void *data) { appcore_base_event_node *node; - if (!__exist_callback(event)) { + if (__context.dirty && !__exist_callback(event)) { if (__context.ops.set_event) __context.ops.set_event(event, __context.data); } @@ -930,6 +1409,7 @@ EXPORT_API appcore_base_event_h appcore_base_add_event(enum appcore_base_event e node->cb = cb; node->type = event; node->data = data; + node->prev_event = NULL; __events = g_list_append(__events, node); return node; @@ -940,10 +1420,14 @@ EXPORT_API int appcore_base_remove_event(appcore_base_event_h handle) appcore_base_event_node *node = handle; enum appcore_base_event event; + if (!node || !g_list_find(__events, node)) + return -1; + event = node->type; __events = g_list_remove(__events, node); + __unset_prev_event(&node->prev_event, event); free(node); - if (!__exist_callback(event)) { + if (__context.dirty && !__exist_callback(event)) { if (__context.ops.unset_event) __context.ops.unset_event(event, __context.data); } @@ -959,6 +1443,13 @@ EXPORT_API int appcore_base_raise_event(void *event, enum appcore_base_event typ EXPORT_API int appcore_base_get_rotation_state(enum appcore_base_rm *curr) { + if (curr == NULL) + return -1; + + if (!__rotation.ref) + return -1; + + *curr = __rotation.rm; return 0; } @@ -977,6 +1468,32 @@ EXPORT_API void appcore_base_toggle_suspended_state(void) __context.suspended_state ^= __context.suspended_state; } +EXPORT_API void appcore_base_exit(void) +{ + if (__context.ops.exit) + __context.ops.exit(__context.data); +} + +EXPORT_API void appcore_base_add_suspend_timer(void) +{ + __add_suspend_timer(); +} + +EXPORT_API void appcore_base_remove_suspend_timer(void) +{ + __remove_suspend_timer(); +} + +EXPORT_API void appcore_base_set_display_state(int display_state) +{ + __context.display_state = display_state; +} + +EXPORT_API int appcore_base_get_display_state(void) +{ + return __context.display_state; +} + static int __on_receive(aul_type type, bundle *b, void *data) { return appcore_base_on_receive(type, b); @@ -1004,12 +1521,17 @@ static int __on_set_i18n(void *data) static void __on_set_event(enum appcore_base_event event, void *data) { - return appcore_base_on_set_event(event); + appcore_base_on_set_event(event); } static void __on_unset_event(enum appcore_base_event event, void *data) { - return appcore_base_on_unset_event(event); + appcore_base_on_unset_event(event); +} + +static void __on_trim_memory(void *data) +{ + appcore_base_on_trim_memory(); } EXPORT_API appcore_base_ops appcore_base_get_default_ops(void) @@ -1021,12 +1543,13 @@ EXPORT_API appcore_base_ops appcore_base_get_default_ops(void) ops.terminate = __on_terminate; ops.receive = __on_receive; ops.set_i18n = __on_set_i18n; + ops.init = NULL; + ops.finish = NULL; ops.run = NULL; ops.exit = NULL; ops.set_event = __on_set_event; ops.unset_event = __on_unset_event; + ops.trim_memory = __on_trim_memory; return ops; } - -