Support milliseconds accuracy api for platform module
authorJiwoong Im <jiwoong.im@samsung.com>
Wed, 2 Nov 2016 00:41:12 +0000 (09:41 +0900)
committerJiwoong Im <jiwoong.im@samsung.com>
Tue, 6 Dec 2016 22:59:51 +0000 (07:59 +0900)
- add alarmmgr_add_alarm_withcb_precision()

Change-Id: I02252d8fc273a09b7682fde66bd3bc5098d9cda1
Signed-off-by: Jiwoong Im <jiwoong.im@samsung.com>
include/alarm.h
src/alarm-lib.c

index 5222c60..2490bfb 100644 (file)
@@ -1591,9 +1591,48 @@ int alarmmgr_set_global(alarm_id_t alarm_id, bool global);
  */
 int alarmmgr_get_global(const alarm_id_t alarm_id, bool *global);
 
+/**
+ * This function adds an alarm and registers a callback function per an alarm.
+ * @param      [in]            alarm_type              ALARM_TYPE_DEFAULT or ALARM_TYPE_VOLATILE
+ * @param      [in]            trigger_at_time Time interval to be triggered from now(sec). an alarm also will be expired at triggering time
+ * @param      [in]            interval                        Interval between subsequent repeats of the alarm
+ * @param      [in]            handler                 The callback function invoked when the alarm is expired
+ * @param      [in]            user_param              Parameters of callback function
+ * @param      [out]   alarm_id                        The id of the alarm added
+ *
+ * @return     @c ALARMMGR_RESULT_SUCCESS on success,
+ *                     otherwise a negative error value
+ * @retval     #ALARMMGR_RESULT_SUCCESS        Successful
+ * @retval     #ERR_ALARM_INVALID_PARAM        Invalid parameter
+ * @retval     #ERR_ALARM_SYSTEM_FAIL  System failure
+ * @retval     #ERR_ALARM_NO_PERMISSION        Permission error
+ * @remark     When a process which registered an alarm is killed, the callback @c handler will not be used.
+ *                     In this case, calling the @c alarmmgr_set_cb() can register a callback again.
+ */
 int alarmmgr_add_alarm_withcb(int alarm_type, time_t trigger_at_time,
                                  time_t interval, alarm_cb_t handler, void *user_param, alarm_id_t *alarm_id);
 
+/**
+ * This function adds an alarm with milliseconds precision and registers a callback function per an alarm.
+ * @param      [in]            alarm_type              ALARM_TYPE_DEFAULT or ALARM_TYPE_VOLATILE
+ * @param      [in]            trigger_at_time Time interval to be triggered from now(sec, with accuracy in milliseconds). an alarm also will be expired at triggering time
+ * @param      [in]            interval                        Interval between subsequent repeats of the alarm
+ * @param      [in]            handler                 The callback function invoked when the alarm is expired
+ * @param      [in]            user_param              Parameters of callback function
+ * @param      [out]   alarm_id                        The id of the alarm added
+ *
+ * @return     @c ALARMMGR_RESULT_SUCCESS on success,
+ *                     otherwise a negative error value
+ * @retval     #ALARMMGR_RESULT_SUCCESS        Successful
+ * @retval     #ERR_ALARM_INVALID_PARAM        Invalid parameter
+ * @retval     #ERR_ALARM_SYSTEM_FAIL  System failure
+ * @retval     #ERR_ALARM_NO_PERMISSION        Permission error
+ * @remark     When a process which registered an alarm is killed, the callback @c handler will not be used.
+ *                     In this case, calling the @c alarmmgr_set_cb() can register a callback again.
+ */
+int alarmmgr_add_alarm_withcb_precision(int alarm_type, time_t trigger_at_time,
+                                 time_t interval, alarm_cb_t handler, void *user_param, alarm_id_t *alarm_id);
+
 int alarmmgr_add_periodic_alarm_withcb(int interval, periodic_method_e method, alarm_cb_t handler,
                void *user_param, alarm_id_t *alarm_id);
 
index 2f03a06..1d5b18f 100644 (file)
@@ -61,6 +61,7 @@ static int __alarmmgr_init_appsvc(void);
 
 typedef struct _alarm_cb_info_t {
        alarm_id_t alarm_id;
+       long msec;
        alarm_cb_t cb_func;
        void *priv_data;
        struct _alarm_cb_info_t *next;
@@ -95,6 +96,14 @@ static const GDBusInterfaceVTable interface_vtable = {
        NULL
 };
 
+void _initialize_alarm_info(alarm_info_t *alarm)
+{
+       memset(alarm, 0, sizeof(alarm_info_t));
+
+       alarm->mode.repeat = ALARM_REPEAT_MODE_ONCE;
+       alarm->alarm_type = ALARM_TYPE_DEFAULT;
+}
+
 static void __add_resultcb(alarm_id_t alarm_id, alarm_cb_t cb_func, void *data)
 {
        alarm_cb_info_t *info;
@@ -103,6 +112,24 @@ static void __add_resultcb(alarm_id_t alarm_id, alarm_cb_t cb_func, void *data)
        if (info == NULL)
                return;
        info->alarm_id = alarm_id;
+       info->msec = 0;
+       info->cb_func = cb_func;
+       info->priv_data = data;
+
+       info->next = alarmcb_head;
+       alarmcb_head = info;
+}
+
+static void __add_resultcb_include_millisec(alarm_id_t alarm_id,
+               long msec, alarm_cb_t cb_func, void *data)
+{
+       alarm_cb_info_t *info;
+
+       info = (alarm_cb_info_t *)malloc(sizeof(alarm_cb_info_t));
+       if (info == NULL)
+               return;
+       info->alarm_id = alarm_id;
+       info->msec = msec;
        info->cb_func = cb_func;
        info->priv_data = data;
 
@@ -149,10 +176,20 @@ static void __remove_resultcb(alarm_cb_info_t *info)
        }
 }
 
+static gboolean __handle_millisec_accuracy(gpointer data)
+{
+       alarm_cb_info_t *info = (alarm_cb_info_t *)data;
+       info->cb_func(info->alarm_id, info->priv_data);
+       return FALSE;
+}
+
 static void __handle_expiry_method_call(GDBusConnection *conn,
                const gchar *name, const gchar *path, const gchar *interface,
                const gchar *method, GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
 {
+       struct timeval current_time;
+       long msec;
+
        if (method && strcmp(method, "alarm_expired") == 0) {
                gchar *package_name = NULL;
                alarm_id_t alarm_id = 0;
@@ -164,8 +201,19 @@ static void __handle_expiry_method_call(GDBusConnection *conn,
                        alarm_context.alarm_handler(alarm_id, alarm_context.user_param);
 
                info = __find_resultcb(alarm_id);
-               if (info && info->cb_func)
-                       info->cb_func(alarm_id, info->priv_data);
+               if (info && info->cb_func) {
+                       if (info->msec > 0) {
+                               gettimeofday(&current_time, NULL);
+                               msec = info->msec - current_time.tv_usec / 1000;
+                               if (msec > 0)
+                                       g_timeout_add((guint)msec, __handle_millisec_accuracy, info);
+                               else
+                                       info->cb_func(alarm_id, info->priv_data);
+                       } else {
+                               ALARM_MGR_EXCEPTION_PRINT("[alarm-lib] Call expired callback");
+                               info->cb_func(alarm_id, info->priv_data);
+                       }
+               }
        }
        g_dbus_method_invocation_return_value(invocation, NULL);
 }
@@ -1066,6 +1114,8 @@ EXPORT_API int alarmmgr_add_alarm_appsvc(int alarm_type, time_t trigger_at_time,
                return ERR_ALARM_INVALID_PARAM;
        }
 
+       _initialize_alarm_info(&alarm_info);
+
        operation = appsvc_get_operation(b);
        if (operation == NULL)
                appsvc_set_operation(b, APPSVC_OPERATION_DEFAULT);
@@ -1238,7 +1288,7 @@ EXPORT_API int alarmmgr_add_alarm(int alarm_type, time_t trigger_at_time,
        alarm_info_t alarm_info;
        int ret;
 
-       ALARM_MGR_LOG_PRINT("[alarm-lib]:alarm_create() is called\n");
+       _initialize_alarm_info(&alarm_info);
 
        ret = __sub_init();
        if (ret < 0)
@@ -1338,6 +1388,8 @@ EXPORT_API int alarmmgr_add_alarm_withcb(int alarm_type, time_t trigger_at_time,
        alarm_info_t alarm_info;
        int ret = 0;
 
+       _initialize_alarm_info(&alarm_info);
+
        if (flag_appid_checked == 0) {
                if (aul_app_get_appid_bypid(getpid(), g_appid, sizeof(g_appid)) != AUL_R_OK) {
                        ALARM_MGR_EXCEPTION_PRINT("PID[%d] may not be app. Please call alarmmgr_init(caller name) in advance.", getpid());
@@ -1410,6 +1462,84 @@ EXPORT_API int alarmmgr_add_alarm_withcb(int alarm_type, time_t trigger_at_time,
        return ALARMMGR_RESULT_SUCCESS;
 }
 
+EXPORT_API int alarmmgr_add_alarm_withcb_precision(int alarm_type, time_t trigger_at_time,
+                                 time_t interval, alarm_cb_t handler, void *user_param, alarm_id_t *alarm_id)
+{
+       int error_code = 0;
+       struct timeval current_time = {.tv_sec = 0, .tv_usec = 0};
+       long msec;
+       struct tm duetime_tm;
+       alarm_info_t alarm_info;
+       int ret = 0;
+
+       gettimeofday(&current_time, NULL);
+
+       _initialize_alarm_info(&alarm_info);
+
+       if (flag_appid_checked == 0) {
+               if (aul_app_get_appid_bypid(getpid(), g_appid, sizeof(g_appid)) != AUL_R_OK)
+                       ALARM_MGR_EXCEPTION_PRINT("PID[%d] may not be app. Please call alarmmgr_init(caller name) in advance.", getpid());
+               else
+                       ALARM_MGR_LOG_PRINT("Get appid only once. appid[%s]", g_appid);
+
+               flag_appid_checked = 1;
+       }
+
+       ret = alarmmgr_init(g_appid);
+       if (ret < 0)
+               return ret;
+
+       if (alarm_id == NULL)
+               return ERR_ALARM_INVALID_PARAM;
+
+       if (trigger_at_time < 0)
+               return ERR_ALARM_INVALID_PARAM;
+
+       alarm_info.alarm_type = alarm_type;
+       alarm_info.alarm_type |= ALARM_TYPE_RELATIVE;
+       alarm_info.alarm_type |= ALARM_TYPE_WITHCB;
+
+       msec = current_time.tv_usec / 1000;
+
+       current_time.tv_sec += trigger_at_time;
+       alarm_info.reserved_info = current_time.tv_sec;
+
+       tzset();        /* Processes the TZ environment variable, and Set timezone, daylight, and tzname. */
+       localtime_r(&current_time.tv_sec, &duetime_tm);
+
+       alarm_info.start.year = duetime_tm.tm_year + 1900;
+       alarm_info.start.month = duetime_tm.tm_mon + 1;
+       alarm_info.start.day = duetime_tm.tm_mday;
+
+       alarm_info.end.year = 0;
+       alarm_info.end.month = 0;
+       alarm_info.end.day = 0;
+
+       alarm_info.start.hour = duetime_tm.tm_hour;
+       alarm_info.start.min = duetime_tm.tm_min;
+       alarm_info.start.sec = duetime_tm.tm_sec;
+
+       if (interval <= 0) {
+               alarm_info.mode.repeat = ALARM_REPEAT_MODE_ONCE;
+               alarm_info.mode.u_interval.interval = 0;
+       } else {
+               alarm_info.mode.repeat = ALARM_REPEAT_MODE_REPEAT;
+               alarm_info.mode.u_interval.interval = interval;
+       }
+
+       ALARM_MGR_EXCEPTION_PRINT("trigger_at_time(%d), start(%d-%d-%d, %02d:%02d:%02d:%02d), repeat(%d), interval(%d), type(%d)",
+               trigger_at_time, alarm_info.start.day, alarm_info.start.month, alarm_info.start.year,
+               alarm_info.start.hour, alarm_info.start.min, alarm_info.start.sec, msec,
+               alarm_info.mode.repeat, alarm_info.mode.u_interval.interval, alarm_info.alarm_type);
+
+       if (!_send_alarm_create(alarm_context, &alarm_info, alarm_id, "null","null", &error_code))
+               return error_code;
+
+       __add_resultcb_include_millisec(*alarm_id, msec, handler, user_param);
+
+       return ALARMMGR_RESULT_SUCCESS;
+}
+
 EXPORT_API int alarmmgr_remove_alarm(alarm_id_t alarm_id)
 {
        int error_code;