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.
28 #include "cal_typedef.h"
29 #include "cal_internal.h"
31 #include "cal_inotify.h"
32 #include "cal_db_util.h"
34 #include "cal_db_query.h"
35 #include "cal_server_service.h"
36 #include "cal_server_ondemand.h"
37 #include "cal_server_dbus.h"
38 #include "cal_server_alarm.h"
40 #define CAL_SERVER_ALARM_THREAD_NAME "cal_server_alarm"
42 GThread *_cal_server_alarm_thread = NULL;
43 GCond _cal_server_alarm_cond;
44 GMutex _cal_server_alarm_mutex;
45 static bool server_killed = false;
46 static bool signal_called = false;
48 struct _alarm_data_s {
50 long long int alert_utime; /* to compare */
53 int type; /* utime, localtime */
55 int record; /* todo, event */
56 char datetime[CAL_STR_SHORT_LEN32];
64 /* this api is necessary for repeat instance. */
65 static int cal_server_alarm_unset_alerted_alarmmgr_id(int alarm_id)
67 char query[CAL_DB_SQL_MAX_LEN] = {0};
70 ret = cal_db_util_begin_trans();
71 if (CALENDAR_ERROR_NONE != ret) {
73 ERR("cal_db_util_begin_trans() Fail");
74 return CALENDAR_ERROR_DB_FAILED;
78 DBG("alarm_id(%d)", alarm_id);
80 snprintf(query, sizeof(query), "UPDATE %s SET alarm_id = 0 WHERE alarm_id =%d ",
81 CAL_TABLE_ALARM, alarm_id);
82 ret = cal_db_util_query_exec(query);
83 if (CALENDAR_ERROR_NONE != ret) {
85 ERR("cal_db_util_query_exec() Fail(%d)", ret);
86 SECURE("[%s]", query);
87 cal_db_util_end_trans(false);
91 cal_db_util_end_trans(true);
92 return CALENDAR_ERROR_NONE;
95 static int _cal_server_alarm_clear_all_cb(alarm_id_t alarm_id, void *data)
99 DBG("remove alarm id(%d)", alarm_id);
100 cal_server_alarm_unset_alerted_alarmmgr_id(alarm_id);
101 ret = alarmmgr_remove_alarm(alarm_id);
102 if (ret != ALARMMGR_RESULT_SUCCESS) {
103 /* LCOV_EXCL_START */
104 ERR("alarmmgr_remove_alarm() Fail(ret:%d)", ret);
108 return CALENDAR_ERROR_NONE;
111 static int _cal_server_alarm_update_alarm_id(int alarm_id, int event_id, int tick, int unit)
113 char query[CAL_DB_SQL_MAX_LEN] = {0};
116 ret = cal_db_util_begin_trans();
117 if (CALENDAR_ERROR_NONE != ret) {
118 /* LCOV_EXCL_START */
119 ERR("cal_db_util_begin_trans() Fail");
120 return CALENDAR_ERROR_DB_FAILED;
124 DBG("Update alarm_id(%d) in alarm table", alarm_id);
125 snprintf(query, sizeof(query), "UPDATE %s SET alarm_id =%d "
126 "WHERE event_id =%d AND remind_tick =%d AND remind_tick_unit =%d",
127 CAL_TABLE_ALARM, alarm_id, event_id, tick, unit);
128 ret = cal_db_util_query_exec(query);
129 if (CALENDAR_ERROR_NONE != ret) {
130 /* LCOV_EXCL_START */
131 ERR("cal_db_util_query_exec() Fail(%d)", ret);
132 SECURE("[%s]", query);
133 cal_db_util_end_trans(false);
137 cal_db_util_end_trans(true);
138 return CALENDAR_ERROR_NONE;
141 static long long int _get_event_alert_utime(const char *field, int event_id, time_t current)
144 char query[CAL_DB_SQL_MAX_LEN] = {0};
145 snprintf(query, sizeof(query), "SELECT %s FROM %s "
146 "WHERE event_id=%d AND %s>%ld ORDER BY %s LIMIT 1",
147 field, CAL_TABLE_UTIME_INSTANCE, event_id, field, current, field);
149 sqlite3_stmt *stmt = NULL;
150 ret = cal_db_util_query_prepare(query, &stmt);
151 if (CALENDAR_ERROR_NONE != ret) {
152 /* LCOV_EXCL_START */
153 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
154 SECURE("query[%s]", query);
159 long long int utime = 0;
160 if (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt))
161 utime = sqlite3_column_int(stmt, 0);
163 sqlite3_finalize(stmt);
167 static int _get_event_alert_localtime(const char *field, int event_id, time_t current)
170 char query[CAL_DB_SQL_MAX_LEN] = {0};
172 snprintf(query, sizeof(query), "SELECT %s FROM %s "
173 "WHERE event_id=%d AND (strftime('%%s', %s) - %ld > 0) ORDER BY %s LIMIT 1",
174 field, CAL_TABLE_LOCALTIME_INSTANCE, event_id, field, current, field);
176 sqlite3_stmt *stmt = NULL;
177 ret = cal_db_util_query_prepare(query, &stmt);
178 if (CALENDAR_ERROR_NONE != ret) {
179 /* LCOV_EXCL_START */
180 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
181 SECURE("query[%s]", query);
186 const char *datetime = NULL;
187 if (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt))
188 datetime = (const char *)sqlite3_column_text(stmt, 0);
190 if (NULL == datetime || '\0' == *datetime) {
191 /* LCOV_EXCL_START */
192 ERR("Invalid datetime [%s]", datetime);
193 sqlite3_finalize(stmt);
198 int y = 0, m = 0, d = 0;
199 int h = 0, n = 0, s = 0;
200 sscanf(datetime, CAL_FORMAT_LOCAL_DATETIME, &y, &m, &d, &h, &n, &s);
201 sqlite3_finalize(stmt);
203 st.tm_year = y - 1900;
209 st.tm_isdst = cal_time_is_dst_savings();
211 return (long long int)mktime(&st);
214 static int64_t _get_todo_alert_utime(const char *field, int id, time_t now_t)
217 char query[CAL_DB_SQL_MAX_LEN] = {0};
218 snprintf(query, sizeof(query), "SELECT %s FROM "CAL_TABLE_SCHEDULE" "
219 "WHERE id=%d AND %s>%ld ORDER BY %s LIMIT 1", field, id, field, now_t, field);
221 sqlite3_stmt *stmt = NULL;
222 ret = cal_db_util_query_prepare(query, &stmt);
223 if (CALENDAR_ERROR_NONE != ret) {
224 /* LCOV_EXCL_START */
225 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
226 SECURE("query[%s]", query);
232 ret = cal_db_util_stmt_step(stmt);
235 utime = (int64_t)sqlite3_column_int64(stmt, 0);
240 break;*/ //Svace:371986
242 ERR("Invalid return(%d)", ret);
247 sqlite3_finalize(stmt);
251 static int _get_todo_alert_localtime(const char *field, int event_id, time_t current)
254 char query[CAL_DB_SQL_MAX_LEN] = {0};
256 snprintf(query, sizeof(query), "SELECT %s FROM %s "
257 "WHERE id=%d AND (strftime('%%s', %s) - %ld > 0) ORDER BY %s LIMIT 1",
258 field, CAL_TABLE_SCHEDULE, event_id, field, current, field);
260 sqlite3_stmt *stmt = NULL;
261 ret = cal_db_util_query_prepare(query, &stmt);
262 if (CALENDAR_ERROR_NONE != ret) {
263 /* LCOV_EXCL_START */
264 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
265 SECURE("query[%s]", query);
270 const char *datetime = NULL;
271 if (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt))
272 datetime = (const char *)sqlite3_column_text(stmt, 0);
274 if (NULL == datetime || '\0' == *datetime) {
275 /* LCOV_EXCL_START */
276 ERR("Invalid datetime [%s]", datetime);
277 sqlite3_finalize(stmt);
282 int y = 0, m = 0, d = 0;
283 int h = 0, n = 0, s = 0;
284 sscanf(datetime, CAL_FORMAT_LOCAL_DATETIME, &y, &m, &d, &h, &n, &s);
285 sqlite3_finalize(stmt);
287 st.tm_year = y - 1900;
293 st.tm_isdst = cal_time_is_dst_savings();
295 return (long long int)mktime(&st);
298 * time(NULL) is not appropriate as parameter.
299 * 1 seconds could be flowed before calling function.(1 sec time diff)
300 * so, searching DB is neccessary to find alert time.
302 static int cal_server_alarm_get_alert_time(int alarm_id, time_t *tt_alert)
305 RETV_IF(NULL == tt_alert, CALENDAR_ERROR_INVALID_PARAMETER);
307 char query[CAL_DB_SQL_MAX_LEN] = {0};
308 snprintf(query, sizeof(query), "SELECT A.event_id, A.remind_tick_unit, A.remind_tick, "
309 "A.alarm_type, A.alarm_utime, A.alarm_datetime, B.type, B.dtstart_type, "
310 "B.dtend_type FROM %s as A, %s as B ON A.event_id =B.id WHERE alarm_id =%d ",
311 CAL_TABLE_ALARM, CAL_TABLE_SCHEDULE, alarm_id);
313 sqlite3_stmt *stmt = NULL;
314 ret = cal_db_util_query_prepare(query, &stmt);
315 if (CALENDAR_ERROR_NONE != ret) {
316 /* LCOV_EXCL_START */
317 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
318 SECURE("query[%s]", query);
327 long long int utime = 0;
328 const char *datetime = NULL;
330 int dtstart_type = 0;
334 if (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
335 event_id = sqlite3_column_int(stmt, 0);
336 unit = sqlite3_column_int(stmt, 1);
337 tick = sqlite3_column_int(stmt, 2);
338 type = sqlite3_column_int(stmt, 3);
339 utime = sqlite3_column_int64(stmt, 4);
340 datetime = (const char *)sqlite3_column_text(stmt, 5);
341 record_type = sqlite3_column_int(stmt, 6);
342 dtstart_type = sqlite3_column_int(stmt, 7);
343 dtend_type = sqlite3_column_int(stmt, 8);
346 if (CALENDAR_ALARM_TIME_UNIT_SPECIFIC == unit) {
347 if (CALENDAR_TIME_UTIME == type) {
350 int y = 0, m = 0, d = 0;
351 int h = 0, n = 0, s = 0;
353 sscanf(datetime, CAL_FORMAT_LOCAL_DATETIME, &y, &m, &d, &h, &n, &s);
355 st.tm_year = y - 1900;
361 st.tm_isdst = cal_time_is_dst_savings();
362 *tt_alert = mktime(&st);
363 DBG("datetime[%s] to %02d:%02d:%02d (%ld)", datetime, h, n, s, *tt_alert);
366 sqlite3_finalize(stmt);
367 return CALENDAR_ERROR_NONE;
369 sqlite3_finalize(stmt);
371 time_t current = time(NULL);
372 current += (tick * unit);
373 current -= 2; /* in case time passed */
375 switch (record_type) {
376 case CALENDAR_BOOK_TYPE_EVENT:
377 switch (dtstart_type) {
378 case CALENDAR_TIME_UTIME:
379 utime = _get_event_alert_utime("dtstart_utime", event_id, current);
382 case CALENDAR_TIME_LOCALTIME:
383 utime = _get_event_alert_localtime("dtstart_datetime", event_id, current);
388 case CALENDAR_BOOK_TYPE_TODO:
389 switch (dtend_type) {
390 case CALENDAR_TIME_UTIME:
391 utime = _get_todo_alert_utime("dtend_utime", event_id, current);
394 case CALENDAR_TIME_LOCALTIME:
395 utime = _get_todo_alert_localtime("dtend_datetime", event_id, current);
400 *tt_alert = utime - (tick * unit);
402 DBG("alert_time(%ld) = utime(%lld) - (tick(%d) * unit(%d))", *tt_alert, utime, tick, unit);
404 return CALENDAR_ERROR_NONE;
409 * true : to get all alarms including same time event.
410 * (ig. if 3 diffrent alarms exist at 06:30, list has 3 data)
411 * false : to get only one alarm to register in alarm-manager.
412 * (ig. if 3 diffrent alarms exist at 06:30, list has only one)
414 static void _cal_server_alarm_get_upcoming_specific_utime(time_t utime, bool get_all, GList **l)
417 char query[CAL_DB_SQL_MAX_LEN] = {0};
418 snprintf(query, sizeof(query), "SELECT A.event_id, A.remind_tick_unit, A.remind_tick,"
419 "A.alarm_type, A.alarm_utime, A.alarm_datetime "
420 "FROM "CAL_TABLE_ALARM" as A, "CAL_TABLE_SCHEDULE" as S ON A.event_id = S.id "
421 "WHERE S.link_base_id = 0 AND A.remind_tick_unit = %d AND A.alarm_type = %d "
422 "AND A.alarm_utime %s %ld %s",
423 CALENDAR_ALARM_TIME_UNIT_SPECIFIC, CALENDAR_TIME_UTIME,
424 true == get_all ? "=" : ">", utime,
425 true == get_all ? "" : "ORDER BY alarm_utime ASC LIMIT 1");
427 sqlite3_stmt *stmt = NULL;
428 ret = cal_db_util_query_prepare(query, &stmt);
429 if (CALENDAR_ERROR_NONE != ret) {
430 /* LCOV_EXCL_START */
431 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
432 SECURE("query[%s]", query);
437 while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
438 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
440 /* LCOV_EXCL_START */
441 ERR("calloc() Fail");
442 sqlite3_finalize(stmt);
447 ad->event_id = sqlite3_column_int(stmt, 0);
448 ad->unit = sqlite3_column_int(stmt, 1);
449 ad->tick = sqlite3_column_int(stmt, 2);
450 ad->type = sqlite3_column_int(stmt, 3);
451 ad->time = (long long int)sqlite3_column_int64(stmt, 4);
452 snprintf(ad->datetime, sizeof(ad->datetime), "%s", (const char *)sqlite3_column_text(stmt, 5));
453 *l = g_list_append(*l, ad);
454 DBG("found id(%d) unit(%d) tick(%d) type(%d) time(%lld) [%s]",
455 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
456 ad->alert_utime = ad->time;
457 if (false == get_all) break;
459 sqlite3_finalize(stmt);
462 static void _cal_server_alarm_get_upcoming_specific_localtime(const char *datetime, bool get_all, GList **l)
465 char query[CAL_DB_SQL_MAX_LEN] = {0};
466 snprintf(query, sizeof(query), "SELECT A.event_id, A.remind_tick_unit, A.remind_tick,"
467 "A.alarm_type, A.alarm_utime, A.alarm_datetime "
468 "FROM "CAL_TABLE_ALARM" as A, "CAL_TABLE_SCHEDULE" as S ON A.event_id = S.id "
469 "WHERE S.link_base_id = 0 AND A.remind_tick_unit = %d AND A.alarm_type = %d "
470 "AND A.alarm_datetime %s '%s' %s",
471 CALENDAR_ALARM_TIME_UNIT_SPECIFIC, CALENDAR_TIME_LOCALTIME,
472 true == get_all ? "=" : ">", datetime,
473 true == get_all ? "" : "ORDER BY alarm_datetime ASC LIMIT 1");
475 sqlite3_stmt *stmt = NULL;
476 ret = cal_db_util_query_prepare(query, &stmt);
477 if (CALENDAR_ERROR_NONE != ret) {
478 /* LCOV_EXCL_START */
479 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
480 SECURE("query[%s]", query);
485 while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
486 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
488 /* LCOV_EXCL_START */
489 ERR("calloc() Fail");
490 sqlite3_finalize(stmt);
495 ad->event_id = sqlite3_column_int(stmt, 0);
496 ad->unit = sqlite3_column_int(stmt, 1);
497 ad->tick = sqlite3_column_int(stmt, 2);
498 ad->type = sqlite3_column_int(stmt, 3);
499 ad->time = (long long int)sqlite3_column_int64(stmt, 4);
500 snprintf(ad->datetime, sizeof(ad->datetime), "%s", (const char *)sqlite3_column_text(stmt, 5));
501 *l = g_list_append(*l, ad);
502 DBG("found id(%d) unit(%d) tick(%d) type(%d) time(%lld) [%s]",
503 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
505 int y = 0, m = 0, d = 0;
506 int h = 0, n = 0, s = 0;
507 sscanf(ad->datetime, CAL_FORMAT_LOCAL_DATETIME, &y, &m, &d, &h, &n, &s);
510 st.tm_year = y - 1900;
516 st.tm_isdst = cal_time_is_dst_savings();
517 ad->alert_utime = (long long int)mktime(&st);
518 if (false == get_all) break;
520 sqlite3_finalize(stmt);
523 static void _cal_server_alarm_get_upcoming_nonspecific_event_utime(time_t utime, bool get_all, GList **l)
530 char query[CAL_DB_SQL_MAX_LEN] = {0};
531 snprintf(query, sizeof(query), "SELECT A.event_id,A.remind_tick_unit,A.remind_tick, "
532 "A.alarm_type,B.dtstart_utime,A.alarm_datetime "
533 "FROM "CAL_TABLE_ALARM" as A, "CAL_TABLE_UTIME_INSTANCE" as B, "CAL_TABLE_SCHEDULE" as S "
534 "ON A.event_id = B.event_id AND B.event_id = S.id "
535 "WHERE S.link_base_id = 0 AND A.remind_tick_unit > %d "
536 "AND (B.dtstart_utime - (A.remind_tick_unit * A.remind_tick)) %s %ld %s",
537 CALENDAR_ALARM_TIME_UNIT_SPECIFIC,
538 true == get_all ? "=" : ">", utime,
539 true == get_all ? "" : "ORDER BY (B.dtstart_utime - (A.remind_tick_unit * A.remind_tick)) LIMIT 1");
541 sqlite3_stmt *stmt = NULL;
542 ret = cal_db_util_query_prepare(query, &stmt);
543 if (CALENDAR_ERROR_NONE != ret) {
544 /* LCOV_EXCL_START */
545 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
546 SECURE("query[%s]", query);
551 while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
552 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
554 /* LCOV_EXCL_START */
555 ERR("calloc() Fail");
556 sqlite3_finalize(stmt);
561 ad->event_id = sqlite3_column_int(stmt, 0);
562 ad->unit = sqlite3_column_int(stmt, 1);
563 ad->tick = sqlite3_column_int(stmt, 2);
564 ad->type = sqlite3_column_int(stmt, 3);
565 ad->time = (long long int)sqlite3_column_int64(stmt, 4);
566 snprintf(ad->datetime, sizeof(ad->datetime), "%s", (const char *)sqlite3_column_text(stmt, 5));
567 *l = g_list_append(*l, ad);
568 DBG("found id(%d) unit(%d) tick(%d) type(%d) time(%lld) [%s]",
569 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
571 ad->alert_utime = ad->time - (ad->tick * ad->unit);
572 if (false == get_all) break;
574 sqlite3_finalize(stmt);
577 static void _cal_server_alarm_get_upcoming_nonspecific_event_localtime(const char *datetime, bool get_all, GList **l)
584 char query[CAL_DB_SQL_MAX_LEN] = {0};
585 snprintf(query, sizeof(query), "SELECT A.event_id, A.remind_tick_unit, A.remind_tick, "
586 "A.alarm_type, A.alarm_utime, B.dtstart_datetime "
587 "FROM "CAL_TABLE_ALARM" as A, "CAL_TABLE_LOCALTIME_INSTANCE" as B, "CAL_TABLE_SCHEDULE" as S "
588 "ON A.event_id = B.event_id AND B.event_id = S.id "
589 "WHERE S.link_base_id = 0 AND A.remind_tick_unit >%d AND "
590 "(strftime('%%s', B.dtstart_datetime) - (A.remind_tick_unit * A.remind_tick) - strftime('%%s', '%s') %s 0) %s",
591 CALENDAR_ALARM_TIME_UNIT_SPECIFIC,
592 datetime, true == get_all ? "=" : ">",
593 true == get_all ? "" : "ORDER BY (strftime('%s', B.dtstart_datetime) - (A.remind_tick_unit * A.remind_tick)) LIMIT 1 ");
594 sqlite3_stmt *stmt = NULL;
595 ret = cal_db_util_query_prepare(query, &stmt);
596 if (CALENDAR_ERROR_NONE != ret) {
597 /* LCOV_EXCL_START */
598 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
599 SECURE("query[%s]", query);
604 while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
605 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
607 /* LCOV_EXCL_START */
608 ERR("calloc() Fail");
609 sqlite3_finalize(stmt);
614 ad->event_id = sqlite3_column_int(stmt, 0);
615 ad->unit = sqlite3_column_int(stmt, 1);
616 ad->tick = sqlite3_column_int(stmt, 2);
617 ad->type = sqlite3_column_int(stmt, 3);
618 ad->time = (long long int)sqlite3_column_int64(stmt, 4);
619 snprintf(ad->datetime, sizeof(ad->datetime), "%s", (const char *)sqlite3_column_text(stmt, 5));
620 *l = g_list_append(*l, ad);
621 DBG("found id(%d) unit(%d) tick(%d) type(%d) time(%lld) [%s]",
622 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
624 int y = 0, m = 0, d = 0;
625 int h = 0, n = 0, s = 0;
626 sscanf(ad->datetime, CAL_FORMAT_LOCAL_DATETIME, &y, &m, &d, &h, &n, &s);
629 st.tm_year = y - 1900;
635 st.tm_isdst = cal_time_is_dst_savings();
636 ad->alert_utime = (long long int)mktime(&st) - (ad->tick * ad->unit);
637 if (false == get_all) break;
639 sqlite3_finalize(stmt);
642 static void _cal_server_alarm_get_upcoming_nonspecific_todo_utime(time_t utime, bool get_all, GList **l)
649 char query[CAL_DB_SQL_MAX_LEN] = {0};
650 snprintf(query, sizeof(query), "SELECT A.event_id, A.remind_tick_unit, A.remind_tick,"
651 "A.alarm_type, S.dtend_utime, A.alarm_datetime "
652 "FROM "CAL_TABLE_ALARM" as A, "CAL_TABLE_SCHEDULE" as S ON A.event_id = S.id "
653 "WHERE A.remind_tick_unit > %d AND S.type = %d "
654 "AND (S.dtend_utime - (A.remind_tick_unit * A.remind_tick)) %s %ld %s",
655 CALENDAR_ALARM_TIME_UNIT_SPECIFIC, CALENDAR_BOOK_TYPE_TODO,
656 true == get_all ? "=" : ">", utime,
657 true == get_all ? "" : "ORDER BY (S.dtend_utime - (A.remind_tick_unit * A.remind_tick)) LIMIT 1 ");
659 sqlite3_stmt *stmt = NULL;
660 ret = cal_db_util_query_prepare(query, &stmt);
661 if (CALENDAR_ERROR_NONE != ret) {
662 /* LCOV_EXCL_START */
663 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
664 SECURE("query[%s]", query);
669 while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
670 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
672 /* LCOV_EXCL_START */
673 ERR("calloc() Fail");
674 sqlite3_finalize(stmt);
679 ad->event_id = sqlite3_column_int(stmt, 0);
680 ad->unit = sqlite3_column_int(stmt, 1);
681 ad->tick = sqlite3_column_int(stmt, 2);
682 ad->type = sqlite3_column_int(stmt, 3);
683 ad->time = (long long int)sqlite3_column_int64(stmt, 4);
684 snprintf(ad->datetime, sizeof(ad->datetime), "%s", (const char *)sqlite3_column_text(stmt, 5));
685 *l = g_list_append(*l, ad);
686 DBG("found id(%d) unit(%d) tick(%d) type(%d) time(%lld) [%s]",
687 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
689 ad->alert_utime = ad->time - (ad->tick * ad->unit);
690 if (false == get_all) break;
692 sqlite3_finalize(stmt);
695 static void _cal_server_alarm_get_upcoming_nonspecific_todo_localtime(const char *datetime, bool get_all, GList **l)
702 char query[CAL_DB_SQL_MAX_LEN] = {0};
703 snprintf(query, sizeof(query), "SELECT A.event_id,A.remind_tick_unit,A.remind_tick,"
704 "A.alarm_type,A.alarm_utime,B.dtend_datetime "
705 "FROM "CAL_TABLE_ALARM" as A, "CAL_TABLE_SCHEDULE" as B ON A.event_id = B.id "
706 "WHERE A.remind_tick_unit >%d AND B.type =%d "
707 "AND (strftime('%%s', B.dtend_datetime) - (A.remind_tick_unit * A.remind_tick) - strftime('%%s', '%s') %s 0) %s",
708 CALENDAR_ALARM_TIME_UNIT_SPECIFIC, CALENDAR_BOOK_TYPE_TODO,
709 datetime, true == get_all ? "=" : ">",
710 true == get_all ? "" : "ORDER BY (strftime('%s', B.dtend_datetime) - (A.remind_tick_unit * A.remind_tick)) LIMIT 1 ");
712 sqlite3_stmt *stmt = NULL;
713 ret = cal_db_util_query_prepare(query, &stmt);
714 if (CALENDAR_ERROR_NONE != ret) {
715 /* LCOV_EXCL_START */
716 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
717 SECURE("query[%s]", query);
722 while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
723 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
725 /* LCOV_EXCL_START */
726 ERR("calloc() Fail");
727 sqlite3_finalize(stmt);
732 ad->event_id = sqlite3_column_int(stmt, 0);
733 ad->unit = sqlite3_column_int(stmt, 1);
734 ad->tick = sqlite3_column_int(stmt, 2);
735 ad->type = sqlite3_column_int(stmt, 3);
736 ad->time = (long long int)sqlite3_column_int64(stmt, 4);
737 snprintf(ad->datetime, sizeof(ad->datetime), "%s", (const char *)sqlite3_column_text(stmt, 5));
738 *l = g_list_append(*l, ad);
739 DBG("found id(%d) unit(%d) tick(%d) type(%d) time(%lld) [%s]",
740 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
742 int y = 0, m = 0, d = 0;
743 int h = 0, n = 0, s = 0;
744 sscanf(ad->datetime, CAL_FORMAT_LOCAL_DATETIME, &y, &m, &d, &h, &n, &s);
747 st.tm_year = y - 1900;
753 st.tm_isdst = cal_time_is_dst_savings();
754 ad->alert_utime = (long long int)mktime(&st) - (ad->tick * ad->unit);
755 if (false == get_all) break;
757 sqlite3_finalize(stmt);
760 static void _cal_server_alarm_get_latest(time_t utime, bool get_all, GList **out_l)
764 RET_IF(NULL == out_l);
767 struct tm st_local = {0};
768 localtime_r(&utime, &st_local);
770 char datetime[CAL_STR_SHORT_LEN32] = {0};
771 ret = snprintf(datetime, sizeof(datetime), CAL_FORMAT_LOCAL_DATETIME,
772 st_local.tm_year +1900, st_local.tm_mon + 1, st_local.tm_mday,
773 st_local.tm_hour, st_local.tm_min, st_local.tm_sec);
776 WARN("datetime is truncated (%s)",datetime);
779 DBG("get alert to register with given time (%ld) datetime[%s]", utime, datetime);
783 _cal_server_alarm_get_upcoming_specific_utime(utime, get_all, &l);
784 _cal_server_alarm_get_upcoming_nonspecific_event_utime(utime, get_all, &l);
785 _cal_server_alarm_get_upcoming_nonspecific_todo_utime(utime, get_all, &l);
787 _cal_server_alarm_get_upcoming_specific_localtime(datetime, get_all, &l);
788 _cal_server_alarm_get_upcoming_nonspecific_event_localtime(datetime, get_all, &l);
789 _cal_server_alarm_get_upcoming_nonspecific_todo_localtime(datetime, get_all, &l);
794 static gint _cal_server_alarm_sort_cb(gconstpointer a, gconstpointer b)
796 struct _alarm_data_s *p1 = (struct _alarm_data_s *)a;
797 struct _alarm_data_s *p2 = (struct _alarm_data_s *)b;
798 DBG("%lld) > (%lld)", p1->alert_utime, p2->alert_utime);
800 return p1->alert_utime < p2->alert_utime ? -1 : 1;
803 static GFunc _cal_server_alarm_print_cb(gpointer data, gpointer user_data)
805 struct _alarm_data_s *ad = (struct _alarm_data_s *)data;
806 DBG("id(%d) unit(%d) tick(%d) type(%d) time(%lld) datetime[%s]",
807 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
811 static int _cal_server_alarm_register(GList *alarm_list)
814 RETV_IF(NULL == alarm_list, CALENDAR_ERROR_INVALID_PARAMETER);
816 int ret = CALENDAR_ERROR_NONE;
817 GList *l = g_list_first(alarm_list);
818 RETV_IF(NULL == l, CALENDAR_ERROR_INVALID_PARAMETER);
820 struct _alarm_data_s *ad = (struct _alarm_data_s *)l->data;
821 RETVM_IF(NULL == ad, CALENDAR_ERROR_DB_FAILED, "No data");
823 /* clear all alarm which set by mine. */
824 ret = alarmmgr_enum_alarm_ids(_cal_server_alarm_clear_all_cb, NULL);
825 if (ret != ALARMMGR_RESULT_SUCCESS) {
826 /* LCOV_EXCL_START */
827 ERR("alarmmgr_enum_alarm_ids() Fail");
832 time_t mod_time = (time_t)ad->alert_utime;
833 alarm_entry_t *alarm_info = NULL;
834 alarm_info = alarmmgr_create_alarm();
835 if (NULL == alarm_info) {
836 /* LCOV_EXCL_START */
837 ERR("Failed to create alarm");
838 return CALENDAR_ERROR_DB_FAILED;
842 struct tm st_alarm = {0};
844 switch (ad->system_type) {
845 case CALENDAR_SYSTEM_EAST_ASIAN_LUNISOLAR:
846 gmtime_r(&mod_time, &st_alarm);
851 localtime_r(&mod_time, &st_alarm);
855 alarm_date_t date = {0};
856 date.year = st_alarm.tm_year + 1900;
857 date.month = st_alarm.tm_mon + 1;
858 date.day = st_alarm.tm_mday;
859 date.hour = st_alarm.tm_hour;
860 date.min = st_alarm.tm_min;
861 date.sec = st_alarm.tm_sec;
862 alarmmgr_set_time(alarm_info, date);
863 DBG(COLOR_CYAN" >>> registered record id (%d) at %04d/%02d/%02d %02d:%02d:%02d "COLOR_END" (utime(%lld), datetime[%s], tick(%d) unit(%d))",
864 ad->event_id, date.year, date.month, date.day, date.hour, date.min, date.sec,
865 ad->time, ad->datetime, ad->tick, ad->unit);
868 ret = alarmmgr_add_alarm_with_localtime(alarm_info, NULL, &alarm_id);
870 /* LCOV_EXCL_START */
871 ERR("alarmmgr_add_alarm_with_localtime Fail (%d)", ret);
872 alarmmgr_free_alarm(alarm_info);
876 DBG("alarmmgr id (%d)", alarm_id);
877 _cal_server_alarm_update_alarm_id(alarm_id, ad->event_id, ad->tick, ad->unit);
878 alarmmgr_free_alarm(alarm_info);
879 return CALENDAR_ERROR_NONE;
882 static bool __app_matched_cb(app_control_h app_control, const char *package, void *user_data)
889 RETV_IF(NULL == user_data, true);
892 ret = app_control_get_mime(app_control, &mime);
893 RETVM_IF(APP_CONTROL_ERROR_NONE != ret, true, "app_control_get_mime() Fail(%d)", ret);
895 const char *reminder_mime = "application/x-tizen.calendar.reminder";
896 if (strncmp(mime, reminder_mime, strlen(reminder_mime))) { /* not same */
897 DBG("get mime[%s] is not [%s]", mime, reminder_mime);
903 struct alarm_ud *au = (struct alarm_ud *)user_data;
904 GList *alarm_list = au->alarm_list;
905 if (NULL == alarm_list) {
906 /* LCOV_EXCL_START */
912 len = g_list_length(alarm_list);
914 DBG("len is 0, no alarm list");
918 app_control_h ac = NULL;
919 ret = app_control_create(&ac);
920 if (APP_CONTROL_ERROR_NONE != ret) {
921 /* LCOV_EXCL_START */
922 ERR("app_control_create() Fail(%d)", ret);
926 ret = app_control_set_operation(ac, APP_CONTROL_OPERATION_DEFAULT);
927 if (APP_CONTROL_ERROR_NONE != ret) {
928 /* LCOV_EXCL_START */
929 ERR("app_control_create() Fail(%d)", ret);
930 app_control_destroy(ac);
934 ret = app_control_set_app_id(ac, package);
935 if (APP_CONTROL_ERROR_NONE != ret) {
936 /* LCOV_EXCL_START */
937 ERR("app_control_set_app_id() Fail(%d)", ret);
938 app_control_destroy(ac);
944 ids = calloc(len, sizeof(char *));
946 /* LCOV_EXCL_START */
947 ERR("calloc() Fail");
948 app_control_destroy(ac);
952 GList *cursor = g_list_first(alarm_list);
953 for (i = 0; i < len; i++) {
954 if (NULL == cursor) {
955 ERR("cursor is NULL");
958 struct _alarm_data_s *ad = (struct _alarm_data_s *)cursor->data;
961 cursor = g_list_next(cursor);
964 DBG("pkg[%s] time[%lld] tick[%d] unit[%d] record_type[%d]",
965 package, ad->time, ad->tick, ad->unit, ad->record);
968 char extra[CAL_STR_MIDDLE_LEN] = {0};
969 slen = snprintf(extra, sizeof(extra), "%s=%d", "id", ad->event_id);
970 slen += snprintf(extra+slen, sizeof(extra)-slen, "&%s=%lld", "time", ad->time);
971 slen += snprintf(extra+slen, sizeof(extra)-slen, "&%s=%d", "tick", ad->tick);
972 slen += snprintf(extra+slen, sizeof(extra)-slen, "&%s=%d", "unit", ad->unit);
973 slen += snprintf(extra+slen, sizeof(extra)-slen, "&%s=%d", "type", ad->record);
976 * key: id, value: id=4&time=123123&..
978 char buf_id[CAL_STR_MIDDLE_LEN] = {0};
979 snprintf(buf_id, sizeof(buf_id), "%d", ad->event_id);
980 app_control_add_extra_data(ac, buf_id, extra);
981 DBG("value[%s] id[%s]", extra, buf_id);
984 ids[i] = strdup(buf_id);
986 cursor = g_list_next(cursor);
988 app_control_add_extra_data_array(ac, "ids", (const char **)ids, len);
989 app_control_send_launch_request(ac, NULL, NULL);
990 app_control_destroy(ac);
992 for (i = 0; i < len; i++) {
1001 static void _cal_server_alarm_noti_with_control(GList *alarm_list)
1006 RETM_IF(NULL == alarm_list, "No alarm list");
1008 app_control_h app_control = NULL;
1009 ret = app_control_create(&app_control);
1010 if (APP_CONTROL_ERROR_NONE != ret) {
1011 /* LCOV_EXCL_START */
1012 ERR("app_control_create() Fail(%d)", ret);
1014 /* LCOV_EXCL_STOP */
1016 ret = app_control_set_operation(app_control, APP_CONTROL_OPERATION_VIEW);
1017 if (APP_CONTROL_ERROR_NONE != ret) {
1018 /* LCOV_EXCL_START */
1019 ERR("app_control_set_operation() Fail(%d)", ret);
1020 app_control_destroy(app_control);
1022 /* LCOV_EXCL_STOP */
1024 ret = app_control_set_mime(app_control, "application/x-tizen.calendar.reminder");
1025 if (APP_CONTROL_ERROR_NONE != ret) {
1026 /* LCOV_EXCL_START */
1027 ERR("app_control_set_mime() Fail(%d)", ret);
1028 app_control_destroy(app_control);
1030 /* LCOV_EXCL_STOP */
1033 struct alarm_ud *au = calloc(1, sizeof(struct alarm_ud));
1035 /* LCOV_EXCL_START */
1036 ERR("calloc() Fail");
1037 app_control_destroy(app_control);
1039 /* LCOV_EXCL_STOP */
1041 au->alarm_list = alarm_list;
1042 ret = app_control_foreach_app_matched(app_control, __app_matched_cb, au);
1043 if (APP_CONTROL_ERROR_NONE != ret) {
1044 /* LCOV_EXCL_START */
1045 ERR("app_control_foreach_app_matched() Fail(%d)", ret);
1047 app_control_destroy(app_control);
1049 /* LCOV_EXCL_STOP */
1052 app_control_destroy(app_control);
1055 static void _cal_server_alarm_noti_with_callback(GList *alarm_list)
1057 RETM_IF(NULL == alarm_list, "No alarm list");
1059 GList *l = g_list_first(alarm_list);
1061 struct _alarm_data_s *ad = (struct _alarm_data_s *)l->data;
1067 DBG("callback time[%lld] tick[%d] unit[%d] record_type[%d]",
1068 ad->time, ad->tick, ad->unit, ad->record);
1071 char extra[CAL_STR_MIDDLE_LEN] = {0};
1072 len = snprintf(extra, sizeof(extra), "%s=%d", "id", ad->event_id);
1073 len += snprintf(extra+len, sizeof(extra)-len, "&%s=%lld", "time", ad->time);
1074 len += snprintf(extra+len, sizeof(extra)-len, "&%s=%d", "tick", ad->tick);
1075 len += snprintf(extra+len, sizeof(extra)-len, "&%s=%d", "unit", ad->unit);
1076 len += snprintf(extra+len, sizeof(extra)-len, "&%s=%d", "type", ad->record);
1077 cal_dbus_publish_reminder(len, extra);
1083 static void cal_server_alarm_register_next_alarm(time_t utime)
1088 _cal_server_alarm_get_latest(utime, false, &l);
1092 l = g_list_sort(l, _cal_server_alarm_sort_cb);
1093 g_list_foreach(l, (GFunc)_cal_server_alarm_print_cb, NULL);
1094 _cal_server_alarm_register(l);
1096 g_list_free_full(l, free);
1099 static void cal_server_alarm_alert(time_t tt_alert)
1102 _cal_server_alarm_get_latest(tt_alert, true, &l);
1106 _cal_server_alarm_noti_with_callback(l);
1107 _cal_server_alarm_noti_with_control(l);
1108 g_list_free_full(l, free);
1111 static int _alert_cb(alarm_id_t alarm_id, void *data)
1114 DBG("alarm_id (%d)", (int)alarm_id);
1116 time_t tt_alert = 0;
1117 cal_server_alarm_get_alert_time(alarm_id, &tt_alert);
1118 cal_server_alarm_alert(tt_alert);
1119 cal_server_alarm_unset_alerted_alarmmgr_id(alarm_id);
1120 cal_server_alarm_start();
1124 static void _timechanged_cb(keynode_t *node, void *data)
1126 cal_server_alarm_alert(time(NULL));
1127 cal_server_alarm_start();
1130 static void _cal_server_alarm_set_timechange(void)
1132 vconf_notify_key_changed(VCONFKEY_SYSTEM_TIME_CHANGED, _timechanged_cb, NULL);
1133 vconf_notify_key_changed(VCONFKEY_TELEPHONY_NITZ_GMT, _timechanged_cb, NULL);
1134 vconf_notify_key_changed(VCONFKEY_TELEPHONY_NITZ_ZONE, _timechanged_cb, NULL);
1135 vconf_notify_key_changed(VCONFKEY_TELEPHONY_NITZ_EVENT_GMT, _timechanged_cb, NULL);
1138 static void _cal_server_alarm_unset_timechange(void)
1140 vconf_ignore_key_changed(VCONFKEY_SYSTEM_TIME_CHANGED, _timechanged_cb);
1141 vconf_ignore_key_changed(VCONFKEY_TELEPHONY_NITZ_GMT, _timechanged_cb);
1142 vconf_ignore_key_changed(VCONFKEY_TELEPHONY_NITZ_ZONE, _timechanged_cb);
1143 vconf_ignore_key_changed(VCONFKEY_TELEPHONY_NITZ_EVENT_GMT, _timechanged_cb);
1146 static void _changed_cb(const char* view_uri, void* data)
1148 DBG("Receive alarm change signal");
1149 cal_server_alarm_start();
1152 static int _cal_server_alarm_set_inotify(calendar_db_changed_cb callback)
1154 cal_inotify_subscribe(CAL_NOTI_TYPE_EVENT, CAL_NOTI_FILE_EVENT, callback, NULL);
1155 cal_inotify_subscribe(CAL_NOTI_TYPE_TODO, CAL_NOTI_FILE_TODO, callback, NULL);
1159 static void _cal_server_alarm_unset_inotify(calendar_db_changed_cb callback)
1161 cal_inotify_unsubscribe(CAL_NOTI_FILE_EVENT, callback, NULL);
1162 cal_inotify_unsubscribe(CAL_NOTI_FILE_TODO, callback, NULL);
1165 static int cal_server_alarm_init(void)
1169 _cal_server_alarm_set_timechange();
1170 _cal_server_alarm_set_inotify(_changed_cb);
1172 ret = alarmmgr_set_cb(_alert_cb, NULL);
1174 /* LCOV_EXCL_START */
1175 ERR("alarmmgr_set_cb() Fail(%d)", ret);
1176 return CALENDAR_ERROR_SYSTEM;
1177 /* LCOV_EXCL_STOP */
1180 ret = alarmmgr_init("calendar-service");
1182 /* LCOV_EXCL_START */
1183 ERR("alarmmgr_init() Fail(%d)", ret);
1184 return CALENDAR_ERROR_SYSTEM;
1185 /* LCOV_EXCL_STOP */
1188 return CALENDAR_ERROR_NONE;
1191 static gpointer _cal_server_alarm_main(gpointer user_data)
1193 DBG("thread alarm: start");
1196 bool is_initialized = false;
1199 g_mutex_lock(&_cal_server_alarm_mutex);
1201 * While syncing with contacts,
1202 * because calendar-service could be stopped by on-demand,
1203 * holding on-demand is needed.
1205 cal_server_ondemand_hold();
1208 if (false == is_initialized) {
1209 ret = cal_server_alarm_init();
1210 if (CALENDAR_ERROR_NONE != ret) {
1211 /* LCOV_EXCL_START */
1212 ERR("cal_server_alarm_init() Fail(%d)", ret);
1214 /* LCOV_EXCL_STOP */
1216 DBG("thread alarm: init");
1217 is_initialized = true;
1220 ret = cal_connect();
1221 if (CALENDAR_ERROR_NONE != ret) {
1222 /* LCOV_EXCL_START */
1223 ERR("cal_connect() Fail(%d)", ret);
1225 /* LCOV_EXCL_STOP */
1228 cal_server_alarm_register_next_alarm(time(NULL));
1233 cal_server_ondemand_release();
1234 cal_server_ondemand_start();
1236 DBG("thread alarm: wait");
1237 while (false == signal_called)
1238 g_cond_wait(&_cal_server_alarm_cond, &_cal_server_alarm_mutex);
1239 signal_called = false;
1240 g_mutex_unlock(&_cal_server_alarm_mutex);
1245 DBG("thread alarm: end");
1246 g_thread_exit(NULL);
1251 void cal_server_alarm_send_signal(void)
1253 g_mutex_lock(&_cal_server_alarm_mutex);
1254 signal_called = true;
1255 g_cond_signal(&_cal_server_alarm_cond);
1256 g_mutex_unlock(&_cal_server_alarm_mutex);
1259 void cal_server_alarm_start(void)
1263 if (NULL == _cal_server_alarm_thread) {
1264 g_mutex_init(&_cal_server_alarm_mutex);
1265 g_cond_init(&_cal_server_alarm_cond);
1266 _cal_server_alarm_thread = g_thread_new(CAL_SERVER_ALARM_THREAD_NAME,
1267 _cal_server_alarm_main, NULL);
1269 cal_server_alarm_send_signal();
1272 static void cal_server_alarm_deinit(void)
1275 _cal_server_alarm_unset_inotify(_changed_cb);
1276 _cal_server_alarm_unset_timechange();
1279 void cal_server_alarm_end(void)
1283 server_killed = true;
1285 cal_server_alarm_deinit();
1286 cal_server_alarm_send_signal();
1288 g_cond_clear(&_cal_server_alarm_cond);
1289 g_thread_join(_cal_server_alarm_thread);
1290 g_thread_unref(_cal_server_alarm_thread);
1291 _cal_server_alarm_thread = NULL;