summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/alarm.h39
-rw-r--r--src/alarm-lib.c136
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(&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;