Add new api for system event handling from tizen_2.3
authorJiwoong Im <jiwoong.im@samsung.com>
Tue, 30 Dec 2014 11:30:59 +0000 (20:30 +0900)
committerJiwoong Im <jiwoong.im@samsung.com>
Tue, 30 Dec 2014 12:16:11 +0000 (21:16 +0900)
Remove system event callbacks except related application lifecycle.
The system event callbacks can be registered using ui_app_add_event_handler().
Multiple system event callbacks can be registered.
The application main loop api is renamed to ui_app_main.

app_event_get_xxx provides apis for getting system event information.

Change-Id: Ib24f8bb46038fc6a4b50c2516e846cfc27e7acfd
Signed-off-by: Jiwoong Im <jiwoong.im@samsung.com>
CMakeLists.txt
include/app.h
include/app_private.h
packaging/capi-appfw-application.spec
src/app_device.c
src/app_event.c [new file with mode: 0755]
src/app_main.c

index 1ce05ad..df7f5df 100644 (file)
@@ -10,7 +10,7 @@ SET(INC_DIR include)
 INCLUDE_DIRECTORIES(${INC_DIR})
 
 SET(requires "dlog bundle appcore-common appcore-efl aul ail appsvc notification elementary capi-base-common alarm-service sqlite3 libtzplatform-config")
-SET(pc_requires "capi-base-common")
+SET(pc_requires "capi-base-common vconf-internal-keys")
 
 INCLUDE(FindPkgConfig)
 pkg_check_modules(${fw_name} REQUIRED ${requires})
index 362178b..ca71b6f 100755 (executable)
@@ -224,6 +224,26 @@ typedef struct
        app_region_format_changed_cb region_format_changed; /**< The registered callback function is called when region format setting is changes. */
 } app_event_callback_s;
 
+/**
+ * @brief The structure type containing the set of callback functions for handling application lifecycle events.
+ * @details It is one of the input parameters of the ui_app_main() function.
+ *
+ * @see ui_app_main()
+ * @see app_create_cb()
+ * @see app_pause_cb()
+ * @see app_resume_cb()
+ * @see app_terminate_cb()
+ * @see service_cb()
+ */
+typedef struct
+{
+       app_create_cb create; /**< This callback function is called at the start of the application. */
+       app_terminate_cb terminate; /**< This callback function is called once after the main loop of the application exits. */
+       app_pause_cb pause; /**< This callback function is called each time the application is completely obscured by another application and becomes invisible to the user. */
+       app_resume_cb resume; /**< This callback function is called each time the application becomes visible to the user. */
+       app_service_cb service; /**< This callback function is called when another application sends the launch request to the application. */
+} ui_app_lifecycle_callback_s;
+
 
 /**
  * @brief Runs the main loop of application until app_efl_exit() is called
@@ -271,6 +291,160 @@ void app_efl_exit(void);
 
 
 /**
+ * @brief Enumeration for system events
+ */
+typedef enum
+{
+       APP_EVENT_LOW_MEMORY, /**< The low memory event */
+       APP_EVENT_LOW_BATTERY, /**< The low battery event */
+       APP_EVENT_LANGUAGE_CHANGED, /**< The system language changed event */
+       APP_EVENT_DEVICE_ORIENTATION_CHANGED, /**< The device orientation changed event */
+       APP_EVENT_REGION_FORMAT_CHANGED, /**< The region format changed event */
+} app_event_type_e;
+
+
+/**
+ * @brief Enumeration for low memory status.
+ */
+typedef enum
+{
+       APP_EVENT_LOW_MEMORY_NORMAL = 0x01, /**< Normal status */
+       APP_EVENT_LOW_MEMORY_SOFT_WARNING = 0x02, /**< Soft warning status */
+       APP_EVENT_LOW_MEMORY_HARD_WARNING = 0x04, /**< Hard warning status */
+} app_event_low_memory_status_e;
+
+
+/**
+ * @brief Enumeration for battery status.
+ */
+typedef enum
+{
+       APP_EVENT_LOW_BATTERY_POWER_OFF = 1, /**< The battery status is under 1% */
+       APP_EVENT_LOW_BATTERY_CRITICAL_LOW, /**< The battery status is under 5% */
+} app_event_low_battery_status_e;
+
+
+/**
+ * @brief The event handler that returned from add event handler function
+ *
+ * @see app_event_type_e
+ * @see app_add_event_handler
+ * @see app_remove_event_handler
+ * @see app_event_info_h
+ */
+typedef struct app_event_handler* app_event_handler_h;
+
+
+/**
+ * @brief The system event information
+ *
+ * @see app_event_get_low_memory_status
+ * @see app_event_get_low_battery_status
+ * @see app_event_get_language
+ * @see app_event_get_region_format
+ * @see app_event_get_device_orientation
+ */
+typedef struct app_event_info* app_event_info_h;
+
+
+/**
+ * @brief The system event callback function
+ *
+ * @param[in] event_info The system event information
+ * @param[in] user_data The user data passed from the add event handler function
+ *
+ * @see app_add_event_handler
+ * @see app_event_info_h
+ */
+typedef void (*app_event_cb)(app_event_info_h event_info, void *user_data);
+
+
+/**
+ * @brief Gets the low memory status from given event info
+ *
+ * @param[in] event_info The system event info
+ * @param[out] status The low memory status
+ *
+ * @return 0 on success, otherwise a negative error value
+ * @retval #APP_ERROR_NONE Successful
+ * @retval #APP_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #APP_ERROR_INVALID_CONTEXT Invalid event context
+ *
+ * @see app_event_info_h
+ * @see app_event_low_memory_status_e
+ */
+int app_event_get_low_memory_status(app_event_info_h event_info, app_event_low_memory_status_e *status);
+
+
+/**
+ * @brief Gets the low battery status from given event info
+ *
+ * @param[in] event_info The system event info
+ * @param[out] status The low battery status
+ *
+ * @return 0 on success, otherwise a negative error value
+ * @retval #APP_ERROR_NONE Successful
+ * @retval #APP_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #APP_ERROR_INVALID_CONTEXT Invalid event context
+ *
+ * @see app_event_info_h
+ * @see app_event_low_battery_status_e
+ */
+int app_event_get_low_battery_status(app_event_info_h event_info, app_event_low_battery_status_e *status);
+
+
+/**
+ * @brief Gets the language from given event info
+ *
+ * @remarks @a lang must be released using free()
+ * @param[in] event_info The system event info
+ * @param[out] lang The language changed
+ *
+ * @return 0 on success, otherwise a negative error value
+ * @retval #APP_ERROR_NONE Successful
+ * @retval #APP_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #APP_ERROR_INVALID_CONTEXT Invalid event context
+ *
+ * @see app_event_info_h
+ */
+int app_event_get_language(app_event_info_h event_info, char **lang);
+
+
+/**
+ * @brief Gets the region format from given event info
+ *
+ * @remarks @a region must be released using free()
+ * @param[in] event_info The system event info
+ * @param[out] region The region format changed
+ *
+ * @return 0 on success, otherwise a negative error value
+ * @retval #APP_ERROR_NONE Successful
+ * @retval #APP_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #APP_ERROR_INVALID_CONTEXT Invalid event context
+ *
+ * @see app_event_info_h
+ */
+int app_event_get_region_format(app_event_info_h event_info, char **region);
+
+
+/**
+ * @brief Gets the device orientation from given event info
+ *
+ * @param[in] event_info The system event info
+ * @param[out] orientation The device orientation changed
+ *
+ * @return 0 on success, otherwise a negative error value
+ * @retval #APP_ERROR_NONE Successful
+ * @retval #APP_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #APP_ERROR_INVALID_CONTEXT Invalid event context
+ *
+ * @see app_event_info_h
+ * @see app_device_orientation_e
+ */
+int app_event_get_device_orientation(app_event_info_h event_info, app_device_orientation_e *orientation);
+
+
+/**
  * @brief Gets the name of the application package.
  *
  * @remarks @a package must be released with free() by you.
@@ -388,6 +562,81 @@ app_device_orientation_e app_get_device_orientation(void);
  */
 void app_set_reclaiming_system_cache_on_pause(bool enable);
 
+/**
+ * @brief Runs the application's main loop until ui_app_exit() is called.
+ *
+ * @details This function is the main entry point of the Tizen application.
+ *          The app_create_cb() callback function is called to initialize the application before the main loop of application starts up.
+ *          After the app_create_cb() callback function returns true, the main loop starts up and the service_cb() callback function is subsequently called.
+ *          If the app_create_cb() callback function returns false, the main loop doesn't start up and app_terminate_cb() callback function is called.
+ *          This main loop supports event handling for the Ecore Main Loop.
+ *
+ * @param[in] argc The argument count
+ * @param[in] argv The argument vector
+ * @param[in] callback The set of callback functions to handle application lifecycle events
+ * @param[in] user_data The user data to be passed to the callback functions
+ *
+ * @return 0 on success, otherwise a negative error value
+ * @retval #APP_ERROR_NONE Successful
+ * @retval #APP_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #APP_ERROR_INVALID_CONTEXT The application is illegally launched, not launched by the launch system
+ * @retval #APP_ERROR_ALREADY_RUNNING The main loop already starts
+ *
+ * @see app_create_cb()
+ * @see app_terminate_cb()
+ * @see app_pause_cb()
+ * @see app_resume_cb()
+ * @see app_service_cb()
+ * @see ui_app_exit()
+ * @see #ui_app_lifecycle_callback_s
+ */
+int ui_app_main(int argc, char **argv, ui_app_lifecycle_callback_s *callback, void *user_data);
+
+
+/**
+ * @brief Exits the main loop of application.
+ *
+ * @details The main loop of application stops and app_terminate_cb() is invoked.
+ *
+ * @see ui_app_main()
+ * @see app_terminate_cb()
+ */
+void ui_app_exit(void);
+
+
+/**
+ * @brief Adds the system event handler
+ *
+ * @param[out] event_handler The event handler
+ * @param[in] event_type The system event type
+ * @param[in] callback The callback function
+ * @param[in] user_data The user data to be passed to the callback functions
+ *
+ * @return 0 on success, otherwise a negative error value
+ * @retval #APP_ERROR_NONE Successful
+ * @retval #APP_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #APP_ERROR_OUT_OF_MEMORY Out of memory
+ *
+ * @see app_event_type_e
+ * @see app_event_cb
+ * @see ui_app_remove_event_handler
+ */
+int ui_app_add_event_handler(app_event_handler_h *event_handler, app_event_type_e event_type, app_event_cb callback, void *user_data);
+
+
+/**
+ * @brief Removes registered event handler
+ *
+ * @param[in] event_handler The event handler
+ *
+ * @return 0 on success, otherwise a negative error value
+ * @retval #APP_ERROR_NONE Successful
+ * @retval #APP_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @see ui_app_add_event_handler
+ */
+int ui_app_remove_event_handler(app_event_handler_h event_handler);
+
 
 /**
  * @}
@@ -396,5 +645,4 @@ void app_set_reclaiming_system_cache_on_pause(bool enable);
 #ifdef __cplusplus
 }
 #endif
-
 #endif /* __TIZEN_APPFW_APP_H__ */
index c3a6a15..52db85c 100755 (executable)
@@ -43,6 +43,19 @@ extern "C" {
 #define PATH_FMT_RO_RES_DIR "/res"
 #define PATH_FMT_RO_LOCALE_DIR "/local"
 
+struct app_event_handler {
+       app_event_type_e type;
+       app_event_cb cb;
+       void *data;
+};
+
+struct app_event_info {
+       app_event_type_e type;
+       void *value;
+};
+
+app_device_orientation_e app_convert_appcore_rm(enum appcore_rm rm);
+
 typedef void (*app_finalizer_cb) (void *data);
 
 int app_error(app_error_e error, const char* function, const char *description);
index 8968348..59444c9 100755 (executable)
@@ -20,6 +20,7 @@ BuildRequires:  pkgconfig(alarm-service)
 BuildRequires:  pkgconfig(capi-base-common)
 BuildRequires:  pkgconfig(sqlite3)
 BuildRequires:  pkgconfig(libtzplatform-config)
+BuildRequires:  pkgconfig(vconf-internal-keys)
 
 %description
 An Application library in SLP C API package.
index 8b6215d..a28c3f9 100755 (executable)
 
 #define LOG_TAG "CAPI_APPFW_APPLICATION"
 
-app_device_orientation_e app_convert_appcore_rm(enum appcore_rm rm)
-{
-       app_device_orientation_e dev_orientation;
-
-       switch (rm)
-       {
-       case APPCORE_RM_PORTRAIT_NORMAL:
-               dev_orientation = APP_DEVICE_ORIENTATION_0;
-               break;
-               
-       case APPCORE_RM_PORTRAIT_REVERSE:
-               dev_orientation = APP_DEVICE_ORIENTATION_180;
-               break;
-               
-       case APPCORE_RM_LANDSCAPE_NORMAL:
-               dev_orientation = APP_DEVICE_ORIENTATION_270;
-               break;
-               
-       case APPCORE_RM_LANDSCAPE_REVERSE:
-               dev_orientation = APP_DEVICE_ORIENTATION_90;
-               break;
-
-       default:
-               dev_orientation = APP_DEVICE_ORIENTATION_0;
-               break;
-       }
-
-       return dev_orientation;
-}
-
 app_device_orientation_e app_get_device_orientation(void)
 {
        enum appcore_rm rm;
diff --git a/src/app_event.c b/src/app_event.c
new file mode 100755 (executable)
index 0000000..b07645f
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * 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.
+ */
+
+#include <string.h>
+
+#include <vconf-internal-keys.h>
+#include <app.h>
+#include <app_private.h>
+
+app_device_orientation_e app_convert_appcore_rm(enum appcore_rm rm)
+{
+       app_device_orientation_e dev_orientation;
+
+       switch (rm)
+       {
+       case APPCORE_RM_PORTRAIT_NORMAL:
+               dev_orientation = APP_DEVICE_ORIENTATION_0;
+               break;
+
+       case APPCORE_RM_PORTRAIT_REVERSE:
+               dev_orientation = APP_DEVICE_ORIENTATION_180;
+               break;
+
+       case APPCORE_RM_LANDSCAPE_NORMAL:
+               dev_orientation = APP_DEVICE_ORIENTATION_270;
+               break;
+
+       case APPCORE_RM_LANDSCAPE_REVERSE:
+               dev_orientation = APP_DEVICE_ORIENTATION_90;
+               break;
+
+       default:
+               dev_orientation = APP_DEVICE_ORIENTATION_0;
+               break;
+       }
+
+       return dev_orientation;
+}
+
+static int _app_convert_low_memory(void *val)
+{
+       switch (*(int *)val) {
+       case VCONFKEY_SYSMAN_LOW_MEMORY_NORMAL:
+               return APP_EVENT_LOW_MEMORY_NORMAL;
+       case VCONFKEY_SYSMAN_LOW_MEMORY_SOFT_WARNING:
+               return APP_EVENT_LOW_MEMORY_SOFT_WARNING;
+       case VCONFKEY_SYSMAN_LOW_MEMORY_HARD_WARNING:
+               return APP_EVENT_LOW_MEMORY_HARD_WARNING;
+       default:
+               return -1;
+       }
+}
+
+static int _app_convert_low_battery(void *val)
+{
+       switch (*(int *)val) {
+       case VCONFKEY_SYSMAN_BAT_POWER_OFF:
+               return APP_EVENT_LOW_BATTERY_POWER_OFF;
+       case VCONFKEY_SYSMAN_BAT_CRITICAL_LOW:
+               return APP_EVENT_LOW_BATTERY_CRITICAL_LOW;
+       default:
+               return -1;
+       }
+}
+
+int app_event_get_low_memory_status(app_event_info_h event_info, app_event_low_memory_status_e *status)
+{
+       int ret;
+
+       if (event_info == NULL || status == NULL)
+               return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "null parameter");
+
+       if (event_info->type != APP_EVENT_LOW_MEMORY)
+               return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "event type mismatching");
+
+       ret = _app_convert_low_memory(event_info->value);
+       if (ret < 0)
+               return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "invalid event info");
+
+       *status = ret;
+
+       return APP_ERROR_NONE;
+}
+
+int app_event_get_low_battery_status(app_event_info_h event_info, app_event_low_battery_status_e *status)
+{
+       int ret;
+
+       if (event_info == NULL || status == NULL)
+               return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "null parameter");
+
+       if (event_info->type != APP_EVENT_LOW_BATTERY)
+               return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "event type mismatching");
+
+       ret = _app_convert_low_battery(event_info->value);
+       if (ret < 0)
+               return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "invalid event info");
+
+       *status = ret;
+
+       return APP_ERROR_NONE;
+}
+
+int app_event_get_language(app_event_info_h event_info, char **lang)
+{
+       if (event_info == NULL || lang == NULL)
+               return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "null parameter");
+
+       if (event_info->type != APP_EVENT_LANGUAGE_CHANGED)
+               return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "event type mismatching");
+
+       *lang = strdup(event_info->value);
+
+       return APP_ERROR_NONE;
+}
+
+int app_event_get_region_format(app_event_info_h event_info, char **region)
+{
+       if (event_info == NULL || region == NULL)
+               return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "null parameter");
+
+       if (event_info->type != APP_EVENT_REGION_FORMAT_CHANGED)
+               return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "event type mismatching");
+
+       *region = strdup(event_info->value);
+
+       return APP_ERROR_NONE;
+}
+
+int app_event_get_device_orientation(app_event_info_h event_info, app_device_orientation_e *orientation)
+{
+       if (event_info == NULL || orientation == NULL)
+               return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "null parameter");
+
+       if (event_info->type != APP_EVENT_DEVICE_ORIENTATION_CHANGED)
+               return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "event type mismatching");
+
+       *orientation = app_convert_appcore_rm(*(enum appcore_rm *)(event_info->value));
+
+       return APP_ERROR_NONE;
+}
+
index 1b58f72..24079a2 100755 (executable)
@@ -62,11 +62,11 @@ static int app_appcore_resume(void *data);
 static int app_appcore_terminate(void *data);
 static int app_appcore_reset(bundle *appcore_bundle, void *data);
 
-static int app_appcore_low_memory(void *data);
-static int app_appcore_low_battery(void *data);
-static int app_appcore_rotation_event(enum appcore_rm rm, void *data);
-static int app_appcore_lang_changed(void *data);
-static int app_appcore_region_changed(void *data);
+static int app_appcore_low_memory(void *event, void *data);
+static int app_appcore_low_battery(void *evnet, void *data);
+static int app_appcore_rotation_event(void *event, enum appcore_rm rm, void *data);
+static int app_appcore_lang_changed(void *evnet, void *data);
+static int app_appcore_region_changed(void *event, void *data);
 
 static void app_set_appcore_event_cb(app_context_h app_context);
 static void app_unset_appcore_event_cb(void);
@@ -260,7 +260,7 @@ int app_appcore_reset(bundle *appcore_bundle, void *data)
 }
 
 
-int app_appcore_low_memory(void *data)
+int app_appcore_low_memory(void *event_info, void *data)
 {
        app_context_h app_context = data;
        app_low_memory_cb low_memory_cb;
@@ -280,7 +280,7 @@ int app_appcore_low_memory(void *data)
        return APP_ERROR_NONE;
 }
 
-int app_appcore_low_battery(void *data)
+int app_appcore_low_battery(void *event_info, void *data)
 {
        app_context_h app_context = data;
        app_low_battery_cb low_battery_cb;
@@ -300,7 +300,7 @@ int app_appcore_low_battery(void *data)
        return APP_ERROR_NONE;
 }
 
-int app_appcore_rotation_event(enum appcore_rm rm, void *data)
+int app_appcore_rotation_event(void *event_info, enum appcore_rm rm, void *data)
 {
        app_context_h app_context = data;
        app_device_orientation_cb device_orientation_cb;
@@ -324,7 +324,7 @@ int app_appcore_rotation_event(enum appcore_rm rm, void *data)
        return APP_ERROR_NONE;
 }
 
-int app_appcore_lang_changed(void *data)
+int app_appcore_lang_changed(void *event_info, void *data)
 {
        app_context_h app_context = data;
        app_language_changed_cb lang_changed_cb;
@@ -344,7 +344,7 @@ int app_appcore_lang_changed(void *data)
        return APP_ERROR_NONE;
 }
 
-int app_appcore_region_changed(void *data)
+int app_appcore_region_changed(void *event_info, void *data)
 {
        app_context_h app_context = data;
        app_region_format_changed_cb region_changed_cb;
@@ -401,3 +401,364 @@ void app_unset_appcore_event_cb(void)
        appcore_set_event_callback(APPCORE_EVENT_LANG_CHANGE, NULL, NULL);
        appcore_set_event_callback(APPCORE_EVENT_REGION_CHANGE, NULL, NULL);
 }
+
+#define UI_APP_EVENT_MAX 5
+static Eina_List *handler_list[UI_APP_EVENT_MAX] = {NULL, };
+static int _initialized = 0;
+
+struct ui_app_context {
+       char *package;
+       char *app_name;
+       app_state_e state;
+       ui_app_lifecycle_callback_s *callback;
+       void *data;
+};
+
+static void _free_handler_list(void)
+{
+       int i;
+       app_event_handler_h handler;
+
+       for (i = 0; i < UI_APP_EVENT_MAX; i++) {
+               EINA_LIST_FREE(handler_list[i], handler)
+                       free(handler);
+       }
+
+       eina_shutdown();
+}
+
+static int _ui_app_appcore_low_memory(void *event_info, void *data)
+{
+       Eina_List *l;
+       app_event_handler_h handler;
+       struct app_event_info event;
+
+       LOGI("_app_appcore_low_memory");
+
+       event.type = APP_EVENT_LOW_MEMORY;
+       event.value = event_info;
+
+       EINA_LIST_FOREACH(handler_list[APP_EVENT_LOW_MEMORY], l, handler) {
+               handler->cb(&event, handler->data);
+       }
+
+       return APP_ERROR_NONE;
+}
+
+static int _ui_app_appcore_low_battery(void *event_info, void *data)
+{
+       Eina_List *l;
+       app_event_handler_h handler;
+       struct app_event_info event;
+
+       LOGI("_ui_app_appcore_low_battery");
+
+       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);
+       }
+
+       return APP_ERROR_NONE;
+}
+
+static int _ui_app_appcore_rotation_event(void *event_info, enum appcore_rm rm, void *data)
+{
+       Eina_List *l;
+       app_event_handler_h handler;
+       struct app_event_info event;
+
+       LOGI("_ui_app_appcore_rotation_event");
+
+       event.type = APP_EVENT_DEVICE_ORIENTATION_CHANGED;
+       event.value = event_info;
+
+       EINA_LIST_FOREACH(handler_list[APP_EVENT_DEVICE_ORIENTATION_CHANGED], l, handler) {
+               handler->cb(&event, handler->data);
+       }
+
+       return APP_ERROR_NONE;
+}
+
+static int _ui_app_appcore_lang_changed(void *event_info, void *data)
+{
+       Eina_List *l;
+       app_event_handler_h handler;
+       struct app_event_info event;
+
+       LOGI("_ui_app_appcore_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);
+       }
+
+       return APP_ERROR_NONE;
+}
+
+static int _ui_app_appcore_region_changed(void *event_info, void *data)
+{
+       Eina_List *l;
+       app_event_handler_h handler;
+       struct app_event_info event;
+
+       if (event_info == NULL) {
+               LOGI("receive empty event, ignore it");
+               return APP_ERROR_NONE;
+       }
+
+       LOGI("_ui_app_appcore_region_changed");
+
+       event.type = APP_EVENT_REGION_FORMAT_CHANGED;
+       event.value = event_info;
+
+       EINA_LIST_FOREACH(handler_list[APP_EVENT_REGION_FORMAT_CHANGED], l, handler) {
+               handler->cb(&event, handler->data);
+       }
+
+       return APP_ERROR_NONE;
+}
+
+
+static void _ui_app_set_appcore_event_cb(void)
+{
+       appcore_set_event_callback(APPCORE_EVENT_LOW_MEMORY, _ui_app_appcore_low_memory, NULL);
+       appcore_set_event_callback(APPCORE_EVENT_LOW_BATTERY, _ui_app_appcore_low_battery, NULL);
+       appcore_set_rotation_cb(_ui_app_appcore_rotation_event, NULL);
+       appcore_set_event_callback(APPCORE_EVENT_LANG_CHANGE, _ui_app_appcore_lang_changed, NULL);
+       appcore_set_event_callback(APPCORE_EVENT_REGION_CHANGE, _ui_app_appcore_region_changed, NULL);
+}
+
+static void _ui_app_unset_appcore_event_cb(void)
+{
+       appcore_set_event_callback(APPCORE_EVENT_LOW_MEMORY, NULL, NULL);
+       appcore_set_event_callback(APPCORE_EVENT_LOW_BATTERY, NULL, NULL);
+       appcore_unset_rotation_cb();
+       appcore_set_event_callback(APPCORE_EVENT_LANG_CHANGE, NULL, NULL);
+       appcore_set_event_callback(APPCORE_EVENT_REGION_CHANGE, NULL, NULL);
+}
+
+static int _ui_app_appcore_create(void *data)
+{
+       LOGI("app_appcore_create");
+       struct ui_app_context *app_context = data;
+       app_create_cb create_cb;
+
+       if (app_context == NULL)
+               return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL);
+
+       _ui_app_set_appcore_event_cb();
+
+       create_cb = app_context->callback->create;
+
+       if (create_cb == NULL || create_cb(app_context->data) == false)
+               return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "app_create_cb() returns false");
+
+       app_context->state = APP_STATE_RUNNING;
+
+       return APP_ERROR_NONE;
+}
+
+static int _ui_app_appcore_terminate(void *data)
+{
+       LOGI("app_appcore_terminate");
+       struct ui_app_context *app_context = data;
+       app_terminate_cb terminate_cb;
+
+       if (app_context == NULL)
+               return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL);
+
+       terminate_cb = app_context->callback->terminate;
+
+       if (terminate_cb != NULL)
+               terminate_cb(app_context->data);
+
+       _ui_app_unset_appcore_event_cb();
+
+       app_finalizer_execute();
+
+       if (_initialized) {
+               _free_handler_list();
+               _initialized = 0;
+       }
+
+       return APP_ERROR_NONE;
+}
+
+static int _ui_app_appcore_pause(void *data)
+{
+       LOGI("app_appcore_pause");
+       struct ui_app_context *app_context = data;
+       app_pause_cb pause_cb;
+
+       if (app_context == NULL)
+               return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL);
+
+       pause_cb = app_context->callback->pause;
+
+       if (pause_cb != NULL)
+               pause_cb(app_context->data);
+
+       return APP_ERROR_NONE;
+}
+
+static int _ui_app_appcore_resume(void *data)
+{
+       LOGI("app_appcore_resume");
+       struct ui_app_context *app_context = data;
+       app_resume_cb resume_cb;
+
+       if (app_context == NULL)
+               return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL);
+
+       resume_cb = app_context->callback->resume;
+
+       if (resume_cb != NULL)
+               resume_cb(app_context->data);
+
+       return APP_ERROR_NONE;
+}
+
+
+static int _ui_app_appcore_reset(bundle *appcore_bundle, void *data)
+{
+       LOGI("app_appcore_reset");
+       struct ui_app_context *app_context = data;
+       app_service_cb callback;
+       service_h service;
+
+       if (app_context == NULL)
+               return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL);
+
+       if (service_create_event(appcore_bundle, &service) != APP_ERROR_NONE)
+               return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "failed to create a service handle from the bundle");
+
+       callback = app_context->callback->service;
+
+       if (callback != NULL)
+               callback(service, app_context->data);
+
+       service_destroy(service);
+
+       return APP_ERROR_NONE;
+}
+
+int ui_app_main(int argc, char **argv, ui_app_lifecycle_callback_s *callback, void *user_data)
+{
+       struct ui_app_context app_context = {
+               .package = NULL,
+               .app_name = NULL,
+               .state = APP_STATE_NOT_RUNNING,
+               .callback = callback,
+               .data = user_data
+       };
+
+       struct appcore_ops appcore_context = {
+               .data = &app_context,
+               .create = _ui_app_appcore_create,
+               .terminate = _ui_app_appcore_terminate,
+               .pause = _ui_app_appcore_pause,
+               .resume = _ui_app_appcore_resume,
+               .reset = _ui_app_appcore_reset,
+       };
+
+       if (argc < 1 || argv == NULL || callback == NULL)
+               return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
+
+       if (callback->create == NULL)
+               return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "app_create_cb() callback must be registered");
+
+       if (app_context.state != APP_STATE_NOT_RUNNING)
+               return app_error(APP_ERROR_ALREADY_RUNNING, __FUNCTION__, NULL);
+
+       if (app_get_id(&(app_context.package)) != APP_ERROR_NONE)
+               return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "failed to get the package");
+
+       if (app_get_package_app_name(app_context.package, &(app_context.app_name)) != APP_ERROR_NONE) {
+               free(app_context.package);
+               return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "failed to get the package's app name");
+       }
+
+       app_context.state = APP_STATE_CREATING;
+
+       LOGI("app_efl_main");
+       appcore_efl_main(app_context.app_name, &argc, &argv, &appcore_context);
+
+       free(app_context.package);
+       free(app_context.app_name);
+
+       return APP_ERROR_NONE;
+}
+
+void ui_app_exit(void)
+{
+       app_efl_exit();
+}
+
+int ui_app_add_event_handler(app_event_handler_h *event_handler, app_event_type_e event_type, app_event_cb callback, void *user_data)
+{
+       app_event_handler_h handler;
+       Eina_List *l_itr;
+
+       if (!_initialized) {
+               eina_init();
+               _initialized = 1;
+       }
+
+       if (event_handler == NULL || callback == NULL)
+               return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "null parameter");
+
+       if (event_type < APP_EVENT_LOW_MEMORY || event_type > APP_EVENT_REGION_FORMAT_CHANGED)
+               return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid event type");
+
+       EINA_LIST_FOREACH(handler_list[event_type], l_itr, handler) {
+               if (handler->cb == callback)
+                       return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "already registered");
+       }
+
+       handler = calloc(1, sizeof(struct app_event_handler));
+       if (!handler)
+               return app_error(APP_ERROR_OUT_OF_MEMORY, __FUNCTION__, "failed to create handler");
+
+       handler->type = event_type;
+       handler->cb = callback;
+       handler->data = user_data;
+       handler_list[event_type] = eina_list_append(handler_list[event_type], handler);
+
+       *event_handler = handler;
+
+       return APP_ERROR_NONE;
+}
+
+int ui_app_remove_event_handler(app_event_handler_h event_handler)
+{
+       app_event_handler_h handler;
+       app_event_type_e type;
+       Eina_List *l_itr;
+       Eina_List *l_next;
+
+       if (event_handler == NULL)
+               return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "handler is null");
+
+       if (!_initialized) {
+               LOGI("handler list is not initialized");
+               return APP_ERROR_NONE;
+       }
+
+       type = event_handler->type;
+       if (type < APP_EVENT_LOW_MEMORY || type > APP_EVENT_REGION_FORMAT_CHANGED)
+               return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid handler");
+
+       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;
+               }
+       }
+
+       return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "cannot find such handler");
+}