From: Jiwoong Im Date: Mon, 1 Aug 2016 11:18:57 +0000 (+0900) Subject: add notification alarm APIs X-Git-Tag: submit/tizen/20161101.112858^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5205d79101686fb72233e5caf4e1db533b21c29c;p=platform%2Fcore%2Fappfw%2Falarm-manager.git add notification alarm APIs - alarmmgr_add_alarm_noti() alarmmgr_add_alarm_noti_with_localtime() alarmmgr_get_alarm_noti_info() Change-Id: I19e994a95a6bb198a42df7102ed3df14b8398c6a Signed-off-by: Jiwoong Im --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 2b50ad4..b753702 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ INCLUDE_DIRECTORIES( include ) -SET(DEPS_PKGS "glib-2.0 dlog aul bundle db-util appsvc pkgmgr-info pkgmgr vconf gio-2.0 gio-unix-2.0 capi-system-device libtzplatform-config libsystemd-login eventsystem") +SET(DEPS_PKGS "glib-2.0 dlog aul bundle db-util appsvc pkgmgr-info pkgmgr vconf gio-2.0 gio-unix-2.0 capi-system-device libtzplatform-config libsystemd-login eventsystem notification") IF(_APPFW_FEATURE_ALARM_MANAGER_MODULE_LOG) ADD_DEFINITIONS("-D_APPFW_FEATURE_ALARM_MANAGER_MODULE_LOG") diff --git a/alarm-manager-registry.c b/alarm-manager-registry.c index f5e9ce5..9268037 100644 --- a/alarm-manager-registry.c +++ b/alarm-manager-registry.c @@ -57,10 +57,11 @@ bool _save_alarms(__alarm_info_t *__alarm_info) alarm_mode_t *mode = &alarm_info->mode; char *query = sqlite3_mprintf("insert into alarmmgr( alarm_id, start,\ - end, uid, pid, global, caller_pkgid, callee_pkgid, app_unique_name, app_service_name, app_service_name_mod, bundle, year,\ + end, uid, pid, global, 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,\ alarm_type, reserved_info, dst_service_name, dst_service_name_mod)\ - values (%d,%d,%d,%d,%d,%d,%Q,%Q,%Q,%Q,%Q,%Q,%d,%d,%d,%d,%d,%d,%d,%d,\ + values (%d,%d,%d,%d,%d,%d,%Q,%Q,%Q,%Q,%Q,%Q,%d,%Q,%d,%d,%d,%d,%d,%d,%d,%d,\ %d,%d,%Q,%Q)",\ __alarm_info->alarm_id, (int)__alarm_info->start, @@ -78,6 +79,9 @@ bool _save_alarms(__alarm_info_t *__alarm_info) __alarm_info->quark_app_service_name_mod), (char *)g_quark_to_string( __alarm_info->quark_bundle), + strlen((char *)g_quark_to_string(__alarm_info->quark_noti)), + (char *)g_quark_to_string( + __alarm_info->quark_noti), start->year, start->month, start->day, @@ -113,7 +117,7 @@ bool _update_alarms(__alarm_info_t *__alarm_info) char *query = sqlite3_mprintf("update alarmmgr set start=%d, end=%d,\ uid=%d, pid=%d, global=%d, caller_pkgid=%Q, callee_pkgid=%Q, app_unique_name=%Q, app_service_name=%Q, app_service_name_mod=%Q,\ - bundle=%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,\ 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",\ @@ -132,6 +136,9 @@ bool _update_alarms(__alarm_info_t *__alarm_info) __alarm_info->quark_app_service_name_mod), (char *)g_quark_to_string( __alarm_info->quark_bundle), + strlen((char *)g_quark_to_string(__alarm_info->quark_noti)), + (char *)g_quark_to_string( + __alarm_info->quark_noti), start->year, start->month, start->day, @@ -192,6 +199,8 @@ bool _load_alarms_from_registry() char dst_service_name[MAX_SERVICE_NAME_LEN] = {0,}; char dst_service_name_mod[MAX_SERVICE_NAME_LEN] = {0,}; char bundle[MAX_BUNDLE_NAME_LEN] = {0,}; + int noti_len; + char *noti; snprintf(query, MAX_QUERY_LEN, "select * from alarmmgr"); @@ -231,6 +240,10 @@ bool _load_alarms_from_registry() MAX_SERVICE_NAME_LEN - 1); strncpy(bundle, (const char *)sqlite3_column_text(stmt, col_idx++), MAX_BUNDLE_NAME_LEN - 1); + noti_len = sqlite3_column_int(stmt, col_idx++); + noti = calloc(1, noti_len + 1); + strncpy(noti, (const char *)sqlite3_column_text(stmt, col_idx++), + noti_len); start->year = sqlite3_column_int(stmt, col_idx++); start->month = sqlite3_column_int(stmt, col_idx++); start->day = sqlite3_column_int(stmt, col_idx++); @@ -259,6 +272,7 @@ bool _load_alarms_from_registry() __alarm_info->quark_dst_service_name_mod = g_quark_from_string(dst_service_name_mod); __alarm_info->quark_bundle = g_quark_from_string(bundle); + __alarm_info->quark_noti = g_quark_from_string(noti); _alarm_next_duetime(__alarm_info); alarm_context.alarms = g_slist_append(alarm_context.alarms, __alarm_info); diff --git a/alarm-manager.c b/alarm-manager.c index 25058d3..ee195a6 100644 --- a/alarm-manager.c +++ b/alarm-manager.c @@ -42,6 +42,9 @@ #include #include #include +#include +#include +#include #include #if !GLIB_CHECK_VERSION(2, 31, 0) @@ -809,6 +812,7 @@ static bool __alarm_create_appsvc(alarm_info_t *alarm_info, alarm_id_t *alarm_id bundle_encode(b, &b_data, &datalen); __alarm_info->quark_bundle = g_quark_from_string((const gchar *)b_data); + __alarm_info->quark_noti = g_quark_from_string("null"); __alarm_info->quark_app_service_name = g_quark_from_string("null"); __alarm_info->quark_dst_service_name = g_quark_from_string("null"); __alarm_info->quark_app_service_name_mod = g_quark_from_string("null"); @@ -993,6 +997,121 @@ static bool __alarm_create(alarm_info_t *alarm_info, alarm_id_t *alarm_id, uid_t return true; } +static bool __alarm_create_noti(alarm_info_t *alarm_info, alarm_id_t *alarm_id, + long requested_interval, uid_t uid, int pid, char *noti_data, int *error_code) +{ + time_t current_time; + time_t due_time; + struct tm ts_ret; + char due_time_r[100] = { 0 }; + char app_name[512] = { 0 }; + char* caller_pkgid = NULL; + pkgmgrinfo_pkginfo_h caller_handle; + bool caller_is_app = false; + + __alarm_info_t *__alarm_info = NULL; + + __alarm_info = malloc(sizeof(__alarm_info_t)); + if (__alarm_info == NULL) { + SECURE_LOGE("Caution!! app_pid=%d, malloc " + "failed. it seems to be OOM\n", pid); + *error_code = ERR_ALARM_SYSTEM_FAIL; + return false; + } + __alarm_info->uid = uid; + __alarm_info->pid = pid; + __alarm_info->alarm_id = -1; + __alarm_info->requested_interval = requested_interval; + __alarm_info->global = false; + + if (__get_cached_unique_name(pid, app_name, &caller_is_app, uid) == false) { + *error_code = ERR_ALARM_SYSTEM_FAIL; + free(__alarm_info); + return false; + } + __alarm_info->quark_app_unique_name = g_quark_from_string(app_name); + + __alarm_info->quark_caller_pkgid = g_quark_from_string("null"); + + if (caller_is_app) { + if (pkgmgrinfo_appinfo_get_usr_appinfo(app_name, uid, &caller_handle) == PMINFO_R_OK) { + if (pkgmgrinfo_appinfo_get_pkgid(caller_handle, &caller_pkgid) == PMINFO_R_OK) { + if (caller_pkgid) + __alarm_info->quark_caller_pkgid = g_quark_from_string(caller_pkgid); + } + pkgmgrinfo_appinfo_destroy_appinfo(caller_handle); + } + } + + __alarm_info->quark_callee_pkgid = g_quark_from_string("null"); + SECURE_LOGD("caller_pkgid = %s, callee_pkgid = null", + g_quark_to_string(__alarm_info->quark_caller_pkgid)); + + __alarm_info->quark_bundle = g_quark_from_string("null"); + __alarm_info->quark_noti = g_quark_from_string(noti_data); + __alarm_info->quark_app_service_name = g_quark_from_string("null"); + __alarm_info->quark_dst_service_name = g_quark_from_string("null"); + __alarm_info->quark_app_service_name_mod = g_quark_from_string("null"); + __alarm_info->quark_dst_service_name_mod = g_quark_from_string("null"); + + __alarm_set_start_and_end_time(alarm_info, __alarm_info); + memcpy(&(__alarm_info->alarm_info), alarm_info, sizeof(alarm_info_t)); + __alarm_generate_alarm_id(__alarm_info, alarm_id); + + time(¤t_time); + + SECURE_LOGD("[alarm-server]:pid=%d, app_unique_name=%s, " + "app_service_name=%s,dst_service_name=%s, c_due_time=%d", \ + pid, g_quark_to_string(__alarm_info->quark_app_unique_name), \ + g_quark_to_string(__alarm_info->quark_app_service_name), \ + g_quark_to_string(__alarm_info->quark_dst_service_name), \ + alarm_context.c_due_time); + + if (alarm_context.c_due_time < current_time) { + ALARM_MGR_EXCEPTION_PRINT("Caution!! alarm_context.c_due_time " + "(%d) is less than current time(%d)", alarm_context.c_due_time, current_time); + alarm_context.c_due_time = -1; + } + + due_time = _alarm_next_duetime(__alarm_info); + if (__alarm_add_to_list(__alarm_info) == false) { + free(__alarm_info); + return false; + } + + if (due_time == 0) { + ALARM_MGR_EXCEPTION_PRINT("[alarm-server]:Create a new alarm: due_time is 0, alarm(%d).", *alarm_id); + return true; + } else if (current_time == due_time) { + ALARM_MGR_EXCEPTION_PRINT("[alarm-server]:Create alarm: current_time(%d) is same as due_time(%d).", + current_time, due_time); + return true; + } else if (difftime(due_time, current_time) < 0) { + ALARM_MGR_EXCEPTION_PRINT("[alarm-server]: Expired Due Time.[Due time=%d, Current Time=%d]!!!Do not add to schedule list.", + due_time, current_time); + return true; + } else { + localtime_r(&due_time, &ts_ret); + strftime(due_time_r, 30, "%c", &ts_ret); + SECURE_LOGD("[alarm-server]:Create a new alarm: alarm(%d) due_time(%s)", *alarm_id, due_time_r); + } + + ALARM_MGR_LOG_PRINT("[alarm-server]:alarm_context.c_due_time(%d), due_time(%d)", alarm_context.c_due_time, due_time); + + if (alarm_context.c_due_time == -1 || due_time < alarm_context.c_due_time) { + _clear_scheduled_alarm_list(); + _add_to_scheduled_alarm_list(__alarm_info); + _alarm_set_timer(&alarm_context, alarm_context.timer, due_time); + alarm_context.c_due_time = due_time; + } else if (due_time == alarm_context.c_due_time) { + _add_to_scheduled_alarm_list(__alarm_info); + } + + __rtc_set(); + + return true; +} + 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) { @@ -1539,6 +1658,25 @@ static void __alarm_expired() } bundle_free(b); } + } else if (strncmp(g_quark_to_string(__alarm_info->quark_noti), "null", 4) != 0) { + GVariant *noti_gv = NULL; + GVariant *body = NULL; + guchar *data; + notification_h noti; + int datalen; + + data = g_base64_decode(g_quark_to_string(__alarm_info->quark_noti), + (gsize *)&datalen); + + noti_gv = g_variant_new_from_data(G_VARIANT_TYPE("(v)"), + data, datalen, + TRUE, NULL, NULL); + + g_variant_get(noti_gv, "(v)", &body); + + noti = notification_create(NOTIFICATION_TYPE_NOTI); + notification_ipc_make_noti_from_gvariant(noti, body); + notification_post_for_uid(noti, __alarm_info->uid); } else { char appid[MAX_SERVICE_NAME_LEN] = { 0, }; pkgmgrinfo_appinfo_h appinfo_handle = NULL; @@ -2403,6 +2541,86 @@ gboolean alarm_manager_alarm_create_appsvc(AlarmManager *pObject, GDBusMethodInv return ret; } +gboolean alarm_manager_alarm_create_noti(AlarmManager *pObject, GDBusMethodInvocation *invoc, + 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 end_day, int mode_day_of_week, + unsigned int mode_interval, + int mode_repeat, int alarm_type, + int reserved_info, + char *noti_data, + gpointer user_data) +{ + alarm_info_t alarm_info; + int return_code = ALARMMGR_RESULT_SUCCESS; + int alarm_id = 0; +#ifdef _APPFW_FEATURE_ALARM_MANAGER_MODULE_LOG + char log_tag[ALARMMGR_LOG_TAG_SIZE] = {0,}; + char log_message[ALARMMGR_LOG_MESSAGE_SIZE] = {0,}; +#endif + bool ret = true; + int uid; + int pid; + const char *name = g_dbus_method_invocation_get_sender(invoc); + + uid = __get_caller_uid(name); + pid = __get_caller_pid(name); + if (uid < 0 || pid < 0) { + return_code = ERR_ALARM_SYSTEM_FAIL; + g_dbus_method_invocation_return_value(invoc, g_variant_new("(ii)", alarm_id, return_code)); + return true; + } + + alarm_info.start.year = start_year; + alarm_info.start.month = start_month; + alarm_info.start.day = start_day; + alarm_info.start.hour = start_hour; + alarm_info.start.min = start_min; + alarm_info.start.sec = start_sec; + + alarm_info.end.year = end_year; + alarm_info.end.month = end_month; + alarm_info.end.day = end_day; + + alarm_info.mode.u_interval.day_of_week = mode_day_of_week; + alarm_info.mode.repeat = mode_repeat; + + alarm_info.alarm_type = alarm_type; + alarm_info.reserved_info = reserved_info; + + if ((alarm_info.alarm_type & ALARM_TYPE_INEXACT)) { + alarm_info.alarm_type |= ALARM_TYPE_PERIOD; + alarm_info.mode.u_interval.interval = + __get_proper_interval(mode_interval, alarm_info.alarm_type); + } else if (mode_interval <= 0) { + alarm_info.mode.u_interval.interval = 0; + } + + if (!__alarm_create_noti(&alarm_info, &alarm_id, mode_interval, uid, pid, noti_data, &return_code)) { + ALARM_MGR_EXCEPTION_PRINT("Unable to create alarm! return_code[%d]", return_code); +#ifdef _APPFW_FEATURE_ALARM_MANAGER_MODULE_LOG + strncpy(log_tag, "FAIL: CREATE", strlen("FAIL: CREATE")); +#endif + ret = false; + } else { +#ifdef _APPFW_FEATURE_ALARM_MANAGER_MODULE_LOG + strncpy(log_tag, "CREATE", strlen("CREATE")); +#endif + } + + g_dbus_method_invocation_return_value(invoc, g_variant_new("(ii)", alarm_id, return_code)); + +#ifdef _APPFW_FEATURE_ALARM_MANAGER_MODULE_LOG + snprintf(log_message, sizeof(log_message), "alarmID: %d, uid: %d, pid: %d, duetime: %d-%d-%d %02d:%02d:%02d", + alarm_id, uid, pid, start_year, start_month, start_day, start_hour, start_min, start_sec); + __save_module_log(log_tag, log_message); +#endif + + return ret; +} + gboolean alarm_manager_alarm_create(AlarmManager *obj, GDBusMethodInvocation *invoc, char *app_service_name, char *app_service_name_mod, int start_year, int start_month, int start_day, @@ -2908,6 +3126,50 @@ gboolean alarm_manager_alarm_get_appsvc_info(AlarmManager *pObject, GDBusMethodI return true; } +gboolean alarm_manager_alarm_get_noti_info(AlarmManager *pObject, GDBusMethodInvocation *invoc, + alarm_id_t alarm_id, gpointer user_data) +{ + bool found = false; + GSList *gs_iter = NULL; + __alarm_info_t *entry = NULL; + int return_code = ALARMMGR_RESULT_SUCCESS; + gchar *noti_data = NULL; + int uid; + const char *name = g_dbus_method_invocation_get_sender(invoc); + + uid = __get_caller_uid(name); + if (uid < 0) { + return_code = ERR_ALARM_SYSTEM_FAIL; + g_dbus_method_invocation_return_value(invoc, g_variant_new("(si)", noti_data, return_code)); + return true; + } + + SECURE_LOGD("called for uid(%d), alarm_id(%d)\n", uid, alarm_id); + + for (gs_iter = alarm_context.alarms; gs_iter != NULL; gs_iter = g_slist_next(gs_iter)) { + entry = gs_iter->data; + if (entry->uid == uid && entry->alarm_id == alarm_id) { + found = true; + noti_data = strdup(g_quark_to_string(entry->quark_noti)); + break; + } + } + + if (found) { + if (noti_data && strlen(noti_data) == 4 && strncmp(noti_data, "null", 4) == 0) { + ALARM_MGR_EXCEPTION_PRINT("The alarm(%d) is an regular alarm, not svc alarm.", alarm_id); + return_code = ERR_ALARM_INVALID_TYPE; + } + } else { + ALARM_MGR_EXCEPTION_PRINT("The alarm(%d) is not found.", alarm_id); + return_code = ERR_ALARM_INVALID_ID; + } + + g_dbus_method_invocation_return_value(invoc, g_variant_new("(si)", noti_data, return_code)); + g_free(noti_data); + return true; +} + gboolean alarm_manager_alarm_get_info(AlarmManager *pObject, GDBusMethodInvocation *invoc, alarm_id_t alarm_id, gpointer user_data) { @@ -3382,10 +3644,12 @@ static bool __initialize_dbus() g_signal_connect(interface, "handle_alarm_create", G_CALLBACK(alarm_manager_alarm_create), NULL); g_signal_connect(interface, "handle_alarm_create_periodic", G_CALLBACK(alarm_manager_alarm_create_periodic), NULL); g_signal_connect(interface, "handle_alarm_create_appsvc", G_CALLBACK(alarm_manager_alarm_create_appsvc), NULL); + g_signal_connect(interface, "handle_alarm_create_noti", G_CALLBACK(alarm_manager_alarm_create_noti), NULL); g_signal_connect(interface, "handle_alarm_delete", G_CALLBACK(alarm_manager_alarm_delete), NULL); g_signal_connect(interface, "handle_alarm_delete_all", G_CALLBACK(alarm_manager_alarm_delete_all), NULL); g_signal_connect(interface, "handle_alarm_get_appsvc_info", G_CALLBACK(alarm_manager_alarm_get_appsvc_info), NULL); g_signal_connect(interface, "handle_alarm_get_info", G_CALLBACK(alarm_manager_alarm_get_info), NULL); + g_signal_connect(interface, "handle_alarm_get_noti_info", G_CALLBACK(alarm_manager_alarm_get_noti_info), NULL); g_signal_connect(interface, "handle_alarm_get_list_of_ids", G_CALLBACK(alarm_manager_alarm_get_list_of_ids), NULL); g_signal_connect(interface, "handle_alarm_get_next_duetime", G_CALLBACK(alarm_manager_alarm_get_next_duetime), NULL); g_signal_connect(interface, "handle_alarm_get_number_of_ids", G_CALLBACK(alarm_manager_alarm_get_number_of_ids), NULL); @@ -3449,6 +3713,8 @@ static bool __initialize_dbus() app_service_name text,\ app_service_name_mod text,\ bundle text, \ + noti_len integer,\ + noti text, \ year integer,\ month integer,\ day integer,\ diff --git a/alarm-service.conf.in b/alarm-service.conf.in index 52a3429..aff48dd 100644 --- a/alarm-service.conf.in +++ b/alarm-service.conf.in @@ -11,6 +11,8 @@ + + @@ -21,6 +23,7 @@ + diff --git a/alarm_mgr.xml b/alarm_mgr.xml index 93e1737..456122e 100644 --- a/alarm_mgr.xml +++ b/alarm_mgr.xml @@ -50,6 +50,25 @@ + + + + + + + + + + + + + + + + + + + @@ -90,6 +109,11 @@ + + + + + diff --git a/include/alarm-internal.h b/include/alarm-internal.h index 1ffb966..9d37168 100644 --- a/include/alarm-internal.h +++ b/include/alarm-internal.h @@ -34,6 +34,7 @@ #include #include #include +#include #include #define INIT_ALARM_LIST_SIZE 64 @@ -135,6 +136,8 @@ bool _send_alarm_create(alarm_context_t context, alarm_info_t *alarm, alarm_id_t *id, const char *dst_service_name,const char *dst_service_name_mod, int *error_code); bool _send_alarm_create_appsvc(alarm_context_t context, alarm_info_t *alarm_info, alarm_id_t *alarm_id, bundle *b,int *error_code); +bool _send_alarm_create_noti(alarm_context_t context, alarm_info_t *alarm_info, + alarm_id_t *alarm_id, notification_h noti, int *error_code); bool _send_alarm_update(alarm_context_t context, int pid, alarm_id_t alarm_id, alarm_info_t *alarm_info, int *error_code); bool _send_alarm_delete(alarm_context_t context, alarm_id_t alarm_id, int *error_code); @@ -149,6 +152,7 @@ bool _send_alarm_reset(alarm_context_t context, int *error_code); bool _remove_from_scheduled_alarm_list(uid_t uid, alarm_id_t alarm_id); bool _load_alarms_from_registry(); bundle *_send_alarm_get_appsvc_info(alarm_context_t context, alarm_id_t alarm_id, int *error_code); +notification_h _send_alarm_get_noti_info(alarm_context_t context, alarm_id_t alarm_id, int *error_code); bool _send_alarm_set_rtc_time(alarm_context_t context, alarm_date_t *time, int *error_code); bool _send_alarm_set_time_with_propagation_delay(alarm_context_t context, unsigned int new_sec, unsigned int new_nsec, unsigned int req_sec, unsigned int req_nsec, int *error_code); bool _send_alarm_set_time_with_propagation_delay_async(alarm_context_t context, unsigned int new_sec, unsigned int new_nsec, unsigned int req_sec, unsigned int req_nsec, alarm_set_time_cb_t result_cb, void *user_data); @@ -182,6 +186,7 @@ typedef struct { time_t due_time; GQuark quark_bundle; /*Bundle Content containing app-svc info*/ + GQuark quark_noti; alarm_info_t alarm_info; diff --git a/include/alarm.h b/include/alarm.h index e52563c..5222c60 100644 --- a/include/alarm.h +++ b/include/alarm.h @@ -152,6 +152,7 @@ int main(int argc, char** argv) #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -874,6 +875,77 @@ int alarmmgr_add_alarm_appsvc_with_localtime(alarm_entry_t *alarm,void *bundle_d /** * This function adds an alarm entry to the server. * Server will remember this entry, and generate alarm events for it when necessary. + * Server will post notification + * Alarm entries registered with the server cannot be changed. + * Remove from server before changing. + * Before the application calls alarmmgr_add_alarm_noti_with_localtime(), the application have to call alarmmgr_set_time(). + * The time set is localtime. + * If the application does not call alarmmgr_set_repeat_mode, the default repeat_mode is ALARM_REPEAT_MODE_ONCE. + * If the application does not call alarmmgr_set_type, the default alarm_type is ALARM_TYPE_DEFAULT. + * The id of the new alarm will be copied to alarm_id if the fuction successes to create an alarm. + * + * @param [in] alarm the entry of an alarm to be created. + * @param [in] noti notification handle to be posted when the alarm is 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 + * @remark None. + * + * @par Sample code: + * @code +#include + + ... +{ + time_t current_time; + struct tm current_tm; + alarm_entry_t* alarm_info; + alarm_id_t alarm_id; + int result; + alarm_date_t test_time; + + noti_handle = notification_create(NOTIFICATION_TYPE_NOTI); + result = notification_set_text(noti_handle, NOTIFICATION_TEXT_TYPE_TITLE, + "Title", "TITLE", NOTIFICATION_VARIABLE_TYPE_NONE); + + time(¤t_time); + + printf("current time: %s\n", ctime(¤t_time)); + localtime_r(¤t_time, ¤t_tm); + + alarm_info = alarmmgr_create_alarm(); + + test_time.year = current_tm.tm_year; + test_time.month = current_tm.tm_mon; + test_time.day = current_tm.tm_mday; + + test_time.hour = current_tm.tm_hour; + test_time.min = current_tm.tm_min+1; + test_time.sec = 5; + + alarmmgr_set_time(alarm_info,test_time); + alarmmgr_set_repeat_mode(alarm_info,ALARM_REPEAT_MODE_WEEKLY,ALARM_WDAY_MONDAY| \ + ALARM_WDAY_TUESDAY|ALARM_WDAY_WEDNESDAY| \ + ALARM_WDAY_THURSDAY|ALARM_WDAY_FRIDAY ); + + alarmmgr_set_type(alarm_info, ALARM_TYPE_DEFAULT); + if ((result = alarmmgr_add_alarm_noti_with_localtime(alarm_info, noti, &alarm_id)) < 0) + printf("Alarm creation failed!!! Alrmgr error code is %d\n",result); + else + printf("Alarm created succesfully with alarm id %d\n",alarm_id); + +} +* @endcode +*/ +int alarmmgr_add_alarm_noti_with_localtime(alarm_entry_t *alarm, notification_h noti, alarm_id_t *alarm_id); + +/** + * This function adds an alarm entry to the server. + * 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. * Before the application calls alarmmgr_add_alarm_with_localtime(), the application have to call alarmmgr_set_time(). @@ -1020,6 +1092,58 @@ int alarmmgr_add_alarm_appsvc(int alarm_type, time_t trigger_at_time, time_t interval, void *bundle_data, alarm_id_t *alarm_id); +/* + * This function adds an alarm entry to the server. + * Server will remember this entry, and generate alarm events for it when necessary. + * Server will post notification + * 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] noti notification handle to be posted when the alarm is 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 None. + * + * @par Sample code: + * @code +#include + + ... +{ + int result; + alarm_id_t alarm_id; + notification_h noti_handle; + + noti_handle = notification_create(NOTIFICATION_TYPE_NOTI); + result = notification_set_text(noti_handle, NOTIFICATION_TEXT_TYPE_TITLE, + "Title", "TITLE", NOTIFICATION_VARIABLE_TYPE_NONE); + + if ((result = alarmmgr_add_alarm_noti(ALARM_TYPE_DEFAULT, 10, 0, noti_handle, &alarm_id))) + printf("Unable to add alarm. Alarmmgr alarm no is %d\n", result); + else + printf("Alarm added successfully. Alarm Id is %d\n", alarm_id); + return; + +} + + * @endcode + */ +int alarmmgr_add_alarm_noti(int alarm_type, time_t trigger_at_time, + time_t interval, notification_h noti, + alarm_id_t *alarm_id); + /** * This function adds an alarm entry to the server. @@ -1324,6 +1448,8 @@ int main(int argc,char **argv { */ void *alarmmgr_get_alarm_appsvc_info(alarm_id_t alarm_id, int *return_code); +int alarmmgr_get_alarm_noti_info(alarm_id_t alarm_id, notification_h *noti); + /** * This function gets the scheduled time of the alarm assosiated with alarm_id. * diff --git a/packaging/alarm-manager.spec b/packaging/alarm-manager.spec index 55e42fd..8d53662 100644 --- a/packaging/alarm-manager.spec +++ b/packaging/alarm-manager.spec @@ -30,6 +30,7 @@ BuildRequires: pkgconfig(capi-system-device) BuildRequires: pkgconfig(libtzplatform-config) BuildRequires: pkgconfig(libsystemd) BuildRequires: pkgconfig(eventsystem) +BuildRequires: pkgconfig(notification) BuildRequires: python-xml %define upgrade_script_path /usr/share/upgrade/scripts diff --git a/src/alarm-lib-stub.c b/src/alarm-lib-stub.c index d02d7b5..4b9bc3f 100644 --- a/src/alarm-lib-stub.c +++ b/src/alarm-lib-stub.c @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include "alarm.h" #include "alarm-internal.h" #include "alarm-mgr-stub.h" @@ -42,6 +44,85 @@ bool _send_alarm_get_number_of_ids(alarm_context_t context, int *num_of_ids, bool _send_alarm_get_info(alarm_context_t context, alarm_id_t alarm_id, alarm_info_t *alarm_info, int *error_code); +bool _send_alarm_create_noti(alarm_context_t context, alarm_info_t *alarm_info, + alarm_id_t *alarm_id, notification_h noti, int *error_code) +{ + gboolean ret; + GError *error = NULL; + int return_code = 0; + GVariant *noti_gv = NULL; + char *noti_data; + guchar *data; + int datalen = 0; + + noti_gv = notification_ipc_make_gvariant_from_noti(noti, true); + + datalen = g_variant_get_size(noti_gv); + if (datalen < 0) + return false; + + data = malloc(datalen); + if (!data) + return false; + + if (!noti_gv) { + if (error_code) + *error_code = ERR_ALARM_SYSTEM_FAIL; + free(data); + return false; + } + + g_variant_store(noti_gv, data); + noti_data = g_base64_encode((guchar *)data, datalen); + + ret = alarm_manager_call_alarm_create_noti_sync((AlarmManager*)context.proxy, + alarm_info->start.year, + alarm_info->start.month, + alarm_info->start.day, + alarm_info->start.hour, + alarm_info->start.min, + alarm_info->start.sec, + alarm_info->end.year, + alarm_info->end.month, + alarm_info->end.day, + alarm_info->mode.u_interval.day_of_week, + alarm_info->mode.u_interval.interval, + alarm_info->mode.repeat, + alarm_info->alarm_type, + alarm_info->reserved_info, + (char *)noti_data, + alarm_id, &return_code, + NULL, &error); + if (noti_data) { + free(noti_data); + noti_data = NULL; + } + + if (ret != TRUE) { + /* g_dbus_proxy_call_sync error */ + /* error_code should be set */ + ALARM_MGR_EXCEPTION_PRINT( + "alarm_manager_call_alarm_create_noti_sync()failed. alarm_id[%d], return_code[%d].", alarm_id, return_code); + ALARM_MGR_EXCEPTION_PRINT("error->message is %s(%d)", error->message, error->code); + if (error_code) { + if (error->code == G_DBUS_ERROR_ACCESS_DENIED) + *error_code = ERR_ALARM_NO_PERMISSION; + else + *error_code = ERR_ALARM_SYSTEM_FAIL; + } + g_error_free(error); + return false; + } + + if (return_code != 0) { + if (error_code) + *error_code = return_code; + return false; + } + + return true; +} + bool _send_alarm_create_appsvc(alarm_context_t context, alarm_info_t *alarm_info, alarm_id_t *alarm_id, bundle *b, int *error_code) @@ -247,6 +328,59 @@ bundle *_send_alarm_get_appsvc_info(alarm_context_t context, alarm_id_t alarm_id return b; } +notification_h _send_alarm_get_noti_info(alarm_context_t context, alarm_id_t alarm_id, int *error_code) +{ + GError *error = NULL; + int return_code = 0; + int datalen; + GVariant *noti_gv = NULL; + GVariant *body = NULL; + notification_h noti = NULL; + gchar *noti_data = NULL; + guchar *data; + + if (!alarm_manager_call_alarm_get_noti_info_sync + ((AlarmManager*)context.proxy, alarm_id, ¬i_data, &return_code, NULL, &error)) { + /* g_dbus_proxy_call_sync error */ + /*error_code should be set */ + ALARM_MGR_EXCEPTION_PRINT("alarm_manager_call_alarm_get_appsvc_info_sync() failed. alarm_id[%d], return_code[%d].", alarm_id, return_code); + ALARM_MGR_EXCEPTION_PRINT("error->message is %s(%d)", error->message, error->code); + if (error_code) { + if (error->code == G_DBUS_ERROR_ACCESS_DENIED) + *error_code = ERR_ALARM_NO_PERMISSION; + else + *error_code = ERR_ALARM_SYSTEM_FAIL; + } + g_error_free(error); + + if (noti_data) + g_free(noti_data); + + return NULL; + } + + if (return_code != 0) { + if (error_code) + *error_code = return_code; + } else { + data = g_base64_decode(noti_data, (gsize *)&datalen); + + noti_gv = g_variant_new_from_data(G_VARIANT_TYPE("(v)"), + data, datalen, + TRUE, NULL, NULL); + + g_variant_get(noti_gv, "(v)", &body); + + noti = notification_create(NOTIFICATION_TYPE_NOTI); + notification_ipc_make_noti_from_gvariant(noti, body); + } + + if (noti_data) + g_free(noti_data); + + return noti; +} + bool _send_alarm_set_rtc_time(alarm_context_t context, alarm_date_t *time, int *error_code) { diff --git a/src/alarm-lib.c b/src/alarm-lib.c index 673ea2b..2f03a06 100644 --- a/src/alarm-lib.c +++ b/src/alarm-lib.c @@ -34,6 +34,7 @@ #include #include #include +#include #ifndef EXPORT_API #define EXPORT_API __attribute__ ((visibility("default"))) @@ -770,6 +771,25 @@ EXPORT_API void *alarmmgr_get_alarm_appsvc_info(alarm_id_t alarm_id, int *return return _send_alarm_get_appsvc_info(alarm_context, alarm_id, return_code); } +EXPORT_API int alarmmgr_get_alarm_noti_info(alarm_id_t alarm_id, notification_h *noti) +{ + int ret = 0; + + ret = __sub_init(); + if (ret < 0) { + return ret; + } + + ALARM_MGR_LOG_PRINT("[alarm-lib]:alarmmgr_get_alarm_appsvc_info() is called."); + + if (alarm_id <= 0) + return ERR_ALARM_INVALID_ID; + + *noti = _send_alarm_get_noti_info(alarm_context, alarm_id, &ret); + + return ret; +} + EXPORT_API int alarmmgr_set_rtc_time(alarm_date_t *time) { @@ -971,6 +991,60 @@ EXPORT_API int alarmmgr_add_alarm_with_localtime(alarm_entry_t *alarm, return ALARMMGR_RESULT_SUCCESS; } +EXPORT_API int alarmmgr_add_alarm_noti_with_localtime(alarm_entry_t *alarm, notification_h noti, alarm_id_t *alarm_id) +{ + alarm_info_t *alarm_info = NULL; /* = (alarm_info_t*)alarm; */ + const char *operation = NULL; + int error_code = 0; + int result; + + if (alarm == NULL) + return ERR_ALARM_INVALID_PARAM; + + if (__alarmmgr_init_appsvc() < 0) { + ALARM_MGR_EXCEPTION_PRINT("Unable to initialize dbus!!!\n"); + return ERR_ALARM_SYSTEM_FAIL; + } + + alarm_info = (alarm_info_t *)alarm; + + if (alarm_info == NULL || alarm_id == NULL) { + ALARM_MGR_EXCEPTION_PRINT("Invalid parameter\n"); + return ERR_ALARM_INVALID_PARAM; + } + alarm_mode_t *mode = &alarm_info->mode; + + ALARM_MGR_EXCEPTION_PRINT("start(%d-%d-%d, %02d:%02d:%02d), end(%d-%d-%d), repeat(%d), interval(%d), type(%d)", + alarm_info->start.day, alarm_info->start.month, alarm_info->start.year, + alarm_info->start.hour, alarm_info->start.min, alarm_info->start.sec, + alarm_info->end.year, alarm_info->end.month, alarm_info->end.day, + alarm_info->mode.repeat, alarm_info->mode.u_interval, alarm_info->alarm_type); + + /* TODO: This should be changed to > ALARM_REPEAT_MODE_MAX ? */ + if (mode->repeat >= ALARM_REPEAT_MODE_MAX) + return ERR_ALARM_INVALID_PARAM; + + if (!__alarm_validate_date(&alarm_info->start, &error_code)) { + ALARM_MGR_EXCEPTION_PRINT("start date error\n"); + return error_code; + } + + if (!__alarm_validate_time(&alarm_info->start, &error_code)) { + ALARM_MGR_EXCEPTION_PRINT("start time error\n"); + return error_code; + } + + if (!__alarm_validate_date(&alarm_info->end, &error_code)) { + ALARM_MGR_EXCEPTION_PRINT("end date error\n"); + return error_code; + } + + if (!_send_alarm_create_noti(alarm_context, alarm_info, alarm_id, noti, &error_code)) + return error_code; + + return ALARMMGR_RESULT_SUCCESS; +} + EXPORT_API int alarmmgr_add_alarm_appsvc(int alarm_type, time_t trigger_at_time, time_t interval, void *bundle_data, alarm_id_t *alarm_id) @@ -1078,6 +1152,77 @@ EXPORT_API int alarmmgr_add_alarm_appsvc(int alarm_type, time_t trigger_at_time, return ALARMMGR_RESULT_SUCCESS; } +EXPORT_API int alarmmgr_add_alarm_noti(int alarm_type, time_t trigger_at_time, + time_t interval, notification_h noti, + alarm_id_t *alarm_id) +{ + int error_code = 0; + int result; + struct timeval current_time; + struct tm duetime_tm; + alarm_info_t alarm_info; + const char *operation = NULL; + + if (__alarmmgr_init_appsvc() < 0) { + ALARM_MGR_EXCEPTION_PRINT("Unable to initialize dbus!!!\n"); + return ERR_ALARM_SYSTEM_FAIL; + } + + 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; + + 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. */ + current_time.tv_sec += (trigger_at_time + 1); + } else { + current_time.tv_sec += trigger_at_time; + } + + 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 ((alarm_info.alarm_type & ALARM_TYPE_INEXACT) && interval < MIN_INEXACT_INTERVAL) + interval = MIN_INEXACT_INTERVAL; + + 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_LOG_PRINT("trigger_at_time(%d), start(%d-%d-%d, %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, + alarm_info.mode.repeat, alarm_info.mode.u_interval.interval, alarm_info.alarm_type); + + if (!_send_alarm_create_noti(alarm_context, &alarm_info, alarm_id, noti, &error_code)) + return error_code; + + return ALARMMGR_RESULT_SUCCESS; +} + 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)