Remove suspend timer when resuming app
[platform/core/appfw/app-core.git] / src / base / appcore_base.c
index d0d27ba..a4b4f73 100644 (file)
 #include <sensor_internal.h>
 #include <ttrace.h>
 #include <system_info.h>
+
 #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;
@@ -56,12 +60,14 @@ typedef struct _appcore_base_context {
        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 {
@@ -69,6 +75,8 @@ typedef struct _appcore_base_rotation {
        int lock;
        int ref;
        enum appcore_base_rm rm;
+       int charger_status;
+       bool initialized;
 } appcore_base_rotation;
 
 struct lang_info_s {
@@ -122,6 +130,70 @@ appcore_base_tizen_profile_t appcore_base_get_tizen_profile(void)
        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)
 {
@@ -129,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);
+               }
        }
 }
 
@@ -242,13 +320,9 @@ static void __auto_rotation_changed_cb(sensor_t sensor, unsigned int event_type,
        __invoke_callback((void *)&__rotation.rm, APPCORE_BASE_EVENT_DEVICE_ORIENTATION_CHANGED);
 }
 
-static void __unregister_rotation_changed_event(void)
+static void __fini_rotation(void)
 {
-       if (!__rotation.ref)
-               return;
-
-       __rotation.ref--;
-       if (__rotation.ref > 1)
+       if (!__rotation.initialized)
                return;
 
        vconf_ignore_key_changed(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, __lock_cb);
@@ -257,19 +331,17 @@ static void __unregister_rotation_changed_event(void)
        sensord_disconnect(__rotation.conn);
 
        __rotation.lock = 0;
-       __rotation.ref = 0;
+       __rotation.initialized = false;
 }
 
-static void __register_rotation_changed_event(void)
+static void __init_rotation(void)
 {
        sensor_t sensor;
        int lock;
        bool r;
 
-       if (__rotation.ref) {
-               __rotation.ref++;
+       if (__rotation.initialized)
                return;
-       }
 
        sensor = sensord_get_sensor(AUTO_ROTATION_SENSOR);
        __rotation.conn = sensord_connect(sensor);
@@ -299,6 +371,60 @@ static void __register_rotation_changed_event(void)
        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++;
 }
 
@@ -615,6 +741,7 @@ 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, "en_US.UTF-8");
@@ -740,7 +867,9 @@ 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) {
@@ -971,6 +1100,28 @@ EXPORT_API int appcore_base_set_i18n(const char *domain_name, const char *dir_na
        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;
@@ -1002,6 +1153,7 @@ EXPORT_API int appcore_base_init(appcore_base_ops ops, int argc, char **argv, vo
        }
 
        __verify_language();
+       __set_default_events();
        if (__context.ops.set_i18n)
                __context.ops.set_i18n(__context.data);
 
@@ -1026,6 +1178,7 @@ 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);
@@ -1039,11 +1192,16 @@ 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;
        }
 
+       __remove_suspend_timer();
+
        g_list_free_full(__events, free);
        __events = NULL;
 
@@ -1063,7 +1221,9 @@ EXPORT_API void appcore_base_fini(void)
 
 EXPORT_API int appcore_base_flush_memory(void)
 {
-       malloc_trim(0);
+       if (__context.ops.trim_memory)
+               __context.ops.trim_memory(__context.data);
+
        return 0;
 }
 
@@ -1110,8 +1270,10 @@ 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;
@@ -1154,7 +1316,7 @@ 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;
@@ -1171,6 +1333,8 @@ EXPORT_API int appcore_base_on_create(void)
 
 EXPORT_API int appcore_base_on_control(bundle *b)
 {
+       appcore_base_control_invoke(b);
+
        return 0;
 }
 
@@ -1183,28 +1347,13 @@ EXPORT_API int appcore_base_on_terminate()
 
 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_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)
-                       break;
-
-               vconf_notify_key_changed(VCONFKEY_REGIONFORMAT_TIME1224, __on_region_change, NULL);
-               break;
        case APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE:
                break;
 
@@ -1216,27 +1365,13 @@ 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_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)
-                       break;
-               vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT_TIME1224, __on_region_change);
-               break;
        case APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE:
                break;
        default:
@@ -1244,6 +1379,20 @@ 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)
 {
@@ -1262,6 +1411,12 @@ EXPORT_API appcore_base_event_h appcore_base_add_event(enum appcore_base_event e
        node->cb = cb;
        node->type = event;
        node->data = data;
+
+       if (event == APPCORE_BASE_EVENT_LANG_CHANGE ||
+                       event == APPCORE_BASE_EVENT_REGION_CHANGE)
+               node->prev_event = NULL;
+       else
+               node->prev_event = GINT_TO_POINTER(-1);
        __events = g_list_append(__events, node);
 
        return node;
@@ -1277,6 +1432,7 @@ EXPORT_API int appcore_base_remove_event(appcore_base_event_h handle)
 
        event = node->type;
        __events = g_list_remove(__events, node);
+       __unset_prev_event(&node->prev_event, event);
        free(node);
        if (__context.dirty && !__exist_callback(event)) {
                if (__context.ops.unset_event)
@@ -1325,6 +1481,26 @@ EXPORT_API void appcore_base_exit(void)
                __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);
@@ -1352,12 +1528,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)
@@ -1375,6 +1556,7 @@ EXPORT_API appcore_base_ops appcore_base_get_default_ops(void)
        ops.exit = NULL;
        ops.set_event = __on_set_event;
        ops.unset_event = __on_unset_event;
+       ops.trim_memory = __on_trim_memory;
 
        return ops;
 }