diff options
-rw-r--r-- | include/alarm.h | 39 | ||||
-rw-r--r-- | src/alarm-lib.c | 136 |
2 files changed, 172 insertions, 3 deletions
diff --git a/include/alarm.h b/include/alarm.h index 5222c60..2490bfb 100644 --- a/include/alarm.h +++ b/include/alarm.h @@ -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); diff --git a/src/alarm-lib.c b/src/alarm-lib.c index 2f03a06..1d5b18f 100644 --- a/src/alarm-lib.c +++ b/src/alarm-lib.c @@ -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(¤t_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(¤t_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(¤t_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; |