Fixed the error reading timezone incorrectly
[platform/core/pim/calendar-service.git] / server / cal_server_alarm.c
1 /*
2  * Calendar Service
3  *
4  * Copyright (c) 2012 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
5  *
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
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  *
18  */
19
20 #include <stdlib.h>
21 #include <sys/time.h>
22 #include <unistd.h>
23 #include <alarm.h>
24 #include <vconf.h>
25 #include <app.h>
26
27 #include "calendar.h"
28 #include "cal_typedef.h"
29 #include "cal_internal.h"
30 #include "cal_time.h"
31 #include "cal_inotify.h"
32 #include "cal_db_util.h"
33 #include "cal_db.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"
39
40 #define CAL_SERVER_ALARM_THREAD_NAME "cal_server_alarm"
41
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;
47
48 struct _alarm_data_s {
49         int event_id;
50         long long int alert_utime; /* to compare */
51         int unit;
52         int tick;
53         int type; /* utime, localtime */
54         long long int time;
55         int record; /* todo, event */
56         char datetime[CAL_STR_SHORT_LEN32];
57         int system_type;
58 };
59
60 struct alarm_ud {
61         GList *alarm_list;
62 };
63
64 /* this api is necessary for repeat instance. */
65 static int cal_server_alarm_unset_alerted_alarmmgr_id(int alarm_id)
66 {
67         char query[CAL_DB_SQL_MAX_LEN] = {0};
68         int ret = 0;
69
70         ret = cal_db_util_begin_trans();
71         if (CALENDAR_ERROR_NONE != ret) {
72                 /* LCOV_EXCL_START */
73                 ERR("cal_db_util_begin_trans() Fail");
74                 return CALENDAR_ERROR_DB_FAILED;
75                 /* LCOV_EXCL_STOP */
76         }
77
78         DBG("alarm_id(%d)", alarm_id);
79
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) {
84                 /* LCOV_EXCL_START */
85                 ERR("cal_db_util_query_exec() Fail(%d)", ret);
86                 SECURE("[%s]", query);
87                 cal_db_util_end_trans(false);
88                 return ret;
89                 /* LCOV_EXCL_STOP */
90         }
91         cal_db_util_end_trans(true);
92         return CALENDAR_ERROR_NONE;
93 }
94
95 static int _cal_server_alarm_clear_all_cb(alarm_id_t alarm_id, void *data)
96 {
97         int ret;
98
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);
105                 return ret;
106                 /* LCOV_EXCL_STOP */
107         }
108         return CALENDAR_ERROR_NONE;
109 }
110
111 static int _cal_server_alarm_update_alarm_id(int alarm_id, int event_id, int tick, int unit)
112 {
113         char query[CAL_DB_SQL_MAX_LEN] = {0};
114         int ret = 0;
115
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;
121                 /* LCOV_EXCL_STOP */
122         }
123
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);
134                 return ret;
135                 /* LCOV_EXCL_STOP */
136         }
137         cal_db_util_end_trans(true);
138         return CALENDAR_ERROR_NONE;
139 }
140
141 static long long int _get_event_alert_utime(const char *field, int event_id, time_t current)
142 {
143         int ret = 0;
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);
148
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);
155                 return ret;
156                 /* LCOV_EXCL_STOP */
157         }
158
159         long long int utime = 0;
160         if (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt))
161                 utime = sqlite3_column_int(stmt, 0);
162
163         sqlite3_finalize(stmt);
164         return utime;
165 }
166
167 static int _get_event_alert_localtime(const char *field, int event_id, time_t current)
168 {
169         int ret = 0;
170         char query[CAL_DB_SQL_MAX_LEN] = {0};
171         struct tm st = {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);
175
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);
182                 return ret;
183                 /* LCOV_EXCL_STOP */
184         }
185
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);
189
190         if (NULL == datetime || '\0' == *datetime) {
191                 /* LCOV_EXCL_START */
192                 ERR("Invalid datetime [%s]", datetime);
193                 sqlite3_finalize(stmt);
194                 return 0;
195                 /* LCOV_EXCL_STOP */
196         }
197
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);
202
203         st.tm_year = y - 1900;
204         st.tm_mon = m - 1;
205         st.tm_mday = d;
206         st.tm_hour = h;
207         st.tm_min = n;
208         st.tm_sec = s;
209         st.tm_isdst = cal_time_is_dst_savings();
210
211         return (long long int)mktime(&st);
212 }
213
214 static int64_t _get_todo_alert_utime(const char *field, int id, time_t now_t)
215 {
216         int ret = 0;
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);
220
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);
227                 return ret;
228                 /* LCOV_EXCL_STOP */
229         }
230
231         int64_t utime = 0;
232         ret = cal_db_util_stmt_step(stmt);
233         switch (ret) {
234         case CAL_SQLITE_ROW:
235                 utime = (int64_t)sqlite3_column_int64(stmt, 0);
236                 break;
237                 /* LCOV_EXCL_START
238         case SQLITE_DONE:
239                 ERR("No data");
240                 break;*/ //Svace:371986
241         default:
242                 ERR("Invalid return(%d)", ret);
243                 break;
244                 /* LCOV_EXCL_STOP */
245         }
246
247         sqlite3_finalize(stmt);
248         return utime;
249 }
250
251 static int _get_todo_alert_localtime(const char *field, int event_id, time_t current)
252 {
253         int ret = 0;
254         char query[CAL_DB_SQL_MAX_LEN] = {0};
255         struct tm st = {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);
259
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);
266                 return ret;
267                 /* LCOV_EXCL_STOP */
268         }
269
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);
273
274         if (NULL == datetime || '\0' == *datetime) {
275                 /* LCOV_EXCL_START */
276                 ERR("Invalid datetime [%s]", datetime);
277                 sqlite3_finalize(stmt);
278                 return 0;
279                 /* LCOV_EXCL_STOP */
280         }
281
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);
286
287         st.tm_year = y - 1900;
288         st.tm_mon = m - 1;
289         st.tm_mday = d;
290         st.tm_hour = h;
291         st.tm_min = n;
292         st.tm_sec = s;
293         st.tm_isdst = cal_time_is_dst_savings();
294
295         return (long long int)mktime(&st);
296 }
297 /*
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.
301  */
302 static int cal_server_alarm_get_alert_time(int alarm_id, time_t *tt_alert)
303 {
304         int ret = 0;
305         RETV_IF(NULL == tt_alert, CALENDAR_ERROR_INVALID_PARAMETER);
306
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);
312
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);
319                 return ret;
320                 /* LCOV_EXCL_STOP */
321         }
322
323         int event_id = 0;
324         int unit = 0;
325         int tick = 0;
326         int type = 0;
327         long long int utime = 0;
328         const char *datetime = NULL;
329         int record_type = 0;
330         int dtstart_type = 0;
331         int dtend_type = 0;
332         struct tm st = {0};
333
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);
344         }
345
346         if (CALENDAR_ALARM_TIME_UNIT_SPECIFIC == unit) {
347                 if (CALENDAR_TIME_UTIME == type) {
348                         *tt_alert = utime;
349                 } else {
350                         int y = 0, m = 0, d = 0;
351                         int h = 0, n = 0, s = 0;
352                         if (datetime) {
353                                 sscanf(datetime, CAL_FORMAT_LOCAL_DATETIME, &y, &m, &d, &h, &n, &s);
354
355                                 st.tm_year = y - 1900;
356                                 st.tm_mon = m - 1;
357                                 st.tm_mday = d;
358                                 st.tm_hour = h;
359                                 st.tm_min = n;
360                                 st.tm_sec = s;
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);
364                         }
365                 }
366                 sqlite3_finalize(stmt);
367                 return CALENDAR_ERROR_NONE;
368         }
369         sqlite3_finalize(stmt);
370
371         time_t current = time(NULL);
372         current += (tick * unit);
373         current -= 2; /* in case time passed */
374
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);
380                         break;
381
382                 case CALENDAR_TIME_LOCALTIME:
383                         utime = _get_event_alert_localtime("dtstart_datetime", event_id, current);
384                         break;
385                 }
386                 break;
387
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);
392                         break;
393
394                 case CALENDAR_TIME_LOCALTIME:
395                         utime = _get_todo_alert_localtime("dtend_datetime", event_id, current);
396                         break;
397                 }
398                 break;
399         }
400         *tt_alert = utime - (tick * unit);
401
402         DBG("alert_time(%ld) = utime(%lld) - (tick(%d) * unit(%d))", *tt_alert, utime, tick, unit);
403
404         return CALENDAR_ERROR_NONE;
405 }
406
407 /*
408  * bool get_all is
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)
413  */
414 static void _cal_server_alarm_get_upcoming_specific_utime(time_t utime, bool get_all, GList **l)
415 {
416         int ret = 0;
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");
426
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);
433                 return;
434                 /* LCOV_EXCL_STOP */
435         }
436
437         while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
438                 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
439                 if (NULL == ad) {
440                         /* LCOV_EXCL_START */
441                         ERR("calloc() Fail");
442                         sqlite3_finalize(stmt);
443                         return;
444                         /* LCOV_EXCL_STOP */
445                 }
446
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;
458         }
459         sqlite3_finalize(stmt);
460 }
461
462 static void _cal_server_alarm_get_upcoming_specific_localtime(const char *datetime, bool get_all, GList **l)
463 {
464         int ret = 0;
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");
474
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);
481                 return;
482                 /* LCOV_EXCL_STOP */
483         }
484
485         while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
486                 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
487                 if (NULL == ad) {
488                         /* LCOV_EXCL_START */
489                         ERR("calloc() Fail");
490                         sqlite3_finalize(stmt);
491                         return;
492                         /* LCOV_EXCL_STOP */
493                 }
494
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);
504
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);
508
509                 struct tm st = {0};
510                 st.tm_year = y - 1900;
511                 st.tm_mon = m -1;
512                 st.tm_mday = d;
513                 st.tm_hour = h;
514                 st.tm_min = n;
515                 st.tm_sec = s;
516                 st.tm_isdst = cal_time_is_dst_savings();
517                 ad->alert_utime = (long long int)mktime(&st);
518                 if (false == get_all) break;
519         }
520         sqlite3_finalize(stmt);
521 }
522
523 static void _cal_server_alarm_get_upcoming_nonspecific_event_utime(time_t utime, bool get_all, GList **l)
524 {
525         int ret = 0;
526         /*
527          * A:alarm
528          * B:utime
529          */
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");
540
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);
547                 return;
548                 /* LCOV_EXCL_STOP */
549         }
550
551         while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
552                 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
553                 if (NULL == ad) {
554                         /* LCOV_EXCL_START */
555                         ERR("calloc() Fail");
556                         sqlite3_finalize(stmt);
557                         return;
558                         /* LCOV_EXCL_STOP */
559                 }
560
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);
570
571                 ad->alert_utime = ad->time - (ad->tick * ad->unit);
572                 if (false == get_all) break;
573         }
574         sqlite3_finalize(stmt);
575 }
576
577 static void _cal_server_alarm_get_upcoming_nonspecific_event_localtime(const char *datetime, bool get_all, GList **l)
578 {
579         int ret = 0;
580         /*
581          * A:alarm
582          * B:localtime
583          */
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);
600                 return;
601                 /* LCOV_EXCL_STOP */
602         }
603
604         while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
605                 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
606                 if (NULL == ad) {
607                         /* LCOV_EXCL_START */
608                         ERR("calloc() Fail");
609                         sqlite3_finalize(stmt);
610                         return;
611                         /* LCOV_EXCL_STOP */
612                 }
613
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);
623
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);
627
628                 struct tm st = {0};
629                 st.tm_year = y - 1900;
630                 st.tm_mon = m -1;
631                 st.tm_mday = d;
632                 st.tm_hour = h;
633                 st.tm_min = n;
634                 st.tm_sec = s;
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;
638         }
639         sqlite3_finalize(stmt);
640 }
641
642 static void _cal_server_alarm_get_upcoming_nonspecific_todo_utime(time_t utime, bool get_all, GList **l)
643 {
644         int ret = 0;
645         /*
646          * A:alarm
647          * S:todo(utime)
648          */
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 ");
658
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);
665                 return;
666                 /* LCOV_EXCL_STOP */
667         }
668
669         while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
670                 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
671                 if (NULL == ad) {
672                         /* LCOV_EXCL_START */
673                         ERR("calloc() Fail");
674                         sqlite3_finalize(stmt);
675                         return;
676                         /* LCOV_EXCL_STOP */
677                 }
678
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);
688
689                 ad->alert_utime = ad->time - (ad->tick * ad->unit);
690                 if (false == get_all) break;
691         }
692         sqlite3_finalize(stmt);
693 }
694
695 static void _cal_server_alarm_get_upcoming_nonspecific_todo_localtime(const char *datetime, bool get_all, GList **l)
696 {
697         int ret = 0;
698         /*
699          * A:alarm
700          * B:todo(localtime)
701          */
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 ");
711
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);
718                 return;
719                 /* LCOV_EXCL_STOP */
720         }
721
722         while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
723                 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
724                 if (NULL == ad) {
725                         /* LCOV_EXCL_START */
726                         ERR("calloc() Fail");
727                         sqlite3_finalize(stmt);
728                         return;
729                         /* LCOV_EXCL_STOP */
730                 }
731
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);
741
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);
745
746                 struct tm st = {0};
747                 st.tm_year = y - 1900;
748                 st.tm_mon = m -1;
749                 st.tm_mday = d;
750                 st.tm_hour = h;
751                 st.tm_min = n;
752                 st.tm_sec = s;
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;
756         }
757         sqlite3_finalize(stmt);
758 }
759
760 static void _cal_server_alarm_get_latest(time_t utime, bool get_all, GList **out_l)
761 {
762         int ret = 0;
763         CAL_FN_CALL();
764         RET_IF(NULL == out_l);
765
766         tzset();
767         struct tm st_local = {0};
768         localtime_r(&utime, &st_local);
769
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);
774
775         if(ret < 0){
776                 WARN("datetime is truncated (%s)",datetime);
777         }
778
779         DBG("get alert to register with given time (%ld) datetime[%s]", utime, datetime);
780
781         GList *l = NULL;
782
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);
786
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);
790
791         *out_l = l;
792 }
793
794 static gint _cal_server_alarm_sort_cb(gconstpointer a, gconstpointer b)
795 {
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);
799
800         return p1->alert_utime < p2->alert_utime ? -1 : 1;
801 }
802
803 static GFunc _cal_server_alarm_print_cb(gpointer data, gpointer user_data)
804 {
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);
808         return 0;
809 }
810
811 static int _cal_server_alarm_register(GList *alarm_list)
812 {
813         CAL_FN_CALL();
814         RETV_IF(NULL == alarm_list, CALENDAR_ERROR_INVALID_PARAMETER);
815
816         int ret = CALENDAR_ERROR_NONE;
817         GList *l = g_list_first(alarm_list);
818         RETV_IF(NULL == l, CALENDAR_ERROR_INVALID_PARAMETER);
819
820         struct _alarm_data_s *ad = (struct _alarm_data_s *)l->data;
821         RETVM_IF(NULL == ad, CALENDAR_ERROR_DB_FAILED, "No data");
822
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");
828                 return ret;
829                 /* LCOV_EXCL_STOP */
830         }
831
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;
839                 /* LCOV_EXCL_STOP */
840         }
841         tzset();
842         struct tm st_alarm = {0};
843
844         switch (ad->system_type) {
845         case CALENDAR_SYSTEM_EAST_ASIAN_LUNISOLAR:
846                 gmtime_r(&mod_time, &st_alarm);
847                 break;
848
849         default:
850                 tzset();
851                 localtime_r(&mod_time, &st_alarm);
852                 break;
853         }
854
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);
866
867         int alarm_id = 0;
868         ret = alarmmgr_add_alarm_with_localtime(alarm_info, NULL, &alarm_id);
869         if (ret < 0) {
870                 /* LCOV_EXCL_START */
871                 ERR("alarmmgr_add_alarm_with_localtime Fail (%d)", ret);
872                 alarmmgr_free_alarm(alarm_info);
873                 return ret;
874                 /* LCOV_EXCL_STOP */
875         }
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;
880 }
881
882 static bool __app_matched_cb(app_control_h app_control, const char *package, void *user_data)
883 {
884         CAL_FN_CALL();
885
886         int ret = 0;
887         int i;
888
889         RETV_IF(NULL == user_data, true);
890
891         char *mime = NULL;
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);
894
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);
898                 free(mime);
899                 return true;
900         }
901         free(mime);
902
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 */
907                 ERR("No list");
908                 return true;
909                 /* LCOV_EXCL_STOP */
910         }
911         int len = 0;
912         len = g_list_length(alarm_list);
913         if (0 == len) {
914                 DBG("len is 0, no alarm list");
915                 return true;
916         }
917
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);
923                 return true;
924                 /* LCOV_EXCL_STOP */
925         }
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);
931                 return true;
932                 /* LCOV_EXCL_STOP */
933         }
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);
939                 return true;
940                 /* LCOV_EXCL_STOP */
941         }
942
943         char **ids = NULL;
944         ids = calloc(len, sizeof(char *));
945         if (NULL == ids) {
946                 /* LCOV_EXCL_START */
947                 ERR("calloc() Fail");
948                 app_control_destroy(ac);
949                 return true;
950                 /* LCOV_EXCL_STOP */
951         }
952         GList *cursor = g_list_first(alarm_list);
953         for (i = 0; i < len; i++) {
954                 if (NULL == cursor) {
955                         ERR("cursor is NULL");
956                         break;
957                 }
958                 struct _alarm_data_s *ad = (struct _alarm_data_s *)cursor->data;
959                 if (NULL == ad) {
960                         WARN("No data");
961                         cursor = g_list_next(cursor);
962                         continue;
963                 }
964                 DBG("pkg[%s] time[%lld] tick[%d] unit[%d] record_type[%d]",
965                                 package, ad->time, ad->tick, ad->unit, ad->record);
966
967                 int slen = 0;
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);
974
975                 /*
976                  * key: id, value: id=4&time=123123&..
977                  */
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);
982
983                 /* append ids */
984                 ids[i] = strdup(buf_id);
985
986                 cursor = g_list_next(cursor);
987         }
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);
991
992         for (i = 0; i < len; i++) {
993                 free(ids[i]);
994                 ids[i] = NULL;
995         }
996         free(ids);
997
998         return true;
999 }
1000
1001 static void _cal_server_alarm_noti_with_control(GList *alarm_list)
1002 {
1003         CAL_FN_CALL();
1004
1005         int ret = 0;
1006         RETM_IF(NULL == alarm_list, "No alarm list");
1007
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);
1013                 return;
1014                 /* LCOV_EXCL_STOP */
1015         }
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);
1021                 return;
1022                 /* LCOV_EXCL_STOP */
1023         }
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);
1029                 return;
1030                 /* LCOV_EXCL_STOP */
1031         }
1032
1033         struct alarm_ud *au = calloc(1, sizeof(struct alarm_ud));
1034         if (NULL == au) {
1035                 /* LCOV_EXCL_START */
1036                 ERR("calloc() Fail");
1037                 app_control_destroy(app_control);
1038                 return;
1039                 /* LCOV_EXCL_STOP */
1040         }
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);
1046                 free(au);
1047                 app_control_destroy(app_control);
1048                 return;
1049                 /* LCOV_EXCL_STOP */
1050         }
1051         free(au);
1052         app_control_destroy(app_control);
1053 }
1054
1055 static void _cal_server_alarm_noti_with_callback(GList *alarm_list)
1056 {
1057         RETM_IF(NULL == alarm_list, "No alarm list");
1058
1059         GList *l = g_list_first(alarm_list);
1060         while (l) {
1061                 struct _alarm_data_s *ad = (struct _alarm_data_s *)l->data;
1062                 if (NULL == ad) {
1063                         WARN("No data");
1064                         l = g_list_next(l);
1065                         continue;
1066                 }
1067                 DBG("callback time[%lld] tick[%d] unit[%d] record_type[%d]",
1068                                 ad->time, ad->tick, ad->unit, ad->record);
1069
1070                 int len = 0;
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);
1078
1079                 l = g_list_next(l);
1080         }
1081 }
1082
1083 static void cal_server_alarm_register_next_alarm(time_t utime)
1084 {
1085         CAL_FN_CALL();
1086
1087         GList *l = NULL;
1088         _cal_server_alarm_get_latest(utime, false, &l);
1089         if (NULL == l)
1090                 return;
1091
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);
1095
1096         g_list_free_full(l, free);
1097 }
1098
1099 static void cal_server_alarm_alert(time_t tt_alert)
1100 {
1101         GList *l = NULL;
1102         _cal_server_alarm_get_latest(tt_alert, true, &l);
1103         if (NULL == l)
1104                 return;
1105
1106         _cal_server_alarm_noti_with_callback(l);
1107         _cal_server_alarm_noti_with_control(l);
1108         g_list_free_full(l, free);
1109 }
1110
1111 static int _alert_cb(alarm_id_t alarm_id, void *data)
1112 {
1113         CAL_FN_CALL();
1114         DBG("alarm_id (%d)", (int)alarm_id);
1115
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();
1121         return 0;
1122 }
1123
1124 static void _timechanged_cb(keynode_t *node, void *data)
1125 {
1126         cal_server_alarm_alert(time(NULL));
1127         cal_server_alarm_start();
1128 }
1129
1130 static void _cal_server_alarm_set_timechange(void)
1131 {
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);
1136 }
1137
1138 static void _cal_server_alarm_unset_timechange(void)
1139 {
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);
1144 }
1145
1146 static void _changed_cb(const char* view_uri, void* data)
1147 {
1148         DBG("Receive alarm change signal");
1149         cal_server_alarm_start();
1150 }
1151
1152 static int _cal_server_alarm_set_inotify(calendar_db_changed_cb callback)
1153 {
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);
1156         return 0;
1157 }
1158
1159 static void _cal_server_alarm_unset_inotify(calendar_db_changed_cb callback)
1160 {
1161         cal_inotify_unsubscribe(CAL_NOTI_FILE_EVENT, callback, NULL);
1162         cal_inotify_unsubscribe(CAL_NOTI_FILE_TODO, callback, NULL);
1163 }
1164
1165 static int cal_server_alarm_init(void)
1166 {
1167         int ret = 0;
1168
1169         _cal_server_alarm_set_timechange();
1170         _cal_server_alarm_set_inotify(_changed_cb);
1171
1172         ret = alarmmgr_set_cb(_alert_cb, NULL);
1173         if (ret < 0) {
1174                 /* LCOV_EXCL_START */
1175                 ERR("alarmmgr_set_cb() Fail(%d)", ret);
1176                 return CALENDAR_ERROR_SYSTEM;
1177                 /* LCOV_EXCL_STOP */
1178         }
1179
1180         ret = alarmmgr_init("calendar-service");
1181         if (ret < 0) {
1182                 /* LCOV_EXCL_START */
1183                 ERR("alarmmgr_init() Fail(%d)", ret);
1184                 return CALENDAR_ERROR_SYSTEM;
1185                 /* LCOV_EXCL_STOP */
1186         }
1187
1188         return CALENDAR_ERROR_NONE;
1189 }
1190
1191 static gpointer _cal_server_alarm_main(gpointer user_data)
1192 {
1193         DBG("thread alarm: start");
1194
1195         int ret = 0;
1196         bool is_initialized = false;
1197
1198         while (1) {
1199                 g_mutex_lock(&_cal_server_alarm_mutex);
1200                 /*
1201                  * While syncing with contacts,
1202                  * because calendar-service could be stopped by on-demand,
1203                  * holding on-demand is needed.
1204                  */
1205                 cal_server_ondemand_hold();
1206
1207                 do {
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);
1213                                         break;
1214                                         /* LCOV_EXCL_STOP */
1215                                 }
1216                                 DBG("thread alarm: init");
1217                                 is_initialized = true;
1218                         }
1219
1220                         ret = cal_connect();
1221                         if (CALENDAR_ERROR_NONE != ret) {
1222                                 /* LCOV_EXCL_START */
1223                                 ERR("cal_connect() Fail(%d)", ret);
1224                                 break;
1225                                 /* LCOV_EXCL_STOP */
1226                         }
1227
1228                         cal_server_alarm_register_next_alarm(time(NULL));
1229                         cal_disconnect();
1230
1231                 } while (0);
1232
1233                 cal_server_ondemand_release();
1234                 cal_server_ondemand_start();
1235
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);
1241
1242                 if (server_killed)
1243                         break;
1244         }
1245         DBG("thread alarm: end");
1246         g_thread_exit(NULL);
1247
1248         return NULL;
1249 }
1250
1251 void cal_server_alarm_send_signal(void)
1252 {
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);
1257 }
1258
1259 void cal_server_alarm_start(void)
1260 {
1261         CAL_FN_CALL();
1262
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);
1268         }
1269         cal_server_alarm_send_signal();
1270 }
1271
1272 static void cal_server_alarm_deinit(void)
1273 {
1274         alarmmgr_fini();
1275         _cal_server_alarm_unset_inotify(_changed_cb);
1276         _cal_server_alarm_unset_timechange();
1277 }
1278
1279 void cal_server_alarm_end(void)
1280 {
1281         CAL_FN_CALL();
1282
1283         server_killed = true;
1284
1285         cal_server_alarm_deinit();
1286         cal_server_alarm_send_signal();
1287
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;
1292 }