- Add alarmmgr_add_alarm_precision().
This api support non-volatile milliseconds accuracy alarm.
Change-Id: Ia20c3eed30ee8190176b8dd4e6f299dc81b4b53d
Signed-off-by: Jiwoong Im <jiwoong.im@samsung.com>
char *query = sqlite3_mprintf("insert into alarmmgr( alarm_id, start,\
end, uid, pid, global, is_disabled, caller_pkgid, callee_pkgid, app_unique_name,\
app_service_name, app_service_name_mod, bundle, noti_len, noti, year,\
- month, day, hour, min, sec, day_of_week, repeat,\
+ month, day, hour, min, sec, msec, day_of_week, repeat,\
alarm_type, reserved_info, dst_service_name, dst_service_name_mod)\
- values (%d,%d,%d,%d,%d,%d,0,%Q,%Q,%Q,%Q,%Q,%Q,%d,%Q,%d,%d,%d,%d,%d,%d,%d,%d,\
+ values (%d,%d,%d,%d,%d,%d,0,%Q,%Q,%Q,%Q,%Q,%Q,%d,%Q,%d,%d,%d,%d,%d,%d,%d,%d,%d,\
%d,%d,%Q,%Q)",\
__alarm_info->alarm_id,
(int)__alarm_info->start,
start->hour,
start->min,
start->sec,
+ alarm_info->msec,
mode->u_interval.day_of_week,
mode->repeat,
alarm_info->alarm_type,
char *query = sqlite3_mprintf("update alarmmgr set start=%d, end=%d,\
uid=%d, pid=%d, global=%d, is_disabled=0, caller_pkgid=%Q, callee_pkgid=%Q, app_unique_name=%Q, app_service_name=%Q, app_service_name_mod=%Q,\
- bundle=%Q, noti_len=%d, noti=%Q, year=%d, month=%d, day=%d, hour=%d, min=%d, sec=%d,\
+ bundle=%Q, noti_len=%d, noti=%Q, year=%d, month=%d, day=%d, hour=%d, min=%d, sec=%d, msec=%d,\
day_of_week=%d, repeat=%d, alarm_type=%d,\
reserved_info=%d, dst_service_name=%Q, dst_service_name_mod=%Q\
where alarm_id=%d",\
start->hour,
start->min,
start->sec,
+ alarm_info->msec,
mode->u_interval.day_of_week,
mode->repeat,
alarm_info->alarm_type,
start->hour = sqlite3_column_int(stmt, col_idx++);
start->min = sqlite3_column_int(stmt, col_idx++);
start->sec = sqlite3_column_int(stmt, col_idx++);
+ alarm_info->msec = sqlite3_column_int(stmt, col_idx++);
mode->u_interval.day_of_week = sqlite3_column_int(stmt, col_idx++);
mode->repeat = sqlite3_column_int(stmt, col_idx++);
alarm_info->alarm_type = sqlite3_column_int(stmt, col_idx++);
static bool __alarm_delete(uid_t uid, alarm_id_t alarm_id, int *error_code);
static bool __alarm_update(uid_t uid, int pid, char *app_service_name, alarm_id_t alarm_id,
alarm_info_t *alarm_info, int *error_code);
-static void __alarm_send_noti_to_application(const char *app_service_name, alarm_id_t alarm_id, uid_t uid);
+static void __alarm_send_noti_to_application(const char *app_service_name, alarm_id_t alarm_id, int msec, uid_t uid);
static void __alarm_expired();
static gboolean __alarm_handler_idle(gpointer user_data);
static void __on_system_time_external_changed(keynode_t *node, void *data);
}
static gboolean __send_noti_to_session_bus(char *service_name,
- alarm_id_t alarm_id, uid_t uid)
+ alarm_id_t alarm_id, int msec, uid_t uid)
{
int fd;
int ret;
return FALSE;
}
- gv = g_variant_new("(is)", alarm_id, service_name);
+ gv = g_variant_new("(iis)", alarm_id, msec, service_name);
if (!gv) {
close(fd);
return FALSE;
return TRUE;
}
-static void __alarm_send_noti_to_application(const char *app_service_name, alarm_id_t alarm_id, uid_t uid)
+static void __alarm_send_noti_to_application(const char *app_service_name,
+ alarm_id_t alarm_id, int msec, uid_t uid)
{
char service_name[MAX_SERVICE_NAME_LEN] = {0,};
gboolean ret;
SECURE_LOGI("[alarm server][send expired_alarm(alarm_id=%d) to app_service_name(%s)]", alarm_id, service_name);
if (uid >= REGULAR_UID_MIN) {
- ret = __send_noti_to_session_bus(service_name, alarm_id, uid);
+ ret = __send_noti_to_session_bus(service_name, alarm_id, msec, uid);
if (ret != TRUE)
ALARM_MGR_EXCEPTION_PRINT("failed to send alarm expired noti for %d, %s",
alarm_id, service_name);
"/org/tizen/alarm/client",
"org.tizen.alarm.client",
"alarm_expired",
- g_variant_new("(is)", alarm_id, service_name),
+ g_variant_new("(iis)", alarm_id, msec, service_name),
NULL,
G_DBUS_CALL_FLAGS_NONE,
-1,
/* TODO: implement aul_update_freezer_status */
/* aul_update_freezer_status(__alarm_info->pid, "wakeup"); */
__alarm_send_noti_to_application(destination_app_service_name,
- alarm_id, __alarm_info->uid); /* dbus auto activation */
+ alarm_id, __alarm_info->alarm_info.msec, __alarm_info->uid); /* dbus auto activation */
ALARM_MGR_LOG_PRINT("after __alarm_send_noti_to_application");
}
}
char *app_service_name, char *app_service_name_mod, int start_year,
int start_month, int start_day,
int start_hour, int start_min,
- int start_sec, int end_year, int end_month,
+ int start_sec, int msec, int end_year, int end_month,
int end_day, int mode_day_of_week,
int mode_repeat, int alarm_type,
int reserved_info,
alarm_info.start.min = start_min;
alarm_info.start.sec = start_sec;
+ alarm_info.msec = msec;
+
alarm_info.end.year = end_year;
alarm_info.end.month = end_month;
alarm_info.end.day = end_day;
if (strcmp(expire_info->service_name, service_name) == 0) {
SECURE_LOGE("expired service name(%s) alarm_id (%d)", expire_info->service_name, expire_info->alarm_id);
- __alarm_send_noti_to_application(expire_info->service_name, expire_info->alarm_id, expire_info->uid);
+ __alarm_send_noti_to_application(expire_info->service_name, expire_info->alarm_id, 0, expire_info->uid);
g_expired_alarm_list = g_slist_remove(g_expired_alarm_list, entry->data);
g_free(expire_info);
}
hour integer,\
min integer,\
sec integer,\
+ msec integer,\
day_of_week integer,\
repeat integer,\
alarm_type integer,\
return fd;
}
-static void _send_noti(char *service_name, int alarm_id)
+static void _send_noti(char *service_name, int alarm_id, int msec)
{
GDBusConnection *conn;
GError *err = NULL;
"/org/tizen/alarm/client",
"org.tizen.alarm.client",
"alarm_expired",
- g_variant_new("(is)", alarm_id, service_name),
+ g_variant_new("(iis)", alarm_id, msec, service_name),
NULL,
G_DBUS_CALL_FLAGS_NONE,
-1,
int r;
int len;
int alarm_id;
+ int msec;
int clifd;
char *service_name;
uint8_t *data;
return G_SOURCE_CONTINUE;
}
- gv = g_variant_new_from_data(G_VARIANT_TYPE("(is)"),
+ gv = g_variant_new_from_data(G_VARIANT_TYPE("(iis)"),
data, len, TRUE, NULL, NULL);
if (!gv) {
return G_SOURCE_CONTINUE;
}
- g_variant_get(gv, "(i&s)", &alarm_id, &service_name);
- _send_noti(service_name, alarm_id);
+ g_variant_get(gv, "(ii&s)", &alarm_id, &msec, &service_name);
+ _send_noti(service_name, alarm_id, msec);
free(data);
g_variant_unref(gv);
<arg type="i" name="alarm_info_start_hour" direction="in" />
<arg type="i" name="alarm_info_start_min" direction="in" />
<arg type="i" name="alarm_info_start_sec" direction="in" />
+ <arg type="i" name="alarm_info_msec" direction="in" />
<arg type="i" name="alarm_info_end_year" direction="in" />
<arg type="i" name="alarm_info_end_month" direction="in" />
<arg type="i" name="alarm_info_end_day" direction="in" />
alarm_date_t start; /**< start time of the alarm */
alarm_date_t end; /**< end time of the alarm */
alarm_mode_t mode; /**< mode of alarm */
+ int msec;
int alarm_type; /**< alarm type*/
int reserved_info; /** 1st duetime(UTC epochtime) */
} alarm_info_t;
time_t interval, const char *destination,
alarm_id_t *alarm_id);
+
+/**
+ * This function adds an alarm entry to the server with milliseconds precision.
+ * Server will remember this entry, and generate alarm events for it when necessary.
+ * Alarm entries registered with the server cannot be changed.
+ * Remove from server before changing.
+ * After the trigger_at_time seconds from now, the alarm will be expired.
+ * If the interval is zero, the repeat_mode is ALARM_REPEAT_MODE_ONCE.
+ * If the interval is >0, the repeat_mode is ALARM_REPEAT_MODE_REPEAT.
+ * The id of the new alarm will be copied to alarm_id if the fuction successes to create an alarm.
+ *
+ * @param [in] alarm_type one of ALARM_TYPE_DEFAULT, 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] destination the packname of application that the alarm will be expired.
+ * @param [out] alarm_id the id of the alarm added.
+ *
+ * @return This function returns ALARMMGR_RESULT_SUCCESS on success or a negative number on failure.
+ *
+ * @pre None.
+ * @post None.
+ * @see alarmmgr_add_alarm_with_localtime alarmmgr_remove_alarm
+ * @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.
+ * The callback function may be delayed, due to the processing of other event.
+ * This function corrects the delay as much as possible.
+ */
+int alarmmgr_add_alarm_precision(int alarm_type, time_t trigger_at_time,
+ time_t interval, const char *destination,
+ alarm_id_t *alarm_id);
+
/**
* This function deletes the alarm associated with the given alarm_id.
*
hour integer,
min integer,
sec integer,
+ msec integer,
day_of_week integer,
repeat integer,
alarm_type integer,
(alarm_id, start, end, pid, caller_pkgid, \
callee_pkgid, app_unique_name, app_service_name, \
app_service_name_mod, bundle, year, month, \
- day, hour, min, sec, day_of_week, repeat, \
+ day, hour, min, sec, msec, day_of_week, repeat, \
alarm_type, reserved_info, dst_service_name, \
dst_service_name_mod) \
SELECT alarm_id, start, end, pid, caller_pkgid, \
callee_pkgid, app_unique_name, app_service_name, \
app_service_name_mod, bundle, year, month, \
- day, hour, min, sec, day_of_week, repeat, \
+ day, hour, min, sec, msec, day_of_week, repeat, \
alarm_type, reserved_info, dst_service_name, dst_service_name_mod \
FROM alarmmgr;
-UPDATE alarmmgr_temp SET uid=5001,global=0,is_disabled=0,noti_len=4,noti="null";
+UPDATE alarmmgr_temp SET uid=5001,global=0,is_disabled=0,msec=0,noti_len=4,noti="null";
DROP TABLE alarmmgr;
ALTER TABLE alarmmgr_temp RENAME TO alarmmgr;
alarm_info->start.hour,
alarm_info->start.min,
alarm_info->start.sec,
+ alarm_info->msec,
alarm_info->end.year,
alarm_info->end.month,
alarm_info->end.day,
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;
" <interface name='org.tizen.alarm.client'>"
" <method name='alarm_expired'>"
" <arg type='i' name='alarm_id' direction='in'/>"
+ " <arg type='i' name='msec' direction='in'/>"
" <arg type='s' name='service_name' direction='in'/>"
" </method>"
" </interface>"
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;
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;
alarm_cb_info_t *info = NULL;
- g_variant_get(param, "(i&s)", &alarm_id, &package_name);
+ int msec;
+
+ g_variant_get(param, "(ii&s)", &alarm_id, &msec, &package_name);
ALARM_MGR_LOG_PRINT("[alarm-lib] : Alarm expired for [%s] : Alarm id [%d]", package_name, alarm_id);
if (alarm_context.alarm_handler != NULL)
info = __find_resultcb(alarm_id);
if (info && info->cb_func) {
- if (info->msec > 0) {
+ if (msec > 0) {
gettimeofday(¤t_time, NULL);
- msec = info->msec - current_time.tv_usec / 1000;
+ msec = msec - (int)current_time.tv_usec / 1000;
if (msec > 0) {
g_timeout_add_full(G_PRIORITY_HIGH, (guint)msec,
__handle_millisec_accuracy, info, NULL);
alarm->start.min = 0;
alarm->start.sec = 0;
+ alarm->msec = 0;
+
alarm->end.year = 0;
alarm->end.month = 0;
alarm->end.day = 0;
return ALARMMGR_RESULT_SUCCESS;
}
-EXPORT_API int alarmmgr_add_alarm(int alarm_type, time_t trigger_at_time,
+static int _alarmmgr_add_alarm(int alarm_type,
+ time_t trigger_at_time,
time_t interval, const char *destination,
- alarm_id_t *alarm_id)
+ alarm_id_t *alarm_id, bool precision)
{
char dst_service_name[MAX_SERVICE_NAME_LEN] = { 0 };
char dst_service_name_mod[MAX_SERVICE_NAME_LEN] = { 0 };
alarm_info_t alarm_info;
int ret;
+ gettimeofday(¤t_time, NULL);
+
_initialize_alarm_info(&alarm_info);
ret = __sub_init();
alarm_info.alarm_type = alarm_type;
alarm_info.alarm_type |= ALARM_TYPE_RELATIVE;
- gettimeofday(¤t_time, NULL);
if (current_time.tv_usec > 500 * 1000) {
/* When the millisecond part of the current_time is bigger than 500ms,
alarm_info.start.month = duetime_tm.tm_mon + 1;
alarm_info.start.day = duetime_tm.tm_mday;
+ alarm_info.msec = precision ? (int)current_time.tv_usec / 1000 : 0;
+
alarm_info.end.year = 0;
alarm_info.end.month = 0;
alarm_info.end.day = 0;
return ALARMMGR_RESULT_SUCCESS;
}
-EXPORT_API 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)
+EXPORT_API int alarmmgr_add_alarm(int alarm_type, time_t trigger_at_time,
+ time_t interval, const char *destination,
+ alarm_id_t *alarm_id)
+{
+ return _alarmmgr_add_alarm(alarm_type, trigger_at_time, interval,
+ destination, alarm_id, false);
+}
+
+EXPORT_API int alarmmgr_add_alarm_precision(int alarm_type,
+ time_t trigger_at_time,
+ time_t interval, const char *destination,
+ alarm_id_t *alarm_id)
+{
+ return _alarmmgr_add_alarm(alarm_type, trigger_at_time, interval,
+ destination, alarm_id, true);
+}
+
+static 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, bool precision)
{
int error_code = 0;
struct timeval current_time;
alarm_info_t alarm_info;
int ret = 0;
+ gettimeofday(¤t_time, NULL);
+
_initialize_alarm_info(&alarm_info);
if (flag_appid_checked == 0) {
alarm_info.alarm_type |= ALARM_TYPE_RELATIVE;
alarm_info.alarm_type |= ALARM_TYPE_WITHCB;
- gettimeofday(¤t_time, NULL);
-
if (current_time.tv_usec > 500 * 1000) {
/* When the millisecond part of the current_time is bigger than 500ms, */
/* the duetime increases by extra 1sec. */
alarm_info.start.month = duetime_tm.tm_mon + 1;
alarm_info.start.day = duetime_tm.tm_mday;
+ alarm_info.msec = precision ? (int)current_time.tv_usec / 1000 : 0;
+
alarm_info.end.year = 0;
alarm_info.end.month = 0;
alarm_info.end.day = 0;
return ALARMMGR_RESULT_SUCCESS;
}
+EXPORT_API 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)
+{
+ return _alarmmgr_add_alarm_withcb(alarm_type, trigger_at_time, interval,
+ handler, user_param, alarm_id, false);
+}
+
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;
+ return _alarmmgr_add_alarm_withcb(alarm_type, trigger_at_time, interval,
+ handler, user_param, alarm_id, true);
}
EXPORT_API int alarmmgr_remove_alarm(alarm_id_t alarm_id)