diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/appcore-agent.c | 305 | ||||
-rw-r--r-- | src/service_app_error.c | 23 | ||||
-rw-r--r-- | src/service_app_main.c | 490 | ||||
-rw-r--r-- | src/service_app_private.h | 34 |
4 files changed, 640 insertions, 212 deletions
diff --git a/src/appcore-agent.c b/src/appcore-agent.c index 87f6f7a..c29c799 100644 --- a/src/appcore-agent.c +++ b/src/appcore-agent.c @@ -27,11 +27,13 @@ #include <stdlib.h> #include <sys/types.h> #include <unistd.h> +#include <malloc.h> #include <Ecore.h> +#include <linux/limits.h> -#include <sysman.h> #include "aul.h" #include "appcore-agent.h" +#include <appcore-common.h> #include <app_control_internal.h> #include <dlog.h> #include <vconf.h> @@ -42,9 +44,24 @@ #define LOG_TAG "APPCORE_AGENT" +#define _ERR(fmt, arg...) LOGE(fmt, ##arg) +#define _INFO(fmt, arg...) LOGI(fmt, ##arg) +#define _DBG(fmt, arg...) LOGD(fmt, ##arg) #ifndef EXPORT_API -# define EXPORT_API __attribute__ ((visibility("default"))) +#define EXPORT_API __attribute__ ((visibility("default"))) +#endif + +#ifndef _ERR +#define _ERR(fmt, arg...) LOGE(fmt, ##arg) +#endif + +#ifndef _INFO +#define _INFO(...) LOGI(__VA_ARGS__) +#endif + +#ifndef _DBG +#define _DBG(...) LOGD(__VA_ARGS__) #endif #define _warn_if(expr, fmt, arg...) do { \ @@ -79,6 +96,10 @@ } \ } while (0) +#define APPID_MAX 256 +#define PKGNAME_MAX 256 +#define PATH_RES "/res" +#define PATH_LOCALE "/locale" static pid_t _pid; @@ -89,6 +110,8 @@ enum sys_event { SE_UNKNOWN, SE_LOWMEM, SE_LOWBAT, + SE_LANGCHG, + SE_REGIONCHG, SE_MAX }; @@ -114,11 +137,14 @@ enum agent_event { static enum appcore_agent_event to_ae[SE_MAX] = { - APPCORE_AGENT_EVENT_UNKNOWN, /* SE_UNKNOWN */ - APPCORE_AGENT_EVENT_LOW_MEMORY, /* SE_LOWMEM */ + APPCORE_AGENT_EVENT_UNKNOWN, /* SE_UNKNOWN */ + APPCORE_AGENT_EVENT_LOW_MEMORY, /* SE_LOWMEM */ APPCORE_AGENT_EVENT_LOW_BATTERY, /* SE_LOWBAT */ + APPCORE_AGENT_EVENT_LANG_CHANGE, /* SE_LANGCHG */ + APPCORE_AGENT_EVENT_REGION_CHANGE, /* SE_REGIONCHG */ }; +static int appcore_agent_event_initialized[SE_MAX] = {0}; enum cb_type { /* callback */ _CB_NONE, @@ -174,11 +200,13 @@ struct agent_appcore { static struct agent_appcore core; - static int __sys_lowmem_post(void *data, void *evt); static int __sys_lowmem(void *data, void *evt); static int __sys_lowbatt(void *data, void *evt); - +static int __sys_langchg_pre(void *data, void *evt); +static int __sys_langchg(void *data, void *evt); +static int __sys_regionchg_pre(void *data, void *evt); +static int __sys_regionchg(void *data, void *evt); static struct evt_ops evtops[] = { { @@ -191,9 +219,27 @@ static struct evt_ops evtops[] = { .type = _CB_VCONF, .key.vkey = VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, .vcb = __sys_lowbatt, - } + }, + { + .type = _CB_VCONF, + .key.vkey = VCONFKEY_LANGSET, + .vcb_pre = __sys_langchg_pre, + .vcb = __sys_langchg, + }, + { + .type = _CB_VCONF, + .key.vkey = VCONFKEY_REGIONFORMAT, + .vcb_pre = __sys_regionchg_pre, + .vcb = __sys_regionchg, + }, + { + .type = _CB_VCONF, + .key.vkey = VCONFKEY_REGIONFORMAT_TIME1224, + .vcb = __sys_regionchg, + }, }; +extern int app_control_create_event(bundle *data, struct app_control_s **app_control); static void __exit_loop(void *data) { @@ -352,6 +398,81 @@ static int __sys_lowbatt(void *data, void *evt) return 0; } +static int __sys_langchg_pre(void *data, void *evt) +{ + keynode_t *key = evt; + char *lang; + char *r; + + lang = vconf_keynode_get_str(key); + if (lang) { + setenv("LANG", lang, 1); + setenv("LC_MESSAGES", lang, 1); + + r = setlocale(LC_ALL, lang); + if (r == NULL) { + r = setlocale(LC_ALL, lang); + if (r) { + _DBG("*****appcore-agent setlocale=%s\n", r); + } + } + } + + return 0; +} + +static int __sys_langchg(void *data, void *evt) +{ + keynode_t *key = evt; + char *val; + + val = vconf_keynode_get_str(key); + + return __sys_do(data, (void *)val, SE_LANGCHG); +} + +static int __sys_regionchg_pre(void *data, void *evt) +{ + keynode_t *key = evt; + char *region; + char *r; + + region = vconf_keynode_get_str(key); + if (region) { + setenv("LC_CTYPE", region, 1); + setenv("LC_NUMERIC", region, 1); + setenv("LC_TIME", region, 1); + setenv("LC_COLLATE", region, 1); + setenv("LC_MONETARY", region, 1); + setenv("LC_PAPER", region, 1); + setenv("LC_NAME", region, 1); + setenv("LC_ADDRESS", region, 1); + setenv("LC_TELEPHONE", region, 1); + setenv("LC_MEASUREMENT", region, 1); + setenv("LC_IDENTIFICATION", region, 1); + + r = setlocale(LC_ALL, ""); + if (r != NULL) { + _DBG("*****appcore-agent setlocale=%s\n", r); + } + } + + return 0; +} + +static int __sys_regionchg(void *data, void *evt) +{ + keynode_t *key = evt; + char *val = NULL; + const char *name; + + name = vconf_keynode_get_name(key); + if (!strcmp(name, VCONFKEY_REGIONFORMAT)) + val = vconf_keynode_get_str(key); + + return __sys_do(data, (void *)val, SE_REGIONCHG); +} + static void __vconf_do(struct evt_ops *eo, keynode_t * key, void *data) { _ret_if(eo == NULL); @@ -374,7 +495,7 @@ static void __vconf_cb(keynode_t *key, void *data) name = vconf_keynode_get_name(key); _ret_if(name == NULL); - _DBG("[APP %d] vconf changed: %s", _pid, name); + SECURE_LOGD("[APP %d] vconf changed: %s", _pid, name); for (i = 0; i < sizeof(evtops) / sizeof(evtops[0]); i++) { struct evt_ops *eo = &evtops[i]; @@ -391,43 +512,76 @@ static void __vconf_cb(keynode_t *key, void *data) } } -static int __add_vconf(struct agent_appcore *ac) +static int __add_vconf(struct agent_appcore *ac, enum sys_event se) { - int i; int r; - for (i = 0; i < sizeof(evtops) / sizeof(evtops[0]); i++) { - struct evt_ops *eo = &evtops[i]; - - switch (eo->type) { - case _CB_VCONF: - r = vconf_notify_key_changed(eo->key.vkey, __vconf_cb, - ac); - break; - default: - /* do nothing */ + switch (se) { + case SE_LOWMEM: + r = vconf_notify_key_changed(VCONFKEY_SYSMAN_LOW_MEMORY, __vconf_cb, ac); + break; + case SE_LOWBAT: + r = vconf_notify_key_changed(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, __vconf_cb, ac); + break; + case SE_LANGCHG: + r = vconf_notify_key_changed(VCONFKEY_LANGSET, __vconf_cb, ac); + break; + case SE_REGIONCHG: + r = vconf_notify_key_changed(VCONFKEY_REGIONFORMAT, __vconf_cb, ac); + if (r < 0) break; - } + + r = vconf_notify_key_changed(VCONFKEY_REGIONFORMAT_TIME1224, __vconf_cb, ac); + break; + default: + r = -1; + break; } - return 0; + return r; } -static int __del_vconf(void) +static int __del_vconf(enum sys_event se) { - int i; int r; - for (i = 0; i < sizeof(evtops) / sizeof(evtops[0]); i++) { - struct evt_ops *eo = &evtops[i]; - - switch (eo->type) { - case _CB_VCONF: - r = vconf_ignore_key_changed(eo->key.vkey, __vconf_cb); - break; - default: - /* do nothing */ + switch (se) { + case SE_LOWMEM: + r = vconf_ignore_key_changed(VCONFKEY_SYSMAN_LOW_MEMORY, __vconf_cb); + break; + case SE_LOWBAT: + r = vconf_ignore_key_changed(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, __vconf_cb); + break; + case SE_LANGCHG: + r = vconf_ignore_key_changed(VCONFKEY_LANGSET, __vconf_cb); + break; + case SE_REGIONCHG: + r = vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT, __vconf_cb); + if (r < 0) break; + + r = vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT_TIME1224, __vconf_cb); + break; + default: + r = -1; + break; + } + + return r; +} + +static int __del_vconf_list(void) +{ + int r; + enum sys_event se; + + for (se = SE_LOWMEM; se < SE_MAX; se++) { + if (appcore_agent_event_initialized[se]) { + r = __del_vconf(se); + if (r < 0) + _ERR("Delete vconf callback failed"); + else + appcore_agent_event_initialized[se] = 0; } } @@ -449,6 +603,7 @@ static int __aul_handler(aul_type type, bundle *b, void *data) break; */ case AUL_TERMINATE: + case AUL_TERMINATE_BGAPP: ret = __agent_terminate(data); break; default: @@ -459,12 +614,39 @@ static int __aul_handler(aul_type type, bundle *b, void *data) return 0; } +static int __get_package_app_name(int pid, char **app_name) +{ + char *name_token = NULL; + char appid[APPID_MAX] = {0}; + int r; + + r = aul_app_get_appid_bypid(pid, appid, APPID_MAX); + if (r != AUL_R_OK) + return -1; + + if (appid[0] == '\0') + return -1; + + name_token = strrchr(appid, '.'); + if (name_token == NULL) + return -1; + + name_token++; + + *app_name = strdup(name_token); + if (*app_name == NULL) + return -1; + + return 0; +} + EXPORT_API int appcore_agent_set_event_callback(enum appcore_agent_event event, int (*cb) (void *, void *), void *data) { struct agent_appcore *ac = &core; struct sys_op *op; enum sys_event se; + int r = 0; for (se = SE_UNKNOWN; se < SE_MAX; se++) { if (event == to_ae[se]) @@ -482,13 +664,30 @@ EXPORT_API int appcore_agent_set_event_callback(enum appcore_agent_event event, op->func = cb; op->data = data; - return 0; + if (op->func && !appcore_agent_event_initialized[se]) { + r = __add_vconf(ac, se); + if (r < 0) + _ERR("Add vconf callback failed"); + else + appcore_agent_event_initialized[se] = 1; + } else if (!op->func && appcore_agent_event_initialized[se]) { + r = __del_vconf(se); + if (r < 0) + _ERR("Delete vconf callback failed"); + else + appcore_agent_event_initialized[se] = 0; + } + + return r; } EXPORT_API int appcore_agent_init(const struct agent_ops *ops, int argc, char **argv) { int r; + char *dirname; + char *app_name = NULL; + int pid; if (core.state != 0) { errno = EALREADY; @@ -500,11 +699,17 @@ EXPORT_API int appcore_agent_init(const struct agent_ops *ops, return -1; } - r = __add_vconf(&core); - if (r == -1) { - _ERR("Add vconf callback failed"); - goto err; - } + pid = getpid(); + r = __get_package_app_name(pid, &app_name); + if (r < 0) + return -1; + + dirname = aul_get_app_root_path(); + SECURE_LOGD("dir : %s", dirname); + SECURE_LOGD("app name : %s", app_name); + r = appcore_set_i18n(app_name, dirname); + free(app_name); + _retv_if(r == -1, -1); r = aul_launch_init(__aul_handler, &core); if (r < 0) { @@ -521,6 +726,7 @@ EXPORT_API int appcore_agent_init(const struct agent_ops *ops, return 0; err: + __del_vconf_list(); //__clear(&core); return -1; } @@ -542,33 +748,48 @@ static int __before_loop(struct agent_priv *agent, int argc, char **argv) if (agent->ops && agent->ops->create) { r = agent->ops->create(agent->ops->data); - if (r == -1) { + if (r < 0) { //appcore_exit(); + if (agent->ops && agent->ops->terminate) + agent->ops->terminate(agent->ops->data); errno = ECANCELED; return -1; } } agent->state = AGS_CREATED; - sysman_inform_backgrd(); return 0; } static void __after_loop(struct agent_priv *agent) { + __del_vconf_list(); priv.state = AGS_DYING; if (agent->ops && agent->ops->terminate) agent->ops->terminate(agent->ops->data); ecore_shutdown(); } - EXPORT_API int appcore_agent_terminate() { + __del_vconf_list(); ecore_main_loop_thread_safe_call_sync((Ecore_Data_Cb)__exit_loop, NULL); return 0; } +EXPORT_API int appcore_agent_terminate_without_restart() +{ + int ret; + + __del_vconf_list(); + ret = aul_terminate_pid_without_restart(getpid()); + if (ret < 0) { + SECURE_LOGD("request failed, but it will be terminated"); + ecore_main_loop_thread_safe_call_sync((Ecore_Data_Cb)__exit_loop, NULL); + } + + return 0; +} EXPORT_API int appcore_agent_main(int argc, char **argv, struct agentcore_ops *ops) diff --git a/src/service_app_error.c b/src/service_app_error.c index cb624c6..b2f7c26 100644 --- a/src/service_app_error.c +++ b/src/service_app_error.c @@ -15,41 +15,40 @@ */ -#include <stdio.h> -#include <stdlib.h> #include <string.h> #include <libintl.h> #include <dlog.h> +#include <app_common.h> -#include <service_app_private.h> +#include "service_app_private.h" #ifdef LOG_TAG #undef LOG_TAG #endif -#define LOG_TAG "TIZEN_N_AGENT" +#define LOG_TAG "CAPI_APPFW_APPLICATION" -static const char* service_app_error_to_string(service_app_error_e error) +static const char* service_app_error_to_string(app_error_e error) { switch (error) { - case SERVICE_APP_ERROR_NONE: + case APP_ERROR_NONE: return "NONE"; - case SERVICE_APP_ERROR_INVALID_PARAMETER: + case APP_ERROR_INVALID_PARAMETER: return "INVALID_PARAMETER"; - case SERVICE_APP_ERROR_OUT_OF_MEMORY: + case APP_ERROR_OUT_OF_MEMORY: return "OUT_OF_MEMORY"; - case SERVICE_APP_ERROR_INVALID_CONTEXT: + case APP_ERROR_INVALID_CONTEXT: return "INVALID_CONTEXT"; - case SERVICE_APP_ERROR_NO_SUCH_FILE: + case APP_ERROR_NO_SUCH_FILE: return "NO_SUCH_FILE"; - case SERVICE_APP_ERROR_ALREADY_RUNNING: + case APP_ERROR_ALREADY_RUNNING: return "ALREADY_RUNNING"; default : @@ -57,7 +56,7 @@ static const char* service_app_error_to_string(service_app_error_e error) } } -int service_app_error(service_app_error_e error, const char* function, const char *description) +int service_app_error(app_error_e error, const char* function, const char *description) { if (description) { diff --git a/src/service_app_main.c b/src/service_app_main.c index 3da99da..3155a5f 100644 --- a/src/service_app_main.c +++ b/src/service_app_main.c @@ -15,28 +15,112 @@ */ -#include <stdio.h> #include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> #include <bundle.h> #include <aul.h> #include <dlog.h> +#include <vconf-internal-keys.h> +#include <app_common.h> + #include <Eina.h> #include <appcore-agent.h> -#include <service_app_private.h> +#include "service_app_private.h" +#include "service_app_extension.h" + +#include <unistd.h> + #ifdef LOG_TAG #undef LOG_TAG #endif -#define LOG_TAG "TIZEN_N_AGENT" -#define SERVICE_APP_EVENT_MAX 2 +#ifndef TIZEN_PATH_MAX +#define TIZEN_PATH_MAX 1024 +#endif + + +#define LOG_TAG "CAPI_APPFW_APPLICATION" + +typedef enum { + SERVICE_APP_STATE_NOT_RUNNING, // The application has been launched or was running but was terminated + SERVICE_APP_STATE_CREATING, // The application is initializing the resources on service_app_create_cb callback + SERVICE_APP_STATE_RUNNING, // The application is running in the foreground and background +} service_app_state_e; + +static int _service_app_get_id(char **id) +{ + static char id_buf[TIZEN_PATH_MAX] = {0, }; + int ret = -1; + + if (id == NULL) + { + return service_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + if (id_buf[0] == '\0') + { + ret = aul_app_get_appid_bypid(getpid(), id_buf, sizeof(id_buf)); + + if (ret < 0) { + return service_app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "failed to get the application ID"); + } + } + + if (id_buf[0] == '\0') + { + return service_app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "failed to get the application ID"); + } + + *id = strdup(id_buf); + + if (*id == NULL) + { + return service_app_error(APP_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL); + } + + return APP_ERROR_NONE; +} + +static int _service_appget_package_app_name(const char *appid, char **name) +{ + char *name_token = NULL; + + if (appid == NULL) + { + return service_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + // com.vendor.name -> name + name_token = strrchr(appid, '.'); + + if (name_token == NULL) + { + return service_app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL); + } + + name_token++; + + *name = strdup(name_token); + + if (*name == NULL) + { + return service_app_error(APP_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL); + } + + return APP_ERROR_NONE; +} + +EXPORT_API void service_app_exit_without_restart(void) +{ + appcore_agent_terminate_without_restart(); +} + +#define SERVICE_APP_EVENT_MAX 5 +static Eina_List *handler_list[SERVICE_APP_EVENT_MAX] = {NULL, }; +static int handler_initialized = 0; +static int appcore_agent_initialized = 0; struct app_event_handler { app_event_type_e type; @@ -49,34 +133,13 @@ struct app_event_info { void *value; }; - -typedef enum { - SERVICE_APP_STATE_NOT_RUNNING, // The application has been launched or was running but was terminated - SERVICE_APP_STATE_CREATING, // The application is initializing the resources on service_app_create_cb callback - SERVICE_APP_STATE_RUNNING, // The application is running in the foreground and background -} service_app_state_e; - -typedef struct { +struct service_app_context { char *package; char *service_app_name; service_app_state_e state; service_app_lifecycle_callback_s *callback; void *data; -} service_app_context_s; - -typedef service_app_context_s *service_app_context_h; - -static int service_app_create(void *data); -static int service_app_terminate(void *data); -static int service_app_reset(app_control_h app_control, void *data); -static int service_app_low_memory(void *event_info, void *data); -static int service_app_low_battery(void *event_info, void *data); - -static void service_app_set_appcore_event_cb(service_app_context_h service_app_context); -static void service_app_unset_appcore_event_cb(void); - -static Eina_List *handler_list[SERVICE_APP_EVENT_MAX] = {NULL, }; -static int _initialized = 0; +}; static void _free_handler_list(void) { @@ -91,229 +154,340 @@ static void _free_handler_list(void) eina_shutdown(); } -EXPORT_API int service_app_main(int argc, char **argv, service_app_lifecycle_callback_s *callback, void *user_data) +static int _service_app_low_memory(void *event_info, void *data) { - service_app_context_s service_app_context = { - .state = SERVICE_APP_STATE_NOT_RUNNING, - .callback = callback, - .data = user_data - }; + Eina_List *l; + app_event_handler_h handler; + struct app_event_info event; - struct agentcore_ops appcore_context = { - .data = &service_app_context, - .create = service_app_create, - .terminate = service_app_terminate, - .app_control = service_app_reset, - }; + LOGI("service_app_low_memory"); - if (argc <= 0 || argv == NULL || callback == NULL) - { - return service_app_error(SERVICE_APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - } + event.type = APP_EVENT_LOW_MEMORY; + event.value = event_info; - if (callback->create == NULL) - { - return service_app_error(SERVICE_APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "service_app_create_cb() callback must be registered"); + EINA_LIST_FOREACH(handler_list[APP_EVENT_LOW_MEMORY], l, handler) { + handler->cb(&event, handler->data); } - if (service_app_context.state != SERVICE_APP_STATE_NOT_RUNNING) - { - return service_app_error(SERVICE_APP_ERROR_ALREADY_RUNNING, __FUNCTION__, NULL); - } + return APP_ERROR_NONE; +} - service_app_context.state = SERVICE_APP_STATE_CREATING; +static int _service_app_low_battery(void *event_info, void *data) +{ + Eina_List *l; + app_event_handler_h handler; + struct app_event_info event; - appcore_agent_main(argc, argv, &appcore_context); + LOGI("service_app_low_battery"); - return SERVICE_APP_ERROR_NONE; -} + event.type = APP_EVENT_LOW_BATTERY; + event.value = event_info; + EINA_LIST_FOREACH(handler_list[APP_EVENT_LOW_BATTERY], l, handler) { + handler->cb(&event, handler->data); + } -EXPORT_API void service_app_exit(void) -{ - appcore_agent_terminate(); + return APP_ERROR_NONE; } -EXPORT_API int service_app_add_event_handler(app_event_handler_h *event_handler, app_event_type_e event_type, app_event_cb callback, void *user_data) +static int _service_app_lang_changed(void *event_info, void *data) { + Eina_List *l; app_event_handler_h handler; - Eina_List *l_itr; + struct app_event_info event; - if (!_initialized) { - eina_init(); - _initialized = 1; + LOGI("service_app_lang_changed"); + + event.type = APP_EVENT_LANGUAGE_CHANGED; + event.value = event_info; + + EINA_LIST_FOREACH(handler_list[APP_EVENT_LANGUAGE_CHANGED], l, handler) { + handler->cb(&event, handler->data); } - if (event_handler == NULL || callback == NULL) - return service_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + return APP_ERROR_NONE; +} - if (event_type < APP_EVENT_LOW_MEMORY || event_type > APP_EVENT_LOW_BATTERY) - return service_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); +static int _service_app_region_changed(void *event_info, void *data) +{ + Eina_List *l; + app_event_handler_h handler; + struct app_event_info event; - EINA_LIST_FOREACH(handler_list[event_type], l_itr, handler) { - if (handler->cb == callback) - return service_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + if (event_info == NULL) { + LOGI("receive empy event, ignore it"); + return APP_ERROR_NONE; } - handler = calloc(1, sizeof(struct app_event_handler)); - if (!handler) - return service_app_error(APP_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL); + LOGI("service_app_region_changed"); - handler->type = event_type; - handler->cb = callback; - handler->data = user_data; - handler_list[event_type] = eina_list_append(handler_list[event_type], handler); + event.type = APP_EVENT_REGION_FORMAT_CHANGED; + event.value = event_info; - *event_handler = handler; + EINA_LIST_FOREACH(handler_list[APP_EVENT_REGION_FORMAT_CHANGED], l, handler) { + handler->cb(&event, handler->data); + } return APP_ERROR_NONE; } -EXPORT_API int service_app_remove_event_handler(app_event_handler_h event_handler) +static void _service_app_appcore_agent_set_event_cb(app_event_type_e event_type) { - app_event_handler_h handler; - app_event_type_e type; - Eina_List *l_itr; - Eina_List *l_next; - - if (event_handler == NULL) - return service_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + switch (event_type) { + case APP_EVENT_LOW_MEMORY: + appcore_agent_set_event_callback(APPCORE_AGENT_EVENT_LOW_MEMORY, _service_app_low_memory, NULL); + break; + case APP_EVENT_LOW_BATTERY: + appcore_agent_set_event_callback(APPCORE_AGENT_EVENT_LOW_BATTERY, _service_app_low_battery, NULL); + break; + case APP_EVENT_LANGUAGE_CHANGED: + appcore_agent_set_event_callback(APPCORE_AGENT_EVENT_LANG_CHANGE, _service_app_lang_changed, NULL); + break; + case APP_EVENT_REGION_FORMAT_CHANGED: + appcore_agent_set_event_callback(APPCORE_AGENT_EVENT_REGION_CHANGE, _service_app_region_changed, NULL); + break; + default: + break; + } +} - if (!_initialized) { - LOGI("handler list is not initialzed"); - return APP_ERROR_NONE; +static void _service_app_appcore_agent_unset_event_cb(app_event_type_e event_type) +{ + switch (event_type) { + case APP_EVENT_LOW_MEMORY: + appcore_agent_set_event_callback(APPCORE_AGENT_EVENT_LOW_MEMORY, NULL, NULL); + break; + case APP_EVENT_LOW_BATTERY: + appcore_agent_set_event_callback(APPCORE_AGENT_EVENT_LOW_BATTERY, NULL, NULL); + break; + case APP_EVENT_LANGUAGE_CHANGED: + appcore_agent_set_event_callback(APPCORE_AGENT_EVENT_LANG_CHANGE, NULL, NULL); + break; + case APP_EVENT_REGION_FORMAT_CHANGED: + appcore_agent_set_event_callback(APPCORE_AGENT_EVENT_REGION_CHANGE, NULL, NULL); + break; + default: + break; } +} - type = event_handler->type; - if (type < APP_EVENT_LOW_MEMORY || type > APP_EVENT_LOW_BATTERY) - return service_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); +static void _service_app_set_appcore_event_cb(void) +{ + app_event_type_e event; - EINA_LIST_FOREACH_SAFE(handler_list[type], l_itr, l_next, handler) { - if (handler == event_handler) { - free(handler); - handler_list[type] = eina_list_remove_list(handler_list[type], l_itr); - return APP_ERROR_NONE; - } + for (event = APP_EVENT_LOW_MEMORY; event <= APP_EVENT_REGION_FORMAT_CHANGED; event++) { + if (eina_list_count(handler_list[event]) > 0) + _service_app_appcore_agent_set_event_cb(event); } +} - return service_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "cannot find such handler"); +static void _service_app_unset_appcore_event_cb(void) +{ + app_event_type_e event; + + for (event = APP_EVENT_LOW_MEMORY; event <= APP_EVENT_REGION_FORMAT_CHANGED; event++) { + if (eina_list_count(handler_list[event]) > 0) + _service_app_appcore_agent_unset_event_cb(event); + } } -int service_app_create(void *data) +static int _service_app_create(void *data) { - service_app_context_h service_app_context = data; + struct service_app_context *app_context = data; service_app_create_cb create_cb; - if (service_app_context == NULL) + if (app_context == NULL) { - return service_app_error(SERVICE_APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL); + return service_app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL); } - service_app_set_appcore_event_cb(service_app_context); + appcore_agent_initialized = 1; + _service_app_set_appcore_event_cb(); - create_cb = service_app_context->callback->create; + create_cb = app_context->callback->create; - if (create_cb == NULL || create_cb(service_app_context->data) == false) + if (create_cb == NULL || create_cb(app_context->data) == false) { - return service_app_error(SERVICE_APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "service_app_create_cb() returns false"); + return service_app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "service_app_create_cb() returns false"); } - service_app_context->state = SERVICE_APP_STATE_RUNNING; + app_context->state = SERVICE_APP_STATE_RUNNING; - return SERVICE_APP_ERROR_NONE; + return APP_ERROR_NONE; } -int service_app_terminate(void *data) +static int _service_app_terminate(void *data) { - service_app_context_h service_app_context = data; + struct service_app_context *app_context = data; service_app_terminate_cb terminate_cb; - if (service_app_context == NULL) + if (app_context == NULL) { - return service_app_error(SERVICE_APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL); + return service_app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL); } - terminate_cb = service_app_context->callback->terminate; + terminate_cb = app_context->callback->terminate; if (terminate_cb != NULL) { - terminate_cb(service_app_context->data); + terminate_cb(app_context->data); } - service_app_unset_appcore_event_cb(); + _service_app_unset_appcore_event_cb(); - if (_initialized) + if (handler_initialized) _free_handler_list(); - return SERVICE_APP_ERROR_NONE; + return APP_ERROR_NONE; } - -int service_app_reset(app_control_h app_control, void *data) +static int _service_app_reset(app_control_h app_control, void *data) { - service_app_context_h service_app_context = data; - service_app_control_cb app_control_cb; + struct service_app_context *app_context = data; + service_app_control_cb service_cb; - if (service_app_context == NULL) + if (app_context == NULL) { - return service_app_error(SERVICE_APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL); + return service_app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL); } - app_control_cb = service_app_context->callback->app_control; + service_cb = app_context->callback->app_control; - if (app_control_cb != NULL) + if (service_cb != NULL) { - app_control_cb(app_control, service_app_context->data); + service_cb(app_control, app_context->data); } - return SERVICE_APP_ERROR_NONE; + return APP_ERROR_NONE; } - -int service_app_low_memory(void *event_info, void *data) +EXPORT_API int service_app_main(int argc, char **argv, service_app_lifecycle_callback_s *callback, void *user_data) { - Eina_List *l; - app_event_handler_h handler; - struct app_event_info event; + struct service_app_context app_context = { + .state = SERVICE_APP_STATE_NOT_RUNNING, + .callback = callback, + .data = user_data + }; - LOGI("service_app_low_memory"); + struct agentcore_ops appcore_context = { + .data = &app_context, + .create = _service_app_create, + .terminate = _service_app_terminate, + .app_control = _service_app_reset, + }; - event.type = APP_EVENT_LOW_MEMORY; - event.value = event_info; + if (argc <= 0 || argv == NULL || callback == NULL) + { + return service_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } - EINA_LIST_FOREACH(handler_list[APP_EVENT_LOW_MEMORY], l, handler) { - handler->cb(&event, handler->data); + if (callback->create == NULL) + { + return service_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "service_app_create_cb() callback must be registered"); + } + + if (app_context.state != SERVICE_APP_STATE_NOT_RUNNING) + { + return service_app_error(APP_ERROR_ALREADY_RUNNING, __FUNCTION__, NULL); + } + + + if (_service_app_get_id(&(app_context.package)) == APP_ERROR_NONE) + { + if (_service_appget_package_app_name(app_context.package, &(app_context.service_app_name)) != APP_ERROR_NONE) + { + free(app_context.package); + } } + app_context.state = SERVICE_APP_STATE_CREATING; + + appcore_agent_main(argc, argv, &appcore_context); + + if (app_context.service_app_name) + free(app_context.service_app_name); + if (app_context.package) + free(app_context.package); + return APP_ERROR_NONE; } -int service_app_low_battery(void *event_info, void *data) +EXPORT_API void service_app_exit(void) +{ + appcore_agent_terminate(); +} + +EXPORT_API int service_app_add_event_handler(app_event_handler_h *event_handler, app_event_type_e event_type, app_event_cb callback, void *user_data) { - Eina_List *l; app_event_handler_h handler; - struct app_event_info event; + Eina_List *l_itr; - LOGI("service_app_low_battery"); + if (!handler_initialized) { + eina_init(); + handler_initialized = 1; + } - event.type = APP_EVENT_LOW_BATTERY; - event.value = event_info; + if (event_handler == NULL || callback == NULL) + return service_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); - EINA_LIST_FOREACH(handler_list[APP_EVENT_LOW_BATTERY], l, handler) { - handler->cb(&event, handler->data); + if (event_type < APP_EVENT_LOW_MEMORY || event_type > APP_EVENT_REGION_FORMAT_CHANGED) + return service_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + + EINA_LIST_FOREACH(handler_list[event_type], l_itr, handler) { + if (handler->cb == callback) + return service_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); } + handler = calloc(1, sizeof(struct app_event_handler)); + if (!handler) + return service_app_error(APP_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL); + + handler->type = event_type; + handler->cb = callback; + handler->data = user_data; + + if (appcore_agent_initialized && eina_list_count(handler_list[event_type]) == 0) + _service_app_appcore_agent_set_event_cb(event_type); + + handler_list[event_type] = eina_list_append(handler_list[event_type], handler); + + *event_handler = handler; + return APP_ERROR_NONE; } -void service_app_set_appcore_event_cb(service_app_context_h service_app_context) +EXPORT_API int service_app_remove_event_handler(app_event_handler_h event_handler) { - appcore_agent_set_event_callback(APPCORE_AGENT_EVENT_LOW_MEMORY, service_app_low_memory, service_app_context); - appcore_agent_set_event_callback(APPCORE_AGENT_EVENT_LOW_BATTERY, service_app_low_battery, service_app_context); -} + app_event_handler_h handler; + app_event_type_e type; + Eina_List *l_itr; + Eina_List *l_next; -void service_app_unset_appcore_event_cb(void) -{ - appcore_agent_set_event_callback(APPCORE_AGENT_EVENT_LOW_MEMORY, NULL, NULL); - appcore_agent_set_event_callback(APPCORE_AGENT_EVENT_LOW_BATTERY, NULL, NULL); + if (event_handler == NULL) + return service_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + + if (!handler_initialized) { + LOGI("handler list is not initialzed"); + return APP_ERROR_NONE; + } + + type = event_handler->type; + if (type < APP_EVENT_LOW_MEMORY + || type > APP_EVENT_REGION_FORMAT_CHANGED + || type == APP_EVENT_DEVICE_ORIENTATION_CHANGED) + return service_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + + EINA_LIST_FOREACH_SAFE(handler_list[type], l_itr, l_next, handler) { + if (handler == event_handler) { + free(handler); + handler_list[type] = eina_list_remove_list(handler_list[type], l_itr); + + if (appcore_agent_initialized && eina_list_count(handler_list[type]) == 0) + _service_app_appcore_agent_unset_event_cb(type); + + return APP_ERROR_NONE; + } + } + + return service_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "cannot find such handler"); } diff --git a/src/service_app_private.h b/src/service_app_private.h new file mode 100644 index 0000000..ba58ecf --- /dev/null +++ b/src/service_app_private.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#ifndef __TIZEN_APPFW_SERVICE_APP_PRIVATE_H__ +#define __TIZEN_APPFW_SERVICE_APP_PRIVATE_H__ + +#include <service_app.h> +#include <app_common.h> + +#ifdef __cplusplus +extern "C" { +#endif + +int service_app_error(app_error_e error, const char* function, const char *description); + +#ifdef __cplusplus +} +#endif + +#endif /* __TIZEN_APPFW_SERVICE_APP_PRIVATE_H__ */ |