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 time_t _make_time(struct tm *time)
143 time_t utc = mktime(time);
145 /* If an error occurs when isdst is 1, retry it after chaning isdst is 0 */
146 if (utc < 0 && time->tm_isdst != 0 ) {
153 static long long int _get_event_alert_utime(const char *field, int event_id, time_t current)
156 char query[CAL_DB_SQL_MAX_LEN] = {0};
157 snprintf(query, sizeof(query), "SELECT %s FROM %s "
158 "WHERE event_id=%d AND %s>%ld ORDER BY %s LIMIT 1",
159 field, CAL_TABLE_UTIME_INSTANCE, event_id, field, current, field);
161 sqlite3_stmt *stmt = NULL;
162 ret = cal_db_util_query_prepare(query, &stmt);
163 if (CALENDAR_ERROR_NONE != ret) {
164 /* LCOV_EXCL_START */
165 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
166 SECURE("query[%s]", query);
171 long long int utime = 0;
172 if (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt))
173 utime = sqlite3_column_int(stmt, 0);
175 sqlite3_finalize(stmt);
179 static int _get_event_alert_localtime(const char *field, int event_id, time_t current)
182 char query[CAL_DB_SQL_MAX_LEN] = {0};
184 struct tm now_s = {0};
187 localtime_r(¤t, &now_s);
188 snprintf(buf, sizeof(buf), "%04d-%02d-%02dT%02d:%02d:%02d", (int)(now_s.tm_year + 1900),
189 (int)(now_s.tm_mon + 1), (int)now_s.tm_mday, (int)now_s.tm_hour,
190 (int)now_s.tm_min, (int)now_s.tm_sec);
191 DBG("Current time : (%s)", buf);
193 snprintf(query, sizeof(query), "SELECT %s FROM %s "
194 "WHERE event_id=%d AND (strftime('%%s', %s) - strftime('%%s', '%s') > 0) ORDER BY %s LIMIT 1",
195 field, CAL_TABLE_LOCALTIME_INSTANCE, event_id, field, buf, field);
197 sqlite3_stmt *stmt = NULL;
198 ret = cal_db_util_query_prepare(query, &stmt);
199 if (CALENDAR_ERROR_NONE != ret) {
200 /* LCOV_EXCL_START */
201 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
202 SECURE("query[%s]", query);
207 const char *datetime = NULL;
208 if (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt))
209 datetime = (const char *)sqlite3_column_text(stmt, 0);
212 if (NULL == datetime || '\0' == *datetime) {
213 /* LCOV_EXCL_START */
214 ERR("Invalid datetime [%s]", datetime);
215 sqlite3_finalize(stmt);
220 int y = 0, m = 0, d = 0;
221 int h = 0, n = 0, s = 0;
222 sscanf(datetime, CAL_FORMAT_LOCAL_DATETIME, &y, &m, &d, &h, &n, &s);
223 sqlite3_finalize(stmt);
225 st.tm_year = y - 1900;
231 st.tm_isdst = cal_time_is_dst_savings();
233 return (long long int)_make_time(&st);
236 static int64_t _get_todo_alert_utime(const char *field, int id, time_t now_t)
239 char query[CAL_DB_SQL_MAX_LEN] = {0};
240 snprintf(query, sizeof(query), "SELECT %s FROM "CAL_TABLE_SCHEDULE" "
241 "WHERE id=%d AND %s>%ld ORDER BY %s LIMIT 1", field, id, field, now_t, field);
243 sqlite3_stmt *stmt = NULL;
244 ret = cal_db_util_query_prepare(query, &stmt);
245 if (CALENDAR_ERROR_NONE != ret) {
246 /* LCOV_EXCL_START */
247 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
248 SECURE("query[%s]", query);
254 ret = cal_db_util_stmt_step(stmt);
257 utime = (int64_t)sqlite3_column_int64(stmt, 0);
262 break;*/ //Svace:371986
264 ERR("Invalid return(%d)", ret);
269 sqlite3_finalize(stmt);
273 static int _get_todo_alert_localtime(const char *field, int event_id, time_t current)
276 char query[CAL_DB_SQL_MAX_LEN] = {0};
278 struct tm now_s = {0};
281 localtime_r(¤t, &now_s);
282 snprintf(buf, sizeof(buf), "%04d-%02d-%02dT%02d:%02d:%02d", (int)(now_s.tm_year + 1900),
283 (int)(now_s.tm_mon + 1), (int)now_s.tm_mday, (int)now_s.tm_hour,
284 (int)now_s.tm_min, (int)now_s.tm_sec);
285 DBG("Current time : (%s)", buf);
287 snprintf(query, sizeof(query), "SELECT %s FROM %s "
288 "WHERE id=%d AND (strftime('%%s', %s) - strftime('%%s', '%s') > 0) ORDER BY %s LIMIT 1",
289 field, CAL_TABLE_SCHEDULE, event_id, field, buf, field);
291 sqlite3_stmt *stmt = NULL;
292 ret = cal_db_util_query_prepare(query, &stmt);
293 if (CALENDAR_ERROR_NONE != ret) {
294 /* LCOV_EXCL_START */
295 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
296 SECURE("query[%s]", query);
301 const char *datetime = NULL;
302 if (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt))
303 datetime = (const char *)sqlite3_column_text(stmt, 0);
305 if (NULL == datetime || '\0' == *datetime) {
306 /* LCOV_EXCL_START */
307 ERR("Invalid datetime [%s]", datetime);
308 sqlite3_finalize(stmt);
313 int y = 0, m = 0, d = 0;
314 int h = 0, n = 0, s = 0;
315 sscanf(datetime, CAL_FORMAT_LOCAL_DATETIME, &y, &m, &d, &h, &n, &s);
316 sqlite3_finalize(stmt);
318 st.tm_year = y - 1900;
324 st.tm_isdst = cal_time_is_dst_savings();
326 return (long long int)_make_time(&st);
329 * time(NULL) is not appropriate as parameter.
330 * 1 seconds could be flowed before calling function.(1 sec time diff)
331 * so, searching DB is neccessary to find alert time.
333 static int cal_server_alarm_get_alert_time(int alarm_id, time_t *tt_alert)
336 RETV_IF(NULL == tt_alert, CALENDAR_ERROR_INVALID_PARAMETER);
338 char query[CAL_DB_SQL_MAX_LEN] = {0};
339 snprintf(query, sizeof(query), "SELECT A.event_id, A.remind_tick_unit, A.remind_tick, "
340 "A.alarm_type, A.alarm_utime, A.alarm_datetime, B.type, B.dtstart_type, "
341 "B.dtend_type FROM %s as A, %s as B ON A.event_id =B.id WHERE alarm_id =%d ",
342 CAL_TABLE_ALARM, CAL_TABLE_SCHEDULE, alarm_id);
344 sqlite3_stmt *stmt = NULL;
345 ret = cal_db_util_query_prepare(query, &stmt);
346 if (CALENDAR_ERROR_NONE != ret) {
347 /* LCOV_EXCL_START */
348 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
349 SECURE("query[%s]", query);
358 long long int utime = 0;
359 const char *datetime = NULL;
361 int dtstart_type = 0;
365 if (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
366 event_id = sqlite3_column_int(stmt, 0);
367 unit = sqlite3_column_int(stmt, 1);
368 tick = sqlite3_column_int(stmt, 2);
369 type = sqlite3_column_int(stmt, 3);
370 utime = sqlite3_column_int64(stmt, 4);
371 datetime = (const char *)sqlite3_column_text(stmt, 5);
372 record_type = sqlite3_column_int(stmt, 6);
373 dtstart_type = sqlite3_column_int(stmt, 7);
374 dtend_type = sqlite3_column_int(stmt, 8);
377 if (CALENDAR_ALARM_TIME_UNIT_SPECIFIC == unit) {
378 if (CALENDAR_TIME_UTIME == type) {
381 int y = 0, m = 0, d = 0;
382 int h = 0, n = 0, s = 0;
384 sscanf(datetime, CAL_FORMAT_LOCAL_DATETIME, &y, &m, &d, &h, &n, &s);
386 st.tm_year = y - 1900;
392 st.tm_isdst = cal_time_is_dst_savings();
393 *tt_alert = _make_time(&st);
394 DBG("datetime[%s] to %02d:%02d:%02d (%ld)", datetime, h, n, s, *tt_alert);
397 sqlite3_finalize(stmt);
398 return CALENDAR_ERROR_NONE;
400 sqlite3_finalize(stmt);
402 time_t current = time(NULL);
404 current += (tick * unit);
405 current -= 2; /* in case time passed */
407 switch (record_type) {
408 case CALENDAR_BOOK_TYPE_EVENT:
409 switch (dtstart_type) {
410 case CALENDAR_TIME_UTIME:
411 utime = _get_event_alert_utime("dtstart_utime", event_id, current);
414 case CALENDAR_TIME_LOCALTIME:
415 utime = _get_event_alert_localtime("dtstart_datetime", event_id, current);
420 case CALENDAR_BOOK_TYPE_TODO:
421 switch (dtend_type) {
422 case CALENDAR_TIME_UTIME:
423 utime = _get_todo_alert_utime("dtend_utime", event_id, current);
426 case CALENDAR_TIME_LOCALTIME:
427 utime = _get_todo_alert_localtime("dtend_datetime", event_id, current);
432 *tt_alert = utime - (tick * unit);
434 DBG("alert_time(%ld) = utime(%lld) - (tick(%d) * unit(%d))", *tt_alert, utime, tick, unit);
436 return CALENDAR_ERROR_NONE;
441 * true : to get all alarms including same time event.
442 * (ig. if 3 diffrent alarms exist at 06:30, list has 3 data)
443 * false : to get only one alarm to register in alarm-manager.
444 * (ig. if 3 diffrent alarms exist at 06:30, list has only one)
446 static void _cal_server_alarm_get_upcoming_specific_utime(time_t utime, bool get_all, GList **l)
450 char query[CAL_DB_SQL_MAX_LEN] = {0};
451 snprintf(query, sizeof(query), "SELECT A.event_id, A.remind_tick_unit, A.remind_tick,"
452 "A.alarm_type, A.alarm_utime, A.alarm_datetime "
453 "FROM "CAL_TABLE_ALARM" as A, "CAL_TABLE_SCHEDULE" as S ON A.event_id = S.id "
454 "WHERE S.link_base_id = 0 AND A.remind_tick_unit = %d AND A.alarm_type = %d "
455 "AND A.alarm_utime %s %ld %s",
456 CALENDAR_ALARM_TIME_UNIT_SPECIFIC, CALENDAR_TIME_UTIME,
457 true == get_all ? "=" : ">", utime,
458 true == get_all ? "" : "ORDER BY alarm_utime ASC LIMIT 1");
460 sqlite3_stmt *stmt = NULL;
461 ret = cal_db_util_query_prepare(query, &stmt);
462 if (CALENDAR_ERROR_NONE != ret) {
463 /* LCOV_EXCL_START */
464 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
465 SECURE("query[%s]", query);
470 while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
471 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
473 /* LCOV_EXCL_START */
474 ERR("calloc() Fail");
475 sqlite3_finalize(stmt);
480 ad->event_id = sqlite3_column_int(stmt, 0);
481 ad->unit = sqlite3_column_int(stmt, 1);
482 ad->tick = sqlite3_column_int(stmt, 2);
483 ad->type = sqlite3_column_int(stmt, 3);
484 ad->time = (long long int)sqlite3_column_int64(stmt, 4);
485 snprintf(ad->datetime, sizeof(ad->datetime), "%s", (const char *)sqlite3_column_text(stmt, 5));
486 *l = g_list_append(*l, ad);
487 ERR("found id(%d) unit(%d) tick(%d) type(%d) time(%lld) [%s]",
488 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
489 ad->alert_utime = ad->time;
490 if (false == get_all) break;
492 sqlite3_finalize(stmt);
495 static void _cal_server_alarm_get_upcoming_specific_localtime(const char *datetime, bool get_all, GList **l)
499 char query[CAL_DB_SQL_MAX_LEN] = {0};
500 snprintf(query, sizeof(query), "SELECT A.event_id, A.remind_tick_unit, A.remind_tick,"
501 "A.alarm_type, A.alarm_utime, A.alarm_datetime "
502 "FROM "CAL_TABLE_ALARM" as A, "CAL_TABLE_SCHEDULE" as S ON A.event_id = S.id "
503 "WHERE S.link_base_id = 0 AND A.remind_tick_unit = %d AND A.alarm_type = %d "
504 "AND A.alarm_datetime %s '%s' %s",
505 CALENDAR_ALARM_TIME_UNIT_SPECIFIC, CALENDAR_TIME_LOCALTIME,
506 true == get_all ? "=" : ">", datetime,
507 true == get_all ? "" : "ORDER BY alarm_datetime ASC LIMIT 1");
509 sqlite3_stmt *stmt = NULL;
510 ret = cal_db_util_query_prepare(query, &stmt);
511 if (CALENDAR_ERROR_NONE != ret) {
512 /* LCOV_EXCL_START */
513 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
514 SECURE("query[%s]", query);
519 while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
520 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
522 /* LCOV_EXCL_START */
523 ERR("calloc() Fail");
524 sqlite3_finalize(stmt);
529 ad->event_id = sqlite3_column_int(stmt, 0);
530 ad->unit = sqlite3_column_int(stmt, 1);
531 ad->tick = sqlite3_column_int(stmt, 2);
532 ad->type = sqlite3_column_int(stmt, 3);
533 ad->time = (long long int)sqlite3_column_int64(stmt, 4);
534 snprintf(ad->datetime, sizeof(ad->datetime), "%s", (const char *)sqlite3_column_text(stmt, 5));
535 *l = g_list_append(*l, ad);
536 ERR("found id(%d) unit(%d) tick(%d) type(%d) time(%lld) [%s]",
537 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
539 int y = 0, m = 0, d = 0;
540 int h = 0, n = 0, s = 0;
541 sscanf(ad->datetime, CAL_FORMAT_LOCAL_DATETIME, &y, &m, &d, &h, &n, &s);
544 st.tm_year = y - 1900;
550 st.tm_isdst = cal_time_is_dst_savings();
551 ad->alert_utime = (long long int)_make_time(&st);
552 if (false == get_all) break;
554 sqlite3_finalize(stmt);
557 static void _cal_server_alarm_get_upcoming_nonspecific_event_utime(time_t utime, bool get_all, GList **l)
565 char query[CAL_DB_SQL_MAX_LEN] = {0};
566 snprintf(query, sizeof(query), "SELECT A.event_id,A.remind_tick_unit,A.remind_tick, "
567 "A.alarm_type,B.dtstart_utime,A.alarm_datetime "
568 "FROM "CAL_TABLE_ALARM" as A, "CAL_TABLE_UTIME_INSTANCE" as B, "CAL_TABLE_SCHEDULE" as S "
569 "ON A.event_id = B.event_id AND B.event_id = S.id "
570 "WHERE S.link_base_id = 0 AND A.remind_tick_unit > %d "
571 "AND (B.dtstart_utime - (A.remind_tick_unit * A.remind_tick)) %s %ld %s",
572 CALENDAR_ALARM_TIME_UNIT_SPECIFIC,
573 true == get_all ? "=" : ">", utime,
574 true == get_all ? "" : "ORDER BY (B.dtstart_utime - (A.remind_tick_unit * A.remind_tick)) LIMIT 1");
576 sqlite3_stmt *stmt = NULL;
577 ret = cal_db_util_query_prepare(query, &stmt);
578 if (CALENDAR_ERROR_NONE != ret) {
579 /* LCOV_EXCL_START */
580 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
581 SECURE("query[%s]", query);
586 while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
587 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
589 /* LCOV_EXCL_START */
590 ERR("calloc() Fail");
591 sqlite3_finalize(stmt);
596 ad->event_id = sqlite3_column_int(stmt, 0);
597 ad->unit = sqlite3_column_int(stmt, 1);
598 ad->tick = sqlite3_column_int(stmt, 2);
599 ad->type = sqlite3_column_int(stmt, 3);
600 ad->time = (long long int)sqlite3_column_int64(stmt, 4);
601 snprintf(ad->datetime, sizeof(ad->datetime), "%s", (const char *)sqlite3_column_text(stmt, 5));
602 *l = g_list_append(*l, ad);
603 ERR("found id(%d) unit(%d) tick(%d) type(%d) time(%lld) [%s]",
604 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
606 ad->alert_utime = ad->time - (ad->tick * ad->unit);
607 if (false == get_all) break;
609 sqlite3_finalize(stmt);
612 static void _cal_server_alarm_get_upcoming_nonspecific_event_localtime(const char *datetime, bool get_all, GList **l)
620 char query[CAL_DB_SQL_MAX_LEN] = {0};
621 snprintf(query, sizeof(query), "SELECT A.event_id, A.remind_tick_unit, A.remind_tick, "
622 "A.alarm_type, A.alarm_utime, B.dtstart_datetime "
623 "FROM "CAL_TABLE_ALARM" as A, "CAL_TABLE_LOCALTIME_INSTANCE" as B, "CAL_TABLE_SCHEDULE" as S "
624 "ON A.event_id = B.event_id AND B.event_id = S.id "
625 "WHERE S.link_base_id = 0 AND A.remind_tick_unit >%d AND "
626 "(strftime('%%s', B.dtstart_datetime) - (A.remind_tick_unit * A.remind_tick) - strftime('%%s', '%s') %s 0) %s",
627 CALENDAR_ALARM_TIME_UNIT_SPECIFIC,
628 datetime, true == get_all ? "=" : ">",
629 true == get_all ? "" : "ORDER BY (strftime('%s', B.dtstart_datetime) - (A.remind_tick_unit * A.remind_tick)) LIMIT 1 ");
630 sqlite3_stmt *stmt = NULL;
631 ret = cal_db_util_query_prepare(query, &stmt);
632 if (CALENDAR_ERROR_NONE != ret) {
633 /* LCOV_EXCL_START */
634 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
635 SECURE("query[%s]", query);
640 while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
641 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
643 /* LCOV_EXCL_START */
644 ERR("calloc() Fail");
645 sqlite3_finalize(stmt);
650 ad->event_id = sqlite3_column_int(stmt, 0);
651 ad->unit = sqlite3_column_int(stmt, 1);
652 ad->tick = sqlite3_column_int(stmt, 2);
653 ad->type = sqlite3_column_int(stmt, 3);
654 ad->time = (long long int)sqlite3_column_int64(stmt, 4);
655 snprintf(ad->datetime, sizeof(ad->datetime), "%s", (const char *)sqlite3_column_text(stmt, 5));
656 *l = g_list_append(*l, ad);
657 ERR("found id(%d) unit(%d) tick(%d) type(%d) time(%lld) [%s]",
658 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
660 int y = 0, m = 0, d = 0;
661 int h = 0, n = 0, s = 0;
662 sscanf(ad->datetime, CAL_FORMAT_LOCAL_DATETIME, &y, &m, &d, &h, &n, &s);
665 st.tm_year = y - 1900;
671 st.tm_isdst = cal_time_is_dst_savings();
672 ad->alert_utime = (long long int)_make_time(&st) - (ad->tick * ad->unit);
673 if (false == get_all) break;
675 sqlite3_finalize(stmt);
678 static void _cal_server_alarm_get_upcoming_nonspecific_todo_utime(time_t utime, bool get_all, GList **l)
686 char query[CAL_DB_SQL_MAX_LEN] = {0};
687 snprintf(query, sizeof(query), "SELECT A.event_id, A.remind_tick_unit, A.remind_tick,"
688 "A.alarm_type, S.dtend_utime, A.alarm_datetime "
689 "FROM "CAL_TABLE_ALARM" as A, "CAL_TABLE_SCHEDULE" as S ON A.event_id = S.id "
690 "WHERE A.remind_tick_unit > %d AND S.type = %d "
691 "AND (S.dtend_utime - (A.remind_tick_unit * A.remind_tick)) %s %ld %s",
692 CALENDAR_ALARM_TIME_UNIT_SPECIFIC, CALENDAR_BOOK_TYPE_TODO,
693 true == get_all ? "=" : ">", utime,
694 true == get_all ? "" : "ORDER BY (S.dtend_utime - (A.remind_tick_unit * A.remind_tick)) LIMIT 1 ");
696 sqlite3_stmt *stmt = NULL;
697 ret = cal_db_util_query_prepare(query, &stmt);
698 if (CALENDAR_ERROR_NONE != ret) {
699 /* LCOV_EXCL_START */
700 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
701 SECURE("query[%s]", query);
706 while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
707 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
709 /* LCOV_EXCL_START */
710 ERR("calloc() Fail");
711 sqlite3_finalize(stmt);
716 ad->event_id = sqlite3_column_int(stmt, 0);
717 ad->unit = sqlite3_column_int(stmt, 1);
718 ad->tick = sqlite3_column_int(stmt, 2);
719 ad->type = sqlite3_column_int(stmt, 3);
720 ad->time = (long long int)sqlite3_column_int64(stmt, 4);
721 snprintf(ad->datetime, sizeof(ad->datetime), "%s", (const char *)sqlite3_column_text(stmt, 5));
722 *l = g_list_append(*l, ad);
723 ERR("found id(%d) unit(%d) tick(%d) type(%d) time(%lld) [%s]",
724 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
726 ad->alert_utime = ad->time - (ad->tick * ad->unit);
727 if (false == get_all) break;
729 sqlite3_finalize(stmt);
732 static void _cal_server_alarm_get_upcoming_nonspecific_todo_localtime(const char *datetime, bool get_all, GList **l)
740 char query[CAL_DB_SQL_MAX_LEN] = {0};
741 snprintf(query, sizeof(query), "SELECT A.event_id,A.remind_tick_unit,A.remind_tick,"
742 "A.alarm_type,A.alarm_utime,B.dtend_datetime "
743 "FROM "CAL_TABLE_ALARM" as A, "CAL_TABLE_SCHEDULE" as B ON A.event_id = B.id "
744 "WHERE A.remind_tick_unit >%d AND B.type =%d "
745 "AND (strftime('%%s', B.dtend_datetime) - (A.remind_tick_unit * A.remind_tick) - strftime('%%s', '%s') %s 0) %s",
746 CALENDAR_ALARM_TIME_UNIT_SPECIFIC, CALENDAR_BOOK_TYPE_TODO,
747 datetime, true == get_all ? "=" : ">",
748 true == get_all ? "" : "ORDER BY (strftime('%s', B.dtend_datetime) - (A.remind_tick_unit * A.remind_tick)) LIMIT 1 ");
750 sqlite3_stmt *stmt = NULL;
751 ret = cal_db_util_query_prepare(query, &stmt);
752 if (CALENDAR_ERROR_NONE != ret) {
753 /* LCOV_EXCL_START */
754 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
755 SECURE("query[%s]", query);
760 while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
761 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
763 /* LCOV_EXCL_START */
764 ERR("calloc() Fail");
765 sqlite3_finalize(stmt);
770 ad->event_id = sqlite3_column_int(stmt, 0);
771 ad->unit = sqlite3_column_int(stmt, 1);
772 ad->tick = sqlite3_column_int(stmt, 2);
773 ad->type = sqlite3_column_int(stmt, 3);
774 ad->time = (long long int)sqlite3_column_int64(stmt, 4);
775 snprintf(ad->datetime, sizeof(ad->datetime), "%s", (const char *)sqlite3_column_text(stmt, 5));
776 *l = g_list_append(*l, ad);
777 ERR("found id(%d) unit(%d) tick(%d) type(%d) time(%lld) [%s]",
778 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
780 int y = 0, m = 0, d = 0;
781 int h = 0, n = 0, s = 0;
782 sscanf(ad->datetime, CAL_FORMAT_LOCAL_DATETIME, &y, &m, &d, &h, &n, &s);
785 st.tm_year = y - 1900;
791 st.tm_isdst = cal_time_is_dst_savings();
792 ad->alert_utime = (long long int)_make_time(&st) - (ad->tick * ad->unit);
793 if (false == get_all) break;
795 sqlite3_finalize(stmt);
798 static void _cal_server_alarm_get_latest(time_t utime, bool get_all, GList **out_l)
802 RET_IF(NULL == out_l);
805 struct tm st_local = {0};
806 localtime_r(&utime, &st_local);
808 char datetime[CAL_STR_SHORT_LEN32] = {0};
809 ret = snprintf(datetime, sizeof(datetime), CAL_FORMAT_LOCAL_DATETIME,
810 st_local.tm_year +1900, st_local.tm_mon + 1, st_local.tm_mday,
811 st_local.tm_hour, st_local.tm_min, st_local.tm_sec);
814 WARN("datetime is truncated (%s)",datetime);
817 ERR("get alert to register with given time (%ld) datetime[%s]", utime, datetime); //Temporarily changed to ERR
821 _cal_server_alarm_get_upcoming_specific_utime(utime, get_all, &l);
822 _cal_server_alarm_get_upcoming_nonspecific_event_utime(utime, get_all, &l);
823 _cal_server_alarm_get_upcoming_nonspecific_todo_utime(utime, get_all, &l);
825 _cal_server_alarm_get_upcoming_specific_localtime(datetime, get_all, &l);
826 _cal_server_alarm_get_upcoming_nonspecific_event_localtime(datetime, get_all, &l);
827 _cal_server_alarm_get_upcoming_nonspecific_todo_localtime(datetime, get_all, &l);
832 static gint _cal_server_alarm_sort_cb(gconstpointer a, gconstpointer b)
834 struct _alarm_data_s *p1 = (struct _alarm_data_s *)a;
835 struct _alarm_data_s *p2 = (struct _alarm_data_s *)b;
836 DBG("%lld) > (%lld)", p1->alert_utime, p2->alert_utime);
838 return p1->alert_utime < p2->alert_utime ? -1 : 1;
841 static GFunc _cal_server_alarm_print_cb(gpointer data, gpointer user_data)
843 struct _alarm_data_s *ad = (struct _alarm_data_s *)data;
844 DBG("id(%d) unit(%d) tick(%d) type(%d) time(%lld) datetime[%s] alert_utime[%lld]",
845 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime, ad->alert_utime);
849 static int _cal_server_alarm_register(GList *alarm_list)
852 RETV_IF(NULL == alarm_list, CALENDAR_ERROR_INVALID_PARAMETER);
854 int ret = CALENDAR_ERROR_NONE;
855 GList *l = g_list_first(alarm_list);
856 RETV_IF(NULL == l, CALENDAR_ERROR_INVALID_PARAMETER);
858 struct _alarm_data_s *ad = (struct _alarm_data_s *)l->data;
859 RETVM_IF(NULL == ad, CALENDAR_ERROR_DB_FAILED, "No data");
861 /* clear all alarm which set by mine. */
862 ret = alarmmgr_enum_alarm_ids(_cal_server_alarm_clear_all_cb, NULL);
863 if (ret != ALARMMGR_RESULT_SUCCESS) {
864 /* LCOV_EXCL_START */
865 ERR("alarmmgr_enum_alarm_ids() Fail");
870 time_t mod_time = (time_t)ad->alert_utime;
871 /*Temporarily added error logs to handle a defect*/
872 ERR("_cal_server_alarm_register ad->alert_utime (%lld) mod_time (%ld)", ad->alert_utime, mod_time);
873 alarm_entry_t *alarm_info = NULL;
874 alarm_info = alarmmgr_create_alarm();
875 if (NULL == alarm_info) {
876 /* LCOV_EXCL_START */
877 ERR("Failed to create alarm");
878 return CALENDAR_ERROR_DB_FAILED;
882 struct tm st_alarm = {0};
884 switch (ad->system_type) {
885 case CALENDAR_SYSTEM_EAST_ASIAN_LUNISOLAR:
886 gmtime_r(&mod_time, &st_alarm);
891 ERR("This case have been choosen "); //Temporarily logs
892 localtime_r(&mod_time, &st_alarm);
896 alarm_date_t date = {0};
897 date.year = st_alarm.tm_year + 1900;
898 date.month = st_alarm.tm_mon + 1;
899 date.day = st_alarm.tm_mday;
900 date.hour = st_alarm.tm_hour;
901 date.min = st_alarm.tm_min;
902 date.sec = st_alarm.tm_sec;
903 alarmmgr_set_time(alarm_info, date);
904 /*Temporarily added error logs to handle a defect*/
905 ERR(COLOR_CYAN" >>> registered record id (%d) at %04d/%02d/%02d %02d:%02d:%02d "COLOR_END" (utime(%lld), datetime[%s], tick(%d) unit(%d))",
906 ad->event_id, date.year, date.month, date.day, date.hour, date.min, date.sec,
907 ad->time, ad->datetime, ad->tick, ad->unit);
910 ret = alarmmgr_add_alarm_with_localtime(alarm_info, NULL, &alarm_id);
912 /* LCOV_EXCL_START */
913 ERR("alarmmgr_add_alarm_with_localtime Fail (%d)", ret);
914 alarmmgr_free_alarm(alarm_info);
918 DBG("alarmmgr id (%d)", alarm_id);
919 _cal_server_alarm_update_alarm_id(alarm_id, ad->event_id, ad->tick, ad->unit);
920 alarmmgr_free_alarm(alarm_info);
921 return CALENDAR_ERROR_NONE;
924 static bool __app_matched_cb(app_control_h app_control, const char *package, void *user_data)
931 RETV_IF(NULL == user_data, true);
934 ret = app_control_get_mime(app_control, &mime);
935 RETVM_IF(APP_CONTROL_ERROR_NONE != ret, true, "app_control_get_mime() Fail(%d)", ret);
937 const char *reminder_mime = "application/x-tizen.calendar.reminder";
938 if (strncmp(mime, reminder_mime, strlen(reminder_mime))) { /* not same */
939 DBG("get mime[%s] is not [%s]", mime, reminder_mime);
945 struct alarm_ud *au = (struct alarm_ud *)user_data;
946 GList *alarm_list = au->alarm_list;
947 if (NULL == alarm_list) {
948 /* LCOV_EXCL_START */
954 len = g_list_length(alarm_list);
956 DBG("len is 0, no alarm list");
960 app_control_h ac = NULL;
961 ret = app_control_create(&ac);
962 if (APP_CONTROL_ERROR_NONE != ret) {
963 /* LCOV_EXCL_START */
964 ERR("app_control_create() Fail(%d)", ret);
968 ret = app_control_set_operation(ac, APP_CONTROL_OPERATION_DEFAULT);
969 if (APP_CONTROL_ERROR_NONE != ret) {
970 /* LCOV_EXCL_START */
971 ERR("app_control_create() Fail(%d)", ret);
972 app_control_destroy(ac);
976 ret = app_control_set_app_id(ac, package);
977 if (APP_CONTROL_ERROR_NONE != ret) {
978 /* LCOV_EXCL_START */
979 ERR("app_control_set_app_id() Fail(%d)", ret);
980 app_control_destroy(ac);
986 ids = calloc(len, sizeof(char *));
988 /* LCOV_EXCL_START */
989 ERR("calloc() Fail");
990 app_control_destroy(ac);
994 GList *cursor = g_list_first(alarm_list);
995 for (i = 0; i < len; i++) {
996 if (NULL == cursor) {
997 ERR("cursor is NULL");
1000 struct _alarm_data_s *ad = (struct _alarm_data_s *)cursor->data;
1003 cursor = g_list_next(cursor);
1006 DBG("pkg[%s] time[%lld] tick[%d] unit[%d] record_type[%d]",
1007 package, ad->time, ad->tick, ad->unit, ad->record);
1010 char extra[CAL_STR_MIDDLE_LEN] = {0};
1011 slen = snprintf(extra, sizeof(extra), "%s=%d", "id", ad->event_id);
1012 slen += snprintf(extra+slen, sizeof(extra)-slen, "&%s=%lld", "time", ad->time);
1013 slen += snprintf(extra+slen, sizeof(extra)-slen, "&%s=%d", "tick", ad->tick);
1014 slen += snprintf(extra+slen, sizeof(extra)-slen, "&%s=%d", "unit", ad->unit);
1015 slen += snprintf(extra+slen, sizeof(extra)-slen, "&%s=%d", "type", ad->record);
1018 * key: id, value: id=4&time=123123&..
1020 char buf_id[CAL_STR_MIDDLE_LEN] = {0};
1021 snprintf(buf_id, sizeof(buf_id), "%d", ad->event_id);
1022 app_control_add_extra_data(ac, buf_id, extra);
1023 DBG("value[%s] id[%s]", extra, buf_id);
1026 ids[i] = strdup(buf_id);
1028 cursor = g_list_next(cursor);
1030 app_control_add_extra_data_array(ac, "ids", (const char **)ids, len);
1031 app_control_send_launch_request(ac, NULL, NULL);
1032 app_control_destroy(ac);
1034 for (i = 0; i < len; i++) {
1043 static void _cal_server_alarm_noti_with_control(GList *alarm_list)
1048 RETM_IF(NULL == alarm_list, "No alarm list");
1050 app_control_h app_control = NULL;
1051 ret = app_control_create(&app_control);
1052 if (APP_CONTROL_ERROR_NONE != ret) {
1053 /* LCOV_EXCL_START */
1054 ERR("app_control_create() Fail(%d)", ret);
1056 /* LCOV_EXCL_STOP */
1058 ret = app_control_set_operation(app_control, APP_CONTROL_OPERATION_VIEW);
1059 if (APP_CONTROL_ERROR_NONE != ret) {
1060 /* LCOV_EXCL_START */
1061 ERR("app_control_set_operation() Fail(%d)", ret);
1062 app_control_destroy(app_control);
1064 /* LCOV_EXCL_STOP */
1066 ret = app_control_set_mime(app_control, "application/x-tizen.calendar.reminder");
1067 if (APP_CONTROL_ERROR_NONE != ret) {
1068 /* LCOV_EXCL_START */
1069 ERR("app_control_set_mime() Fail(%d)", ret);
1070 app_control_destroy(app_control);
1072 /* LCOV_EXCL_STOP */
1075 struct alarm_ud *au = calloc(1, sizeof(struct alarm_ud));
1077 /* LCOV_EXCL_START */
1078 ERR("calloc() Fail");
1079 app_control_destroy(app_control);
1081 /* LCOV_EXCL_STOP */
1083 au->alarm_list = alarm_list;
1084 ret = app_control_foreach_app_matched(app_control, __app_matched_cb, au);
1085 if (APP_CONTROL_ERROR_NONE != ret) {
1086 /* LCOV_EXCL_START */
1087 ERR("app_control_foreach_app_matched() Fail(%d)", ret);
1089 app_control_destroy(app_control);
1091 /* LCOV_EXCL_STOP */
1094 app_control_destroy(app_control);
1097 static void _cal_server_alarm_noti_with_callback(GList *alarm_list)
1099 RETM_IF(NULL == alarm_list, "No alarm list");
1101 GList *l = g_list_first(alarm_list);
1103 struct _alarm_data_s *ad = (struct _alarm_data_s *)l->data;
1109 DBG("callback time[%lld] tick[%d] unit[%d] record_type[%d]",
1110 ad->time, ad->tick, ad->unit, ad->record);
1113 char extra[CAL_STR_MIDDLE_LEN] = {0};
1114 len = snprintf(extra, sizeof(extra), "%s=%d", "id", ad->event_id);
1115 len += snprintf(extra+len, sizeof(extra)-len, "&%s=%lld", "time", ad->time);
1116 len += snprintf(extra+len, sizeof(extra)-len, "&%s=%d", "tick", ad->tick);
1117 len += snprintf(extra+len, sizeof(extra)-len, "&%s=%d", "unit", ad->unit);
1118 len += snprintf(extra+len, sizeof(extra)-len, "&%s=%d", "type", ad->record);
1119 cal_dbus_publish_reminder(len, extra);
1125 static void cal_server_alarm_register_next_alarm(time_t utime)
1129 ERR(" cal_server_alarm_register_next_alarm utime = %ld", utime); // Temporarily logs
1131 _cal_server_alarm_get_latest(utime, false, &l);
1135 l = g_list_sort(l, _cal_server_alarm_sort_cb);
1136 g_list_foreach(l, (GFunc)_cal_server_alarm_print_cb, NULL);
1137 _cal_server_alarm_register(l);
1139 g_list_free_full(l, free);
1142 static void cal_server_alarm_alert(time_t tt_alert)
1145 _cal_server_alarm_get_latest(tt_alert, true, &l);
1149 _cal_server_alarm_noti_with_callback(l);
1150 _cal_server_alarm_noti_with_control(l);
1151 g_list_free_full(l, free);
1154 static int _alert_cb(alarm_id_t alarm_id, void *data)
1157 DBG("alarm_id (%d)", (int)alarm_id);
1159 time_t tt_alert = 0;
1160 cal_server_alarm_get_alert_time(alarm_id, &tt_alert);
1161 cal_server_alarm_alert(tt_alert);
1162 cal_server_alarm_unset_alerted_alarmmgr_id(alarm_id);
1163 cal_server_alarm_start();
1167 static void _timechanged_cb(keynode_t *node, void *data)
1169 cal_server_alarm_alert(time(NULL));
1170 cal_server_alarm_start();
1173 static void _cal_server_alarm_set_timechange(void)
1175 vconf_notify_key_changed(VCONFKEY_SYSTEM_TIME_CHANGED, _timechanged_cb, NULL);
1176 vconf_notify_key_changed(VCONFKEY_TELEPHONY_NITZ_GMT, _timechanged_cb, NULL);
1177 vconf_notify_key_changed(VCONFKEY_TELEPHONY_NITZ_ZONE, _timechanged_cb, NULL);
1178 vconf_notify_key_changed(VCONFKEY_TELEPHONY_NITZ_EVENT_GMT, _timechanged_cb, NULL);
1181 static void _cal_server_alarm_unset_timechange(void)
1183 vconf_ignore_key_changed(VCONFKEY_SYSTEM_TIME_CHANGED, _timechanged_cb);
1184 vconf_ignore_key_changed(VCONFKEY_TELEPHONY_NITZ_GMT, _timechanged_cb);
1185 vconf_ignore_key_changed(VCONFKEY_TELEPHONY_NITZ_ZONE, _timechanged_cb);
1186 vconf_ignore_key_changed(VCONFKEY_TELEPHONY_NITZ_EVENT_GMT, _timechanged_cb);
1189 static void _changed_cb(const char* view_uri, void* data)
1191 DBG("Receive alarm change signal");
1192 cal_server_alarm_start();
1195 static int _cal_server_alarm_set_inotify(calendar_db_changed_cb callback)
1197 cal_inotify_subscribe(CAL_NOTI_TYPE_EVENT, CAL_NOTI_FILE_EVENT, callback, NULL);
1198 cal_inotify_subscribe(CAL_NOTI_TYPE_TODO, CAL_NOTI_FILE_TODO, callback, NULL);
1202 static void _cal_server_alarm_unset_inotify(calendar_db_changed_cb callback)
1204 cal_inotify_unsubscribe(CAL_NOTI_FILE_EVENT, callback, NULL);
1205 cal_inotify_unsubscribe(CAL_NOTI_FILE_TODO, callback, NULL);
1208 static int cal_server_alarm_init(void)
1212 _cal_server_alarm_set_timechange();
1213 _cal_server_alarm_set_inotify(_changed_cb);
1215 ret = alarmmgr_set_cb(_alert_cb, NULL);
1217 /* LCOV_EXCL_START */
1218 ERR("alarmmgr_set_cb() Fail(%d)", ret);
1219 return CALENDAR_ERROR_SYSTEM;
1220 /* LCOV_EXCL_STOP */
1223 ret = alarmmgr_init("calendar-service");
1225 /* LCOV_EXCL_START */
1226 ERR("alarmmgr_init() Fail(%d)", ret);
1227 return CALENDAR_ERROR_SYSTEM;
1228 /* LCOV_EXCL_STOP */
1231 return CALENDAR_ERROR_NONE;
1234 static gpointer _cal_server_alarm_main(gpointer user_data)
1236 DBG("thread alarm: start");
1239 bool is_initialized = false;
1242 g_mutex_lock(&_cal_server_alarm_mutex);
1244 * While syncing with contacts,
1245 * because calendar-service could be stopped by on-demand,
1246 * holding on-demand is needed.
1248 cal_server_ondemand_hold();
1251 if (false == is_initialized) {
1252 ret = cal_server_alarm_init();
1253 if (CALENDAR_ERROR_NONE != ret) {
1254 /* LCOV_EXCL_START */
1255 ERR("cal_server_alarm_init() Fail(%d)", ret);
1257 /* LCOV_EXCL_STOP */
1259 DBG("thread alarm: init");
1260 is_initialized = true;
1263 ret = cal_connect();
1264 if (CALENDAR_ERROR_NONE != ret) {
1265 /* LCOV_EXCL_START */
1266 ERR("cal_connect() Fail(%d)", ret);
1268 /* LCOV_EXCL_STOP */
1271 cal_server_alarm_register_next_alarm(time(NULL));
1276 cal_server_ondemand_release();
1277 cal_server_ondemand_start();
1279 DBG("thread alarm: wait");
1280 while (false == signal_called)
1281 g_cond_wait(&_cal_server_alarm_cond, &_cal_server_alarm_mutex);
1282 signal_called = false;
1283 g_mutex_unlock(&_cal_server_alarm_mutex);
1288 DBG("thread alarm: end");
1289 g_thread_exit(NULL);
1294 void cal_server_alarm_send_signal(void)
1296 g_mutex_lock(&_cal_server_alarm_mutex);
1297 signal_called = true;
1298 g_cond_signal(&_cal_server_alarm_cond);
1299 g_mutex_unlock(&_cal_server_alarm_mutex);
1302 void cal_server_alarm_start(void)
1306 if (NULL == _cal_server_alarm_thread) {
1307 g_mutex_init(&_cal_server_alarm_mutex);
1308 g_cond_init(&_cal_server_alarm_cond);
1309 _cal_server_alarm_thread = g_thread_new(CAL_SERVER_ALARM_THREAD_NAME,
1310 _cal_server_alarm_main, NULL);
1312 cal_server_alarm_send_signal();
1315 static void cal_server_alarm_deinit(void)
1318 _cal_server_alarm_unset_inotify(_changed_cb);
1319 _cal_server_alarm_unset_timechange();
1322 void cal_server_alarm_end(void)
1326 server_killed = true;
1328 cal_server_alarm_deinit();
1329 cal_server_alarm_send_signal();
1331 g_cond_clear(&_cal_server_alarm_cond);
1332 g_thread_join(_cal_server_alarm_thread);
1333 g_thread_unref(_cal_server_alarm_thread);
1334 _cal_server_alarm_thread = NULL;