X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fbase%2Fappcore_base.c;h=c9a17cc69ebffdc30e16d2e82265f95c93eb4f45;hb=0fcfe3095409c931075c57faa7bd48809ab70b6f;hp=2f7298b05408a4a7511d724ee88b8f589041410b;hpb=49019cdc06f443428b3c6d7d273b4aa4a0c28011;p=platform%2Fcore%2Fappfw%2Fapp-core.git diff --git a/src/base/appcore_base.c b/src/base/appcore_base.c index 2f7298b..c9a17cc 100644 --- a/src/base/appcore_base.c +++ b/src/base/appcore_base.c @@ -35,6 +35,8 @@ #include #include #include +#include +#include #include "appcore_base.h" #include "appcore_base_private.h" @@ -51,6 +53,7 @@ typedef struct _appcore_base_context { unsigned int tid; bool suspended_state; bool allowed_bg; + bool dirty; } appcore_base_context; typedef struct _appcore_base_event_node { @@ -59,11 +62,24 @@ typedef struct _appcore_base_event_node { void *data; } appcore_base_event_node; +typedef struct _appcore_base_rotation { + int conn; + int lock; + int ref; + enum appcore_base_rm rm; +} 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; static void __invoke_callback(void *event, int type) { @@ -94,6 +110,156 @@ 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 __unregister_rotation_changed_event(void) +{ + if (!__rotation.ref) + return; + + __rotation.ref--; + if (__rotation.ref > 1) + 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.ref = 0; +} + +static void __register_rotation_changed_event(void) +{ + sensor_t sensor; + int lock; + bool r; + + if (__rotation.ref) { + __rotation.ref++; + 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.ref++; +} + static void __on_low_memory(keynode_t *key, void *data) { int val; @@ -101,7 +267,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 +279,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 +354,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,26 +384,23 @@ 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); @@ -198,76 +409,58 @@ static GHashTable *__get_lang_table(void) 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 *dup_lang; - char *token; + char *parent_lang = NULL; + char *extract_lang; if (lang == NULL) return list; - found = g_list_find_custom(g_list_first(list), lang, - __compare_langs); + extract_lang = __get_string_before(lang, "."); + if (extract_lang == NULL) + return list; + + found = g_list_find_custom(list, extract_lang, __compare_langs); if (found) { list = g_list_remove_link(list, found); - free(found->data); - g_list_free(found); - list = g_list_append(list, strdup(lang)); - return list; + list = g_list_concat(list, found); + goto end; } - dup_lang = strdup(lang); - if (dup_lang == NULL) - return list; + parent_lang = __get_string_before(extract_lang, "_"); + if (parent_lang == NULL) + goto end; - token = strtok(dup_lang, "_"); - if (token == NULL) { - free(dup_lang); - return list; - } + info = g_hash_table_lookup(table, parent_lang); + if (info == NULL) + goto end; - child_list = g_hash_table_lookup(table, token); - if (child_list == NULL) { - free(dup_lang); - return list; + found = g_list_find_custom(info->list, extract_lang, __compare_langs); + if (found) { + info->list = g_list_remove_link(info->list, found); + list = g_list_concat(list, found); + goto end; } - found = g_list_find_custom(g_list_first(child_list), - lang, __compare_langs); + found = g_list_find_custom(info->list, parent_lang, __compare_langs); if (found) { - list = g_list_append(list, strdup(lang)); - child_list = g_list_remove_link(child_list, found); - free(found->data); - g_list_free(found); - free(dup_lang); - return list; + info->list = g_list_remove_link(info->list, found); + list = g_list_concat(list, found); + goto end; } - found = g_list_find_custom(g_list_first(child_list), - token, __compare_langs); + found = g_list_first(info->list); if (found) { - list = g_list_append(list, strdup(token)); - child_list = g_list_remove_link(child_list, found); - free(found->data); - g_list_free(found); - free(dup_lang); - return list; + info->list = g_list_remove_link(info->list, found); + list = g_list_concat(list, found); } - free(dup_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; - } - } +end: + if (extract_lang) + free(extract_lang); + if (parent_lang) + free(parent_lang); return list; } @@ -294,6 +487,21 @@ static GList *__split_language(const char *lang) return list; } +static GList *__append_default_langs(GList *list) +{ + const char *langs[] = {"en_US", "en_GB", "en"}; + unsigned int i; + GList *found; + + for (i = 0; i < (sizeof(langs) / sizeof(langs[0])); i++) { + found = g_list_find_custom(list, langs[i], __compare_langs); + if (found == NULL) + list = g_list_append(list, strdup(langs[i])); + } + + return list; +} + static char *__get_language(const char *lang) { GHashTable *table; @@ -323,6 +531,7 @@ static char *__get_language(const char *lang) g_list_free_full(list, free); g_hash_table_destroy(table); + lang_list = __append_default_langs(lang_list); iter = g_list_first(lang_list); while (iter) { language = (char *)iter->data; @@ -340,11 +549,6 @@ static char *__get_language(const char *lang) } g_list_free_full(lang_list, free); - n = sizeof(buf) - strlen(buf) - 1; - strncat(buf, ":", n); - n = sizeof(buf) - strlen(buf) - 1; - strncat(buf, "en_US:en_GB:en", n); - return strdup(buf); } @@ -363,7 +567,7 @@ static void __update_lang(void) setenv("LANGUAGE", language, 1); free(language); } else { - setenv("LANGUAGE", language, 1); + setenv("LANGUAGE", lang, 1); } setenv("LANG", lang, 1); setenv("LC_MESSAGES", lang, 1); @@ -419,7 +623,7 @@ static void __on_region_change(keynode_t *key, void *data) const char *name; name = vconf_keynode_get_name(key); - if (!strcmp(name, VCONFKEY_REGIONFORMAT)) + if (name && !strcmp(name, VCONFKEY_REGIONFORMAT)) val = vconf_keynode_get_str(key); __update_region(); @@ -545,7 +749,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; } @@ -581,6 +785,12 @@ static int __set_i18n(const char *domain, const char *dir) return -1; } + if (dir) { + if (__locale_dir) + free(__locale_dir); + __locale_dir = strdup(dir); + } + __update_lang(); __update_region(); @@ -597,12 +807,6 @@ static int __set_i18n(const char *domain, const char *dir) if (r == NULL) _ERR("appcore: setlocale() error"); - if (dir) { - if (__locale_dir) - free(__locale_dir); - __locale_dir = strdup(dir); - } - r = bindtextdomain(domain, dir); if (r == NULL) _ERR("appcore: bindtextdomain() error"); @@ -646,8 +850,16 @@ 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); +} + 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; @@ -656,14 +868,33 @@ 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 (__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.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); + } + } + } + + 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 r; + } } if (__context.ops.run) @@ -676,6 +907,13 @@ EXPORT_API void appcore_base_fini(void) { int i; + aul_status_update(STATUS_DYING); + 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) @@ -687,14 +925,15 @@ EXPORT_API void appcore_base_fini(void) __events = NULL; __fini_suspend_dbus_handler(); - aul_status_update(STATUS_DYING); - if (__context.ops.terminate) - __context.ops.terminate(__context.data); - 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) @@ -733,8 +972,11 @@ EXPORT_API int appcore_base_on_receive(aul_type type, bundle *b) __remove_suspend_timer(); } - if (__context.ops.control) - __context.ops.control(b, __context.data); + if (__context.ops.control) { + traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:RESET"); + __context.ops.control(b, __context.data); + traceEnd(TTRACE_TAG_APPLICATION_MANAGER); + } break; case AUL_RESUME: _DBG("[APP %d] AUL event: AUL_RESUME", getpid()); @@ -834,6 +1076,9 @@ EXPORT_API void appcore_base_on_set_event(enum appcore_base_event event) case APPCORE_BASE_EVENT_LANG_CHANGE: vconf_notify_key_changed(VCONFKEY_LANGSET, __on_language_change, NULL); break; + case APPCORE_BASE_EVENT_DEVICE_ORIENTATION_CHANGED: + __register_rotation_changed_event(); + break; case APPCORE_BASE_EVENT_REGION_CHANGE: r = vconf_notify_key_changed(VCONFKEY_REGIONFORMAT, __on_region_change, NULL); if (r < 0) @@ -864,6 +1109,9 @@ EXPORT_API void appcore_base_on_unset_event(enum appcore_base_event event) case APPCORE_BASE_EVENT_LANG_CHANGE: vconf_ignore_key_changed(VCONFKEY_LANGSET, __on_language_change); break; + case APPCORE_BASE_EVENT_DEVICE_ORIENTATION_CHANGED: + __unregister_rotation_changed_event(); + break; case APPCORE_BASE_EVENT_REGION_CHANGE: r = vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT, __on_region_change); if (r < 0) @@ -882,7 +1130,7 @@ EXPORT_API appcore_base_event_h appcore_base_add_event(enum appcore_base_event e { 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); } @@ -905,10 +1153,13 @@ 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); free(node); - if (!__exist_callback(event)) { + if (__context.dirty && !__exist_callback(event)) { if (__context.ops.unset_event) __context.ops.unset_event(event, __context.data); } @@ -924,6 +1175,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; } @@ -986,6 +1244,8 @@ 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;