4 * Copyright (c) 2012 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
29 #include "cal_typedef.h"
30 #include "cal_internal.h"
32 #include "cal_inotify.h"
33 #include "cal_db_util.h"
35 #include "cal_db_query.h"
36 #include "cal_server_dbus.h"
38 #define CAL_SEARCH_LOOP_MAX 4
40 struct _alarm_data_s {
42 long long int alert_utime; /* to compare */
45 int type; /* utime, localtime */
47 int record; /* todo, event */
48 char datetime[CAL_STR_SHORT_LEN32];
52 /* this api is necessary for repeat instance. */
53 static int _cal_server_alarm_unset_alerted_alarmmgr_id(int alarm_id)
55 char query[CAL_DB_SQL_MAX_LEN] = {0};
58 ret = cal_db_util_begin_trans();
59 if (CALENDAR_ERROR_NONE != ret) {
61 ERR("cal_db_util_begin_trans() Fail");
62 return CALENDAR_ERROR_DB_FAILED;
66 DBG("alarm_id(%d)", alarm_id);
68 snprintf(query, sizeof(query), "UPDATE %s SET alarm_id = 0 WHERE alarm_id =%d ",
69 CAL_TABLE_ALARM, alarm_id);
70 ret = cal_db_util_query_exec(query);
71 if (CALENDAR_ERROR_NONE != ret) {
73 ERR("cal_db_util_query_exec() Fail(%d)", ret);
74 SECURE("[%s]", query);
75 cal_db_util_end_trans(false);
79 cal_db_util_end_trans(true);
80 return CALENDAR_ERROR_NONE;
83 static int _cal_server_alarm_clear_all_cb(alarm_id_t alarm_id, void *data)
87 DBG("remove alarm id(%d)", alarm_id);
88 _cal_server_alarm_unset_alerted_alarmmgr_id(alarm_id);
89 ret = alarmmgr_remove_alarm(alarm_id);
90 if (ret != ALARMMGR_RESULT_SUCCESS) {
92 ERR("alarmmgr_remove_alarm() Fail(ret:%d)", ret);
96 return CALENDAR_ERROR_NONE;
99 static int _cal_server_alarm_update_alarm_id(int alarm_id, int event_id, int tick, int unit)
101 char query[CAL_DB_SQL_MAX_LEN] = {0};
104 ret = cal_db_util_begin_trans();
105 if (CALENDAR_ERROR_NONE != ret) {
106 /* LCOV_EXCL_START */
107 ERR("cal_db_util_begin_trans() Fail");
108 return CALENDAR_ERROR_DB_FAILED;
112 DBG("Update alarm_id(%d) in alarm table", alarm_id);
113 snprintf(query, sizeof(query), "UPDATE %s SET alarm_id =%d "
114 "WHERE event_id =%d AND remind_tick =%d AND remind_tick_unit =%d",
115 CAL_TABLE_ALARM, alarm_id, event_id, tick, unit);
116 ret = cal_db_util_query_exec(query);
117 if (CALENDAR_ERROR_NONE != ret) {
118 /* LCOV_EXCL_START */
119 ERR("cal_db_util_query_exec() Fail(%d)", ret);
120 SECURE("[%s]", query);
121 cal_db_util_end_trans(false);
125 cal_db_util_end_trans(true);
126 return CALENDAR_ERROR_NONE;
129 static long long int _get_event_alert_utime(const char *field, int event_id, time_t current)
132 char query[CAL_DB_SQL_MAX_LEN] = {0};
133 snprintf(query, sizeof(query), "SELECT %s FROM %s "
134 "WHERE event_id=%d AND %s>%ld ORDER BY %s LIMIT 1",
135 field, CAL_TABLE_UTIME_INSTANCE, event_id, field, current, field);
137 sqlite3_stmt *stmt = NULL;
138 ret = cal_db_util_query_prepare(query, &stmt);
139 if (CALENDAR_ERROR_NONE != ret) {
140 /* LCOV_EXCL_START */
141 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
142 SECURE("query[%s]", query);
147 long long int utime = 0;
148 if (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt))
149 utime = sqlite3_column_int(stmt, 0);
151 sqlite3_finalize(stmt);
155 static int _get_event_alert_localtime(const char *field, int event_id, time_t current)
158 char query[CAL_DB_SQL_MAX_LEN] = {0};
161 localtime_r(¤t, &st);
162 time_t mod_current = timegm(&st);
163 snprintf(query, sizeof(query), "SELECT %s FROM %s "
164 "WHERE event_id=%d AND strftime('%%s', %s)>%ld ORDER BY %s LIMIT 1",
165 field, CAL_TABLE_LOCALTIME_INSTANCE, event_id, field, mod_current, field);
167 sqlite3_stmt *stmt = NULL;
168 ret = cal_db_util_query_prepare(query, &stmt);
169 if (CALENDAR_ERROR_NONE != ret) {
170 /* LCOV_EXCL_START */
171 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
172 SECURE("query[%s]", query);
177 const char *datetime = NULL;
178 if (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt))
179 datetime = (const char *)sqlite3_column_text(stmt, 0);
181 if (NULL == datetime || '\0' == *datetime) {
182 /* LCOV_EXCL_START */
183 ERR("Invalid datetime [%s]", datetime);
184 sqlite3_finalize(stmt);
189 int y = 0, m = 0, d = 0;
190 int h = 0, n = 0, s = 0;
191 sscanf(datetime, CAL_FORMAT_LOCAL_DATETIME, &y, &m, &d, &h, &n, &s);
192 sqlite3_finalize(stmt);
194 st.tm_year = y - 1900;
201 return (long long int)mktime(&st);
204 static int64_t _get_todo_alert_utime(const char *field, int id, time_t now_t)
207 char query[CAL_DB_SQL_MAX_LEN] = {0};
208 snprintf(query, sizeof(query), "SELECT %s FROM "CAL_TABLE_SCHEDULE" "
209 "WHERE id=%d AND %s>%ld ORDER BY %s LIMIT 1", field, id, field, now_t, field);
211 sqlite3_stmt *stmt = NULL;
212 ret = cal_db_util_query_prepare(query, &stmt);
213 if (CALENDAR_ERROR_NONE != ret) {
214 /* LCOV_EXCL_START */
215 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
216 SECURE("query[%s]", query);
222 ret = cal_db_util_stmt_step(stmt);
225 utime = (int64_t)sqlite3_column_int64(stmt, 0);
227 /* LCOV_EXCL_START */
232 ERR("Invalid return(%d)", ret);
237 sqlite3_finalize(stmt);
241 static int _get_todo_alert_localtime(const char *field, int event_id, time_t current)
244 char query[CAL_DB_SQL_MAX_LEN] = {0};
247 localtime_r(¤t, &st);
248 time_t mod_current = timegm(&st);
249 snprintf(query, sizeof(query), "SELECT %s FROM %s "
250 "WHERE id=%d AND strftime('%%s', %s)>%ld ORDER BY %s LIMIT 1",
251 field, CAL_TABLE_SCHEDULE, event_id, field, mod_current, field);
253 sqlite3_stmt *stmt = NULL;
254 ret = cal_db_util_query_prepare(query, &stmt);
255 if (CALENDAR_ERROR_NONE != ret) {
256 /* LCOV_EXCL_START */
257 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
258 SECURE("query[%s]", query);
263 const char *datetime = NULL;
264 if (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt))
265 datetime = (const char *)sqlite3_column_text(stmt, 0);
267 if (NULL == datetime || '\0' == *datetime) {
268 /* LCOV_EXCL_START */
269 ERR("Invalid datetime [%s]", datetime);
270 sqlite3_finalize(stmt);
275 int y = 0, m = 0, d = 0;
276 int h = 0, n = 0, s = 0;
277 sscanf(datetime, CAL_FORMAT_LOCAL_DATETIME, &y, &m, &d, &h, &n, &s);
278 sqlite3_finalize(stmt);
280 st.tm_year = y - 1900;
287 return (long long int)mktime(&st);
290 * to get aler time, time(NULL) is not accurate. 1 secs diff could be occured.
291 * so, searching DB is neccessary to find alert time.
293 int cal_server_alarm_get_alert_time(int alarm_id, time_t *tt_alert)
296 RETV_IF(NULL == tt_alert, CALENDAR_ERROR_INVALID_PARAMETER);
298 char query[CAL_DB_SQL_MAX_LEN] = {0};
299 snprintf(query, sizeof(query), "SELECT A.event_id, A.remind_tick_unit, A.remind_tick, "
300 "A.alarm_type, A.alarm_utime, A.alarm_datetime, B.type, B.dtstart_type, "
301 "B.dtend_type FROM %s as A, %s as B ON A.event_id =B.id WHERE alarm_id =%d ",
302 CAL_TABLE_ALARM, CAL_TABLE_SCHEDULE, alarm_id);
304 sqlite3_stmt *stmt = NULL;
305 ret = cal_db_util_query_prepare(query, &stmt);
306 if (CALENDAR_ERROR_NONE != ret) {
307 /* LCOV_EXCL_START */
308 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
309 SECURE("query[%s]", query);
318 long long int utime = 0;
319 const char *datetime = NULL;
321 int dtstart_type = 0;
325 if (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
326 event_id = sqlite3_column_int(stmt, 0);
327 unit = sqlite3_column_int(stmt, 1);
328 tick = sqlite3_column_int(stmt, 2);
329 type = sqlite3_column_int(stmt, 3);
330 utime = sqlite3_column_int64(stmt, 4);
331 datetime = (const char *)sqlite3_column_text(stmt, 5);
332 record_type = sqlite3_column_int(stmt, 6);
333 dtstart_type = sqlite3_column_int(stmt, 7);
334 dtend_type = sqlite3_column_int(stmt, 8);
337 if (NULL == tt_alert) {
338 /* LCOV_EXCL_START */
339 ERR("Invalid parameter: tt_alert is NULL");
340 sqlite3_finalize(stmt);
341 return CALENDAR_ERROR_INVALID_PARAMETER;
345 if (CALENDAR_ALARM_TIME_UNIT_SPECIFIC == unit) {
346 if (CALENDAR_TIME_UTIME == type) {
349 int y = 0, m = 0, d = 0;
350 int h = 0, n = 0, s = 0;
352 sscanf(datetime, CAL_FORMAT_LOCAL_DATETIME, &y, &m, &d, &h, &n, &s);
354 st.tm_year = y - 1900;
360 *tt_alert = mktime(&st);
361 DBG("datetime[%s] to %02d:%02d:%02d (%d)", datetime, h, n, s, *tt_alert);
364 sqlite3_finalize(stmt);
365 return CALENDAR_ERROR_NONE;
367 sqlite3_finalize(stmt);
369 time_t current = time(NULL);
370 current += (tick * unit);
371 current -= 2; /* in case time passed */
373 switch (record_type) {
374 case CALENDAR_BOOK_TYPE_EVENT:
375 switch (dtstart_type) {
376 case CALENDAR_TIME_UTIME:
377 utime = _get_event_alert_utime("dtstart_utime", event_id, current);
380 case CALENDAR_TIME_LOCALTIME:
381 utime = _get_event_alert_localtime("dtstart_datetime", event_id, current);
386 case CALENDAR_BOOK_TYPE_TODO:
387 switch (dtend_type) {
388 case CALENDAR_TIME_UTIME:
389 utime = _get_todo_alert_utime("dtend_utime", event_id, current);
392 case CALENDAR_TIME_LOCALTIME:
393 utime = _get_todo_alert_localtime("dtend_datetime", event_id, current);
398 DBG("alert_time(%d) = utime(%lld) - (tick(%d) * unit(%d))", *tt_alert, utime, tick, unit);
400 *tt_alert = utime - (tick * unit);
401 return CALENDAR_ERROR_NONE;
406 * true : to get all alarms including same time event.
407 * (ig. if 3 diffrent alarms exist at 06:30, list has 3 data)
408 * false : to get only one alarm to register in alarm-manager.
409 * (ig. if 3 diffrent alarms exist at 06:30, list has only one)
411 static void _cal_server_alarm_get_upcoming_specific_utime(time_t utime, bool get_all, GList **l)
414 char query[CAL_DB_SQL_MAX_LEN] = {0};
415 snprintf(query, sizeof(query), "SELECT event_id,remind_tick_unit,remind_tick,"
416 "alarm_type,alarm_utime,alarm_datetime "
417 "FROM %s WHERE remind_tick_unit =%d AND alarm_type =%d AND alarm_utime %s %ld %s",
418 CAL_TABLE_ALARM, CALENDAR_ALARM_TIME_UNIT_SPECIFIC, CALENDAR_TIME_UTIME,
419 true == get_all ? "=" : ">", utime,
420 true == get_all ? "" : "ORDER BY alarm_utime ASC LIMIT 1");
422 sqlite3_stmt *stmt = NULL;
423 ret = cal_db_util_query_prepare(query, &stmt);
424 if (CALENDAR_ERROR_NONE != ret) {
425 /* LCOV_EXCL_START */
426 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
427 SECURE("query[%s]", query);
432 while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
433 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
435 /* LCOV_EXCL_START */
436 ERR("calloc() Fail");
437 sqlite3_finalize(stmt);
442 ad->event_id = sqlite3_column_int(stmt, 0);
443 ad->unit = sqlite3_column_int(stmt, 1);
444 ad->tick = sqlite3_column_int(stmt, 2);
445 ad->type = sqlite3_column_int(stmt, 3);
446 ad->time = (long long int)sqlite3_column_int64(stmt, 4);
447 snprintf(ad->datetime, sizeof(ad->datetime), "%s", (const char *)sqlite3_column_text(stmt, 5));
448 *l = g_list_append(*l, ad);
449 DBG("found id(%d) unit(%d) tick(%d) type(%d) time(%lld) [%s]",
450 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
451 ad->alert_utime = ad->time;
452 if (false == get_all) break;
454 sqlite3_finalize(stmt);
457 static void _cal_server_alarm_get_upcoming_specific_localtime(const char *datetime, bool get_all, GList **l)
460 char query[CAL_DB_SQL_MAX_LEN] = {0};
461 snprintf(query, sizeof(query), "SELECT event_id,remind_tick_unit,remind_tick,"
462 "alarm_type,alarm_utime,alarm_datetime "
463 "FROM %s WHERE remind_tick_unit=%d AND alarm_type=%d AND alarm_datetime %s '%s' %s",
464 CAL_TABLE_ALARM, CALENDAR_ALARM_TIME_UNIT_SPECIFIC, CALENDAR_TIME_LOCALTIME,
465 true == get_all ? "=" : ">", datetime,
466 true == get_all ? "" : "ORDER BY alarm_datetime ASC LIMIT 1");
468 sqlite3_stmt *stmt = NULL;
469 ret = cal_db_util_query_prepare(query, &stmt);
470 if (CALENDAR_ERROR_NONE != ret) {
471 /* LCOV_EXCL_START */
472 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
473 SECURE("query[%s]", query);
478 while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
479 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
481 /* LCOV_EXCL_START */
482 ERR("calloc() Fail");
483 sqlite3_finalize(stmt);
488 ad->event_id = sqlite3_column_int(stmt, 0);
489 ad->unit = sqlite3_column_int(stmt, 1);
490 ad->tick = sqlite3_column_int(stmt, 2);
491 ad->type = sqlite3_column_int(stmt, 3);
492 ad->time = (long long int)sqlite3_column_int64(stmt, 4);
493 snprintf(ad->datetime, sizeof(ad->datetime), "%s", (const char *)sqlite3_column_text(stmt, 5));
494 *l = g_list_append(*l, ad);
495 DBG("found id(%d) unit(%d) tick(%d) type(%d) time(%lld) [%s]",
496 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
498 int y = 0, m = 0, d = 0;
499 int h = 0, n = 0, s = 0;
500 sscanf(ad->datetime, CAL_FORMAT_LOCAL_DATETIME, &y, &m, &d, &h, &n, &s);
503 st.tm_year = y - 1900;
509 ad->alert_utime = (long long int)mktime(&st);
510 if (false == get_all) break;
512 sqlite3_finalize(stmt);
515 static void _cal_server_alarm_get_upcoming_nonspecific_event_utime(time_t utime, bool get_all, GList **l)
522 char query[CAL_DB_SQL_MAX_LEN] = {0};
523 snprintf(query, sizeof(query), "SELECT A.event_id,A.remind_tick_unit,A.remind_tick, "
524 "A.alarm_type,B.dtstart_utime,A.alarm_datetime "
525 "FROM %s as A, %s as B ON A.event_id = B.event_id "
526 "WHERE A.remind_tick_unit >%d AND (B.dtstart_utime - (A.remind_tick_unit * A.remind_tick)) %s %ld %s",
527 CAL_TABLE_ALARM, CAL_TABLE_UTIME_INSTANCE, CALENDAR_ALARM_TIME_UNIT_SPECIFIC,
528 true == get_all ? "=" : ">", utime,
529 true == get_all ? "" : "ORDER BY (B.dtstart_utime - (A.remind_tick_unit * A.remind_tick)) LIMIT 1");
531 sqlite3_stmt *stmt = NULL;
532 ret = cal_db_util_query_prepare(query, &stmt);
533 if (CALENDAR_ERROR_NONE != ret) {
534 /* LCOV_EXCL_START */
535 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
536 SECURE("query[%s]", query);
541 while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
542 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
544 /* LCOV_EXCL_START */
545 ERR("calloc() Fail");
546 sqlite3_finalize(stmt);
551 ad->event_id = sqlite3_column_int(stmt, 0);
552 ad->unit = sqlite3_column_int(stmt, 1);
553 ad->tick = sqlite3_column_int(stmt, 2);
554 ad->type = sqlite3_column_int(stmt, 3);
555 ad->time = (long long int)sqlite3_column_int64(stmt, 4);
556 snprintf(ad->datetime, sizeof(ad->datetime), "%s", (const char *)sqlite3_column_text(stmt, 5));
557 *l = g_list_append(*l, ad);
558 DBG("found id(%d) unit(%d) tick(%d) type(%d) time(%lld) [%s]",
559 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
561 ad->alert_utime = ad->time - (ad->tick * ad->unit);
562 if (false == get_all) break;
564 sqlite3_finalize(stmt);
567 static void _cal_server_alarm_get_upcoming_nonspecific_event_localtime(const char *datetime, bool get_all, GList **l)
574 char query[CAL_DB_SQL_MAX_LEN] = {0};
575 snprintf(query, sizeof(query), "SELECT A.event_id,A.remind_tick_unit,A.remind_tick, "
576 "A.alarm_type,A.alarm_utime,B.dtstart_datetime "
577 "FROM %s as A, %s as B ON A.event_id = B.event_id "
578 "WHERE A.remind_tick_unit >%d AND "
579 "(strftime('%%s', B.dtstart_datetime) - (A.remind_tick_unit * A.remind_tick) - strftime('%%s', '%s') %s 0) %s",
580 CAL_TABLE_ALARM, CAL_TABLE_LOCALTIME_INSTANCE, CALENDAR_ALARM_TIME_UNIT_SPECIFIC,
581 datetime, true == get_all ? "=" : ">",
582 true == get_all ? "" : "ORDER BY (strftime('%s', B.dtstart_datetime) - (A.remind_tick_unit * A.remind_tick)) LIMIT 1 ");
583 sqlite3_stmt *stmt = NULL;
584 ret = cal_db_util_query_prepare(query, &stmt);
585 if (CALENDAR_ERROR_NONE != ret) {
586 /* LCOV_EXCL_START */
587 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
588 SECURE("query[%s]", query);
593 while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
594 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
596 /* LCOV_EXCL_START */
597 ERR("calloc() Fail");
598 sqlite3_finalize(stmt);
603 ad->event_id = sqlite3_column_int(stmt, 0);
604 ad->unit = sqlite3_column_int(stmt, 1);
605 ad->tick = sqlite3_column_int(stmt, 2);
606 ad->type = sqlite3_column_int(stmt, 3);
607 ad->time = (long long int)sqlite3_column_int64(stmt, 4);
608 snprintf(ad->datetime, sizeof(ad->datetime), "%s", (const char *)sqlite3_column_text(stmt, 5));
609 *l = g_list_append(*l, ad);
610 DBG("found id(%d) unit(%d) tick(%d) type(%d) time(%lld) [%s]",
611 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
613 int y = 0, m = 0, d = 0;
614 int h = 0, n = 0, s = 0;
615 sscanf(ad->datetime, CAL_FORMAT_LOCAL_DATETIME, &y, &m, &d, &h, &n, &s);
618 st.tm_year = y - 1900;
624 ad->alert_utime = (long long int)mktime(&st) - (ad->tick * ad->unit);
625 if (false == get_all) break;
627 sqlite3_finalize(stmt);
630 static void _cal_server_alarm_get_upcoming_nonspecific_todo_utime(time_t utime, bool get_all, GList **l)
637 char query[CAL_DB_SQL_MAX_LEN] = {0};
638 snprintf(query, sizeof(query), "SELECT A.event_id,A.remind_tick_unit,A.remind_tick,"
639 "A.alarm_type,B.dtend_utime,A.alarm_datetime "
640 "FROM %s as A, %s as B ON A.event_id = B.id "
641 "WHERE A.remind_tick_unit >%d AND B.type =%d "
642 "AND (B.dtend_utime - (A.remind_tick_unit * A.remind_tick)) %s %ld %s",
643 CAL_TABLE_ALARM, CAL_TABLE_SCHEDULE,
644 CALENDAR_ALARM_TIME_UNIT_SPECIFIC, CALENDAR_BOOK_TYPE_TODO,
645 true == get_all ? "=" : ">", utime,
646 true == get_all ? "" : "ORDER BY (B.dtend_utime - (A.remind_tick_unit * A.remind_tick)) LIMIT 1 ");
648 sqlite3_stmt *stmt = NULL;
649 ret = cal_db_util_query_prepare(query, &stmt);
650 if (CALENDAR_ERROR_NONE != ret) {
651 /* LCOV_EXCL_START */
652 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
653 SECURE("query[%s]", query);
658 while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
659 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
661 /* LCOV_EXCL_START */
662 ERR("calloc() Fail");
663 sqlite3_finalize(stmt);
668 ad->event_id = sqlite3_column_int(stmt, 0);
669 ad->unit = sqlite3_column_int(stmt, 1);
670 ad->tick = sqlite3_column_int(stmt, 2);
671 ad->type = sqlite3_column_int(stmt, 3);
672 ad->time = (long long int)sqlite3_column_int64(stmt, 4);
673 snprintf(ad->datetime, sizeof(ad->datetime), "%s", (const char *)sqlite3_column_text(stmt, 5));
674 *l = g_list_append(*l, ad);
675 DBG("found id(%d) unit(%d) tick(%d) type(%d) time(%lld) [%s]",
676 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
678 ad->alert_utime = ad->time - (ad->tick * ad->unit);
679 if (false == get_all) break;
681 sqlite3_finalize(stmt);
684 static void _cal_server_alarm_get_upcoming_nonspecific_todo_localtime(const char *datetime, bool get_all, GList **l)
691 char query[CAL_DB_SQL_MAX_LEN] = {0};
692 snprintf(query, sizeof(query), "SELECT A.event_id,A.remind_tick_unit,A.remind_tick,"
693 "A.alarm_type,A.alarm_utime,B.dtend_datetime "
694 "FROM %s as A, %s as B ON A.event_id = B.id "
695 "WHERE A.remind_tick_unit >%d AND B.type =%d "
696 "AND (strftime('%%s', B.dtend_datetime) - (A.remind_tick_unit * A.remind_tick) - strftime('%%s', '%s') %s 0) %s",
697 CAL_TABLE_ALARM, CAL_TABLE_SCHEDULE,
698 CALENDAR_ALARM_TIME_UNIT_SPECIFIC, CALENDAR_BOOK_TYPE_TODO,
699 datetime, true == get_all ? "=" : ">",
700 true == get_all ? "" : "ORDER BY (strftime('%s', B.dtend_datetime) - (A.remind_tick_unit * A.remind_tick)) LIMIT 1 ");
702 sqlite3_stmt *stmt = NULL;
703 ret = cal_db_util_query_prepare(query, &stmt);
704 if (CALENDAR_ERROR_NONE != ret) {
705 /* LCOV_EXCL_START */
706 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
707 SECURE("query[%s]", query);
712 while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
713 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
715 /* LCOV_EXCL_START */
716 ERR("calloc() Fail");
717 sqlite3_finalize(stmt);
722 ad->event_id = sqlite3_column_int(stmt, 0);
723 ad->unit = sqlite3_column_int(stmt, 1);
724 ad->tick = sqlite3_column_int(stmt, 2);
725 ad->type = sqlite3_column_int(stmt, 3);
726 ad->time = (long long int)sqlite3_column_int64(stmt, 4);
727 snprintf(ad->datetime, sizeof(ad->datetime), "%s", (const char *)sqlite3_column_text(stmt, 5));
728 *l = g_list_append(*l, ad);
729 DBG("found id(%d) unit(%d) tick(%d) type(%d) time(%lld) [%s]",
730 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
732 int y = 0, m = 0, d = 0;
733 int h = 0, n = 0, s = 0;
734 sscanf(ad->datetime, CAL_FORMAT_LOCAL_DATETIME, &y, &m, &d, &h, &n, &s);
737 st.tm_year = y - 1900;
743 ad->alert_utime = (long long int)mktime(&st) - (ad->tick * ad->unit);
744 if (false == get_all) break;
746 sqlite3_finalize(stmt);
749 static void _cal_server_alarm_get_latest(time_t utime, bool get_all, GList **out_l)
752 RET_IF(NULL == out_l);
755 struct tm st_local = {0};
756 localtime_r(&utime, &st_local);
758 char datetime[CAL_STR_SHORT_LEN32] = {0};
759 snprintf(datetime, sizeof(datetime), CAL_FORMAT_LOCAL_DATETIME,
760 st_local.tm_year +1900, st_local.tm_mon + 1, st_local.tm_mday,
761 st_local.tm_hour, st_local.tm_min, st_local.tm_sec);
762 DBG("get alert to register with given time (%ld) datetime[%s]", utime, datetime);
766 _cal_server_alarm_get_upcoming_specific_utime(utime, get_all, &l);
767 _cal_server_alarm_get_upcoming_nonspecific_event_utime(utime, get_all, &l);
768 _cal_server_alarm_get_upcoming_nonspecific_todo_utime(utime, get_all, &l);
770 _cal_server_alarm_get_upcoming_specific_localtime(datetime, get_all, &l);
771 _cal_server_alarm_get_upcoming_nonspecific_event_localtime(datetime, get_all, &l);
772 _cal_server_alarm_get_upcoming_nonspecific_todo_localtime(datetime, get_all, &l);
777 static gint _cal_server_alarm_sort_cb(gconstpointer a, gconstpointer b)
779 struct _alarm_data_s *p1 = (struct _alarm_data_s *)a;
780 struct _alarm_data_s *p2 = (struct _alarm_data_s *)b;
781 DBG("%lld) > (%lld)", p1->alert_utime, p2->alert_utime);
783 return p1->alert_utime < p2->alert_utime ? -1 : 1;
786 static GFunc _cal_server_alarm_print_cb(gpointer data, gpointer user_data)
788 struct _alarm_data_s *ad = (struct _alarm_data_s *)data;
789 DBG("id(%d) unit(%d) tick(%d) type(%d) time(%lld) datetime[%s]",
790 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
794 static int _cal_server_alarm_register(GList *alarm_list)
797 RETV_IF(NULL == alarm_list, CALENDAR_ERROR_INVALID_PARAMETER);
799 int ret = CALENDAR_ERROR_NONE;
800 GList *l = g_list_first(alarm_list);
801 struct _alarm_data_s *ad = (struct _alarm_data_s *)l->data;
802 RETVM_IF(NULL == ad, CALENDAR_ERROR_DB_FAILED, "No data");
804 /* clear all alarm which set by mine. */
805 ret = alarmmgr_enum_alarm_ids(_cal_server_alarm_clear_all_cb, NULL);
806 if (ret != ALARMMGR_RESULT_SUCCESS) {
807 /* LCOV_EXCL_START */
808 ERR("alarmmgr_enum_alarm_ids() Fail");
813 time_t mod_time = (time_t)ad->alert_utime;
814 alarm_entry_t *alarm_info = NULL;
815 alarm_info = alarmmgr_create_alarm();
816 if (NULL == alarm_info) {
817 /* LCOV_EXCL_START */
818 ERR("Failed to create alarm");
819 return CALENDAR_ERROR_DB_FAILED;
823 struct tm st_alarm = {0};
825 switch (ad->system_type) {
826 case CALENDAR_SYSTEM_EAST_ASIAN_LUNISOLAR:
827 gmtime_r(&mod_time, &st_alarm);
832 localtime_r(&mod_time, &st_alarm);
836 alarm_date_t date = {0};
837 date.year = st_alarm.tm_year + 1900;
838 date.month = st_alarm.tm_mon + 1;
839 date.day = st_alarm.tm_mday;
840 date.hour = st_alarm.tm_hour;
841 date.min = st_alarm.tm_min;
842 date.sec = st_alarm.tm_sec;
843 alarmmgr_set_time(alarm_info, date);
844 DBG(COLOR_CYAN" >>> registered record id (%d) at %04d/%02d/%02d %02d:%02d:%02d "COLOR_END" (utime(%lld), datetime[%s], tick(%d) unit(%d))",
845 ad->event_id, date.year, date.month, date.day, date.hour, date.min, date.sec,
846 ad->time, ad->datetime, ad->tick, ad->unit);
849 ret = alarmmgr_add_alarm_with_localtime(alarm_info, NULL, &alarm_id);
851 /* LCOV_EXCL_START */
852 ERR("alarmmgr_add_alarm_with_localtime Fail (%d)", ret);
853 alarmmgr_free_alarm(alarm_info);
857 DBG("alarmmgr id (%d)", alarm_id);
858 _cal_server_alarm_update_alarm_id(alarm_id, ad->event_id, ad->tick, ad->unit);
859 alarmmgr_free_alarm(alarm_info);
860 return CALENDAR_ERROR_NONE;
867 static bool __app_matched_cb(app_control_h app_control, const char *package, void *user_data)
874 RETV_IF(NULL == user_data, true);
877 ret = app_control_get_mime(app_control, &mime);
878 RETVM_IF(APP_CONTROL_ERROR_NONE != ret, true, "app_control_get_mime() Fail(%d)", ret);
880 const char *reminder_mime = "application/x-tizen.calendar.reminder";
881 if (strncmp(mime, reminder_mime, strlen(reminder_mime))) { /* not same */
882 DBG("get mime[%s] is not [%s]", mime, reminder_mime);
888 struct alarm_ud *au = (struct alarm_ud *)user_data;
889 GList *alarm_list = au->alarm_list;
890 if (NULL == alarm_list) {
891 /* LCOV_EXCL_START */
897 len = g_list_length(alarm_list);
899 DBG("len is 0, no alarm list");
903 app_control_h ac = NULL;
904 ret = app_control_create(&ac);
905 if (APP_CONTROL_ERROR_NONE != ret) {
906 /* LCOV_EXCL_START */
907 ERR("app_control_create() Fail(%d)", ret);
911 ret = app_control_set_operation(ac, APP_CONTROL_OPERATION_DEFAULT);
912 if (APP_CONTROL_ERROR_NONE != ret) {
913 /* LCOV_EXCL_START */
914 ERR("app_control_create() Fail(%d)", ret);
915 app_control_destroy(ac);
919 ret = app_control_set_app_id(ac, package);
920 if (APP_CONTROL_ERROR_NONE != ret) {
921 /* LCOV_EXCL_START */
922 ERR("app_control_set_app_id() Fail(%d)", ret);
923 app_control_destroy(ac);
929 ids = calloc(len, sizeof(char *));
931 /* LCOV_EXCL_START */
932 ERR("calloc() Fail");
933 app_control_destroy(ac);
937 GList *cursor = g_list_first(alarm_list);
938 for (i = 0; i < len; i++) {
939 struct _alarm_data_s *ad = (struct _alarm_data_s *)cursor->data;
942 cursor = g_list_next(cursor);
945 DBG("pkg[%s] time[%lld] tick[%d] unit[%d] record_type[%d]",
946 package, ad->time, ad->tick, ad->unit, ad->record);
949 char extra[CAL_STR_MIDDLE_LEN] = {0};
950 slen = snprintf(extra, sizeof(extra), "%s=%d", "id", ad->event_id);
951 slen += snprintf(extra+slen, sizeof(extra)-slen, "&%s=%lld", "time", ad->time);
952 slen += snprintf(extra+slen, sizeof(extra)-slen, "&%s=%d", "tick", ad->tick);
953 slen += snprintf(extra+slen, sizeof(extra)-slen, "&%s=%d", "unit", ad->unit);
954 slen += snprintf(extra+slen, sizeof(extra)-slen, "&%s=%d", "type", ad->record);
957 * key: id, value: id=4&time=123123&..
959 char buf_id[CAL_STR_MIDDLE_LEN] = {0};
960 snprintf(buf_id, sizeof(buf_id), "%d", ad->event_id);
961 app_control_add_extra_data(ac, buf_id, extra);
962 DBG("value[%s] id[%s]", extra, buf_id);
965 ids[i] = strdup(buf_id);
967 cursor = g_list_next(cursor);
969 app_control_add_extra_data_array(ac, "ids", (const char **)ids, len);
970 app_control_send_launch_request(ac, NULL, NULL);
971 app_control_destroy(ac);
973 g_list_free_full(alarm_list, free);
974 for (i = 0; i < len; i++) {
983 static void _cal_server_alarm_noti_with_control(GList *alarm_list)
988 RETM_IF(NULL == alarm_list, "No alarm list");
990 app_control_h app_control = NULL;
991 ret = app_control_create(&app_control);
992 if (APP_CONTROL_ERROR_NONE != ret) {
993 /* LCOV_EXCL_START */
994 ERR("app_control_create() Fail(%d)", ret);
998 ret = app_control_set_operation(app_control, APP_CONTROL_OPERATION_VIEW);
999 if (APP_CONTROL_ERROR_NONE != ret) {
1000 /* LCOV_EXCL_START */
1001 ERR("app_control_set_operation() Fail(%d)", ret);
1002 app_control_destroy(app_control);
1004 /* LCOV_EXCL_STOP */
1006 ret = app_control_set_mime(app_control, "application/x-tizen.calendar.reminder");
1007 if (APP_CONTROL_ERROR_NONE != ret) {
1008 /* LCOV_EXCL_START */
1009 ERR("app_control_set_mime() Fail(%d)", ret);
1010 app_control_destroy(app_control);
1012 /* LCOV_EXCL_STOP */
1015 struct alarm_ud *au = calloc(1, sizeof(struct alarm_ud));
1017 /* LCOV_EXCL_START */
1018 ERR("calloc() Fail");
1019 app_control_destroy(app_control);
1021 /* LCOV_EXCL_STOP */
1023 au->alarm_list = alarm_list;
1024 ret = app_control_foreach_app_matched(app_control, __app_matched_cb, au);
1025 if (APP_CONTROL_ERROR_NONE != ret) {
1026 /* LCOV_EXCL_START */
1027 ERR("app_control_foreach_app_matched() Fail(%d)", ret);
1029 app_control_destroy(app_control);
1031 /* LCOV_EXCL_STOP */
1034 app_control_destroy(app_control);
1037 static void _cal_server_alarm_noti_with_callback(GList *alarm_list)
1039 RETM_IF(NULL == alarm_list, "No alarm list");
1041 GList *l = g_list_first(alarm_list);
1043 struct _alarm_data_s *ad = (struct _alarm_data_s *)l->data;
1049 DBG("callback time[%lld] tick[%d] unit[%d] record_type[%d]",
1050 ad->time, ad->tick, ad->unit, ad->record);
1053 char extra[CAL_STR_MIDDLE_LEN] = {0};
1054 len = snprintf(extra, sizeof(extra), "%s=%d", "id", ad->event_id);
1055 len += snprintf(extra+len, sizeof(extra)-len, "&%s=%lld", "time", ad->time);
1056 len += snprintf(extra+len, sizeof(extra)-len, "&%s=%d", "tick", ad->tick);
1057 len += snprintf(extra+len, sizeof(extra)-len, "&%s=%d", "unit", ad->unit);
1058 len += snprintf(extra+len, sizeof(extra)-len, "&%s=%d", "type", ad->record);
1059 cal_dbus_publish_reminder(len, extra);
1065 int cal_server_alarm_register_next_alarm(time_t utime)
1068 _cal_server_alarm_get_latest(utime, false, &l);
1070 return CALENDAR_ERROR_NONE;
1072 l = g_list_sort(l, _cal_server_alarm_sort_cb);
1073 g_list_foreach(l, (GFunc)_cal_server_alarm_print_cb, NULL);
1074 _cal_server_alarm_register(l);
1076 g_list_free_full(l, free);
1077 return CALENDAR_ERROR_NONE;
1080 void cal_server_alarm_alert(time_t tt_alert)
1083 _cal_server_alarm_get_latest(tt_alert, true, &l);
1087 _cal_server_alarm_noti_with_callback(l);
1088 _cal_server_alarm_noti_with_control(l);
1089 /* DO NOT FREE LIST, list is freed in callback */
1092 static int _alert_cb(alarm_id_t alarm_id, void *data)
1095 DBG("alarm_id (%ld)", alarm_id);
1097 time_t tt_alert = 0;
1098 cal_server_alarm_get_alert_time(alarm_id, &tt_alert);
1099 cal_server_alarm_alert(tt_alert);
1100 _cal_server_alarm_unset_alerted_alarmmgr_id(alarm_id);
1101 cal_server_alarm_register_next_alarm(tt_alert);
1105 static void _cal_server_alarm_timechange_cb(keynode_t *node, void *data)
1107 time_t t = time(NULL);
1108 cal_server_alarm_alert(t);
1109 cal_server_alarm_register_next_alarm(t);
1112 void _cal_server_alarm_set_timechange(void)
1114 vconf_notify_key_changed(VCONFKEY_SYSTEM_TIME_CHANGED,
1115 _cal_server_alarm_timechange_cb, NULL);
1116 vconf_notify_key_changed(VCONFKEY_TELEPHONY_NITZ_GMT,
1117 _cal_server_alarm_timechange_cb, NULL);
1118 vconf_notify_key_changed(VCONFKEY_TELEPHONY_NITZ_EVENT_GMT,
1119 _cal_server_alarm_timechange_cb, NULL);
1120 vconf_notify_key_changed(VCONFKEY_TELEPHONY_NITZ_ZONE,
1121 _cal_server_alarm_timechange_cb, NULL);
1124 void _cal_server_alarm_unset_timechange(void)
1126 vconf_ignore_key_changed(VCONFKEY_SYSTEM_TIME_CHANGED,
1127 _cal_server_alarm_timechange_cb);
1128 vconf_ignore_key_changed(VCONFKEY_TELEPHONY_NITZ_GMT,
1129 _cal_server_alarm_timechange_cb);
1130 vconf_ignore_key_changed(VCONFKEY_TELEPHONY_NITZ_EVENT_GMT,
1131 _cal_server_alarm_timechange_cb);
1132 vconf_ignore_key_changed(VCONFKEY_TELEPHONY_NITZ_ZONE,
1133 _cal_server_alarm_timechange_cb);
1136 static void _changed_cb(const char* view_uri, void* data)
1139 cal_server_alarm_register_next_alarm(time(NULL));
1142 static int _cal_server_alarm_set_inotify(calendar_db_changed_cb callback)
1144 cal_inotify_subscribe(CAL_NOTI_TYPE_EVENT, CAL_NOTI_FILE_EVENT, callback, NULL);
1145 cal_inotify_subscribe(CAL_NOTI_TYPE_TODO, CAL_NOTI_FILE_TODO, callback, NULL);
1149 static void _cal_server_alarm_unset_inotify(calendar_db_changed_cb callback)
1151 cal_inotify_unsubscribe(CAL_NOTI_FILE_EVENT, callback, NULL);
1152 cal_inotify_unsubscribe(CAL_NOTI_FILE_TODO, callback, NULL);
1155 int cal_server_alarm_init(void)
1160 _cal_server_alarm_set_timechange();
1161 _cal_server_alarm_set_inotify(_changed_cb);
1163 ret = alarmmgr_init("calendar-service");
1165 /* LCOV_EXCL_START */
1166 ERR("alarmmgr_init() Fail(%d)", ret);
1167 return CALENDAR_ERROR_SYSTEM;
1168 /* LCOV_EXCL_STOP */
1171 ret = alarmmgr_set_cb(_alert_cb, NULL);
1173 /* LCOV_EXCL_START */
1174 ERR("alarmmgr_set_cb() Fail(%d)", ret);
1175 return CALENDAR_ERROR_SYSTEM;
1176 /* LCOV_EXCL_STOP */
1179 cal_server_alarm_register_next_alarm(time(NULL));
1180 return CALENDAR_ERROR_NONE;
1183 void cal_server_alarm_deinit(void)
1186 _cal_server_alarm_unset_inotify(_changed_cb);
1187 _cal_server_alarm_unset_timechange();