Merge "Coverity Issue fixes for Calendar" into tizen
[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         CAL_FN_CALL();
763         RET_IF(NULL == out_l);
764
765         tzset();
766         struct tm st_local = {0};
767         localtime_r(&utime, &st_local);
768
769         char datetime[CAL_STR_SHORT_LEN32] = {0};
770         snprintf(datetime, sizeof(datetime), CAL_FORMAT_LOCAL_DATETIME,
771                         st_local.tm_year +1900, st_local.tm_mon + 1, st_local.tm_mday,
772                         st_local.tm_hour, st_local.tm_min, st_local.tm_sec);
773         DBG("get alert to register with given time (%ld) datetime[%s]", utime, datetime);
774
775         GList *l = NULL;
776
777         _cal_server_alarm_get_upcoming_specific_utime(utime, get_all, &l);
778         _cal_server_alarm_get_upcoming_nonspecific_event_utime(utime, get_all, &l);
779         _cal_server_alarm_get_upcoming_nonspecific_todo_utime(utime, get_all, &l);
780
781         _cal_server_alarm_get_upcoming_specific_localtime(datetime, get_all, &l);
782         _cal_server_alarm_get_upcoming_nonspecific_event_localtime(datetime, get_all, &l);
783         _cal_server_alarm_get_upcoming_nonspecific_todo_localtime(datetime, get_all, &l);
784
785         *out_l = l;
786 }
787
788 static gint _cal_server_alarm_sort_cb(gconstpointer a, gconstpointer b)
789 {
790         struct _alarm_data_s *p1 = (struct _alarm_data_s *)a;
791         struct _alarm_data_s *p2 = (struct _alarm_data_s *)b;
792         DBG("%lld) > (%lld)", p1->alert_utime, p2->alert_utime);
793
794         return p1->alert_utime < p2->alert_utime ? -1 : 1;
795 }
796
797 static GFunc _cal_server_alarm_print_cb(gpointer data, gpointer user_data)
798 {
799         struct _alarm_data_s *ad = (struct _alarm_data_s *)data;
800         DBG("id(%d) unit(%d) tick(%d) type(%d) time(%lld) datetime[%s]",
801                         ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
802         return 0;
803 }
804
805 static int _cal_server_alarm_register(GList *alarm_list)
806 {
807         CAL_FN_CALL();
808         RETV_IF(NULL == alarm_list, CALENDAR_ERROR_INVALID_PARAMETER);
809
810         int ret = CALENDAR_ERROR_NONE;
811         GList *l = g_list_first(alarm_list);
812         RETV_IF(NULL == l, CALENDAR_ERROR_INVALID_PARAMETER);
813
814         struct _alarm_data_s *ad = (struct _alarm_data_s *)l->data;
815         RETVM_IF(NULL == ad, CALENDAR_ERROR_DB_FAILED, "No data");
816
817         /* clear all alarm which set by mine. */
818         ret = alarmmgr_enum_alarm_ids(_cal_server_alarm_clear_all_cb, NULL);
819         if (ret != ALARMMGR_RESULT_SUCCESS) {
820                 /* LCOV_EXCL_START */
821                 ERR("alarmmgr_enum_alarm_ids() Fail");
822                 return ret;
823                 /* LCOV_EXCL_STOP */
824         }
825
826         time_t mod_time = (time_t)ad->alert_utime;
827         alarm_entry_t *alarm_info = NULL;
828         alarm_info = alarmmgr_create_alarm();
829         if (NULL == alarm_info) {
830                 /* LCOV_EXCL_START */
831                 ERR("Failed to create alarm");
832                 return CALENDAR_ERROR_DB_FAILED;
833                 /* LCOV_EXCL_STOP */
834         }
835         tzset();
836         struct tm st_alarm = {0};
837
838         switch (ad->system_type) {
839         case CALENDAR_SYSTEM_EAST_ASIAN_LUNISOLAR:
840                 gmtime_r(&mod_time, &st_alarm);
841                 break;
842
843         default:
844                 tzset();
845                 localtime_r(&mod_time, &st_alarm);
846                 break;
847         }
848
849         alarm_date_t date = {0};
850         date.year = st_alarm.tm_year + 1900;
851         date.month = st_alarm.tm_mon + 1;
852         date.day = st_alarm.tm_mday;
853         date.hour = st_alarm.tm_hour;
854         date.min = st_alarm.tm_min;
855         date.sec = st_alarm.tm_sec;
856         alarmmgr_set_time(alarm_info, date);
857         DBG(COLOR_CYAN" >>> registered record id (%d) at %04d/%02d/%02d %02d:%02d:%02d "COLOR_END" (utime(%lld), datetime[%s], tick(%d) unit(%d))",
858                         ad->event_id, date.year, date.month, date.day, date.hour, date.min, date.sec,
859                         ad->time, ad->datetime, ad->tick, ad->unit);
860
861         int alarm_id = 0;
862         ret = alarmmgr_add_alarm_with_localtime(alarm_info, NULL, &alarm_id);
863         if (ret < 0) {
864                 /* LCOV_EXCL_START */
865                 ERR("alarmmgr_add_alarm_with_localtime Fail (%d)", ret);
866                 alarmmgr_free_alarm(alarm_info);
867                 return ret;
868                 /* LCOV_EXCL_STOP */
869         }
870         DBG("alarmmgr id (%d)", alarm_id);
871         _cal_server_alarm_update_alarm_id(alarm_id, ad->event_id, ad->tick, ad->unit);
872         alarmmgr_free_alarm(alarm_info);
873         return CALENDAR_ERROR_NONE;
874 }
875
876 static bool __app_matched_cb(app_control_h app_control, const char *package, void *user_data)
877 {
878         CAL_FN_CALL();
879
880         int ret = 0;
881         int i;
882
883         RETV_IF(NULL == user_data, true);
884
885         char *mime = NULL;
886         ret = app_control_get_mime(app_control, &mime);
887         RETVM_IF(APP_CONTROL_ERROR_NONE != ret, true, "app_control_get_mime() Fail(%d)", ret);
888
889         const char *reminder_mime = "application/x-tizen.calendar.reminder";
890         if (strncmp(mime, reminder_mime, strlen(reminder_mime))) { /* not same */
891                 DBG("get mime[%s] is not [%s]", mime, reminder_mime);
892                 free(mime);
893                 return true;
894         }
895         free(mime);
896
897         struct alarm_ud *au = (struct alarm_ud *)user_data;
898         GList *alarm_list = au->alarm_list;
899         if (NULL == alarm_list) {
900                 /* LCOV_EXCL_START */
901                 ERR("No list");
902                 return true;
903                 /* LCOV_EXCL_STOP */
904         }
905         int len = 0;
906         len = g_list_length(alarm_list);
907         if (0 == len) {
908                 DBG("len is 0, no alarm list");
909                 return true;
910         }
911
912         app_control_h ac = NULL;
913         ret = app_control_create(&ac);
914         if (APP_CONTROL_ERROR_NONE != ret) {
915                 /* LCOV_EXCL_START */
916                 ERR("app_control_create() Fail(%d)", ret);
917                 return true;
918                 /* LCOV_EXCL_STOP */
919         }
920         ret = app_control_set_operation(ac,  APP_CONTROL_OPERATION_DEFAULT);
921         if (APP_CONTROL_ERROR_NONE != ret) {
922                 /* LCOV_EXCL_START */
923                 ERR("app_control_create() Fail(%d)", ret);
924                 app_control_destroy(ac);
925                 return true;
926                 /* LCOV_EXCL_STOP */
927         }
928         ret = app_control_set_app_id(ac, package);
929         if (APP_CONTROL_ERROR_NONE != ret) {
930                 /* LCOV_EXCL_START */
931                 ERR("app_control_set_app_id() Fail(%d)", ret);
932                 app_control_destroy(ac);
933                 return true;
934                 /* LCOV_EXCL_STOP */
935         }
936
937         char **ids = NULL;
938         ids = calloc(len, sizeof(char *));
939         if (NULL == ids) {
940                 /* LCOV_EXCL_START */
941                 ERR("calloc() Fail");
942                 app_control_destroy(ac);
943                 return true;
944                 /* LCOV_EXCL_STOP */
945         }
946         GList *cursor = g_list_first(alarm_list);
947         for (i = 0; i < len; i++) {
948                 if (NULL == cursor) {
949                         ERR("cursor is NULL");
950                         break;
951                 }
952                 struct _alarm_data_s *ad = (struct _alarm_data_s *)cursor->data;
953                 if (NULL == ad) {
954                         WARN("No data");
955                         cursor = g_list_next(cursor);
956                         continue;
957                 }
958                 DBG("pkg[%s] time[%lld] tick[%d] unit[%d] record_type[%d]",
959                                 package, ad->time, ad->tick, ad->unit, ad->record);
960
961                 int slen = 0;
962                 char extra[CAL_STR_MIDDLE_LEN] = {0};
963                 slen = snprintf(extra, sizeof(extra), "%s=%d", "id", ad->event_id);
964                 slen += snprintf(extra+slen, sizeof(extra)-slen, "&%s=%lld", "time", ad->time);
965                 slen += snprintf(extra+slen, sizeof(extra)-slen, "&%s=%d", "tick", ad->tick);
966                 slen += snprintf(extra+slen, sizeof(extra)-slen, "&%s=%d", "unit", ad->unit);
967                 slen += snprintf(extra+slen, sizeof(extra)-slen, "&%s=%d", "type", ad->record);
968
969                 /*
970                  * key: id, value: id=4&time=123123&..
971                  */
972                 char buf_id[CAL_STR_MIDDLE_LEN] = {0};
973                 snprintf(buf_id, sizeof(buf_id), "%d", ad->event_id);
974                 app_control_add_extra_data(ac, buf_id, extra);
975                 DBG("value[%s] id[%s]", extra, buf_id);
976
977                 /* append ids */
978                 ids[i] = strdup(buf_id);
979
980                 cursor = g_list_next(cursor);
981         }
982         app_control_add_extra_data_array(ac, "ids", (const char **)ids, len);
983         app_control_send_launch_request(ac, NULL, NULL);
984         app_control_destroy(ac);
985
986         for (i = 0; i < len; i++) {
987                 free(ids[i]);
988                 ids[i] = NULL;
989         }
990         free(ids);
991
992         return true;
993 }
994
995 static void _cal_server_alarm_noti_with_control(GList *alarm_list)
996 {
997         CAL_FN_CALL();
998
999         int ret = 0;
1000         RETM_IF(NULL == alarm_list, "No alarm list");
1001
1002         app_control_h app_control = NULL;
1003         ret = app_control_create(&app_control);
1004         if (APP_CONTROL_ERROR_NONE != ret) {
1005                 /* LCOV_EXCL_START */
1006                 ERR("app_control_create() Fail(%d)", ret);
1007                 return;
1008                 /* LCOV_EXCL_STOP */
1009         }
1010         ret = app_control_set_operation(app_control, APP_CONTROL_OPERATION_VIEW);
1011         if (APP_CONTROL_ERROR_NONE != ret) {
1012                 /* LCOV_EXCL_START */
1013                 ERR("app_control_set_operation() Fail(%d)", ret);
1014                 app_control_destroy(app_control);
1015                 return;
1016                 /* LCOV_EXCL_STOP */
1017         }
1018         ret = app_control_set_mime(app_control, "application/x-tizen.calendar.reminder");
1019         if (APP_CONTROL_ERROR_NONE != ret) {
1020                 /* LCOV_EXCL_START */
1021                 ERR("app_control_set_mime() Fail(%d)", ret);
1022                 app_control_destroy(app_control);
1023                 return;
1024                 /* LCOV_EXCL_STOP */
1025         }
1026
1027         struct alarm_ud *au = calloc(1, sizeof(struct alarm_ud));
1028         if (NULL == au) {
1029                 /* LCOV_EXCL_START */
1030                 ERR("calloc() Fail");
1031                 app_control_destroy(app_control);
1032                 return;
1033                 /* LCOV_EXCL_STOP */
1034         }
1035         au->alarm_list = alarm_list;
1036         ret = app_control_foreach_app_matched(app_control, __app_matched_cb, au);
1037         if (APP_CONTROL_ERROR_NONE != ret) {
1038                 /* LCOV_EXCL_START */
1039                 ERR("app_control_foreach_app_matched() Fail(%d)", ret);
1040                 free(au);
1041                 app_control_destroy(app_control);
1042                 return;
1043                 /* LCOV_EXCL_STOP */
1044         }
1045         free(au);
1046         app_control_destroy(app_control);
1047 }
1048
1049 static void _cal_server_alarm_noti_with_callback(GList *alarm_list)
1050 {
1051         RETM_IF(NULL == alarm_list, "No alarm list");
1052
1053         GList *l = g_list_first(alarm_list);
1054         while (l) {
1055                 struct _alarm_data_s *ad = (struct _alarm_data_s *)l->data;
1056                 if (NULL == ad) {
1057                         WARN("No data");
1058                         l = g_list_next(l);
1059                         continue;
1060                 }
1061                 DBG("callback time[%lld] tick[%d] unit[%d] record_type[%d]",
1062                                 ad->time, ad->tick, ad->unit, ad->record);
1063
1064                 int len = 0;
1065                 char extra[CAL_STR_MIDDLE_LEN] = {0};
1066                 len = snprintf(extra, sizeof(extra), "%s=%d", "id", ad->event_id);
1067                 len += snprintf(extra+len, sizeof(extra)-len, "&%s=%lld", "time", ad->time);
1068                 len += snprintf(extra+len, sizeof(extra)-len, "&%s=%d", "tick", ad->tick);
1069                 len += snprintf(extra+len, sizeof(extra)-len, "&%s=%d", "unit", ad->unit);
1070                 len += snprintf(extra+len, sizeof(extra)-len, "&%s=%d", "type", ad->record);
1071                 cal_dbus_publish_reminder(len, extra);
1072
1073                 l = g_list_next(l);
1074         }
1075 }
1076
1077 static void cal_server_alarm_register_next_alarm(time_t utime)
1078 {
1079         CAL_FN_CALL();
1080
1081         GList *l = NULL;
1082         _cal_server_alarm_get_latest(utime, false, &l);
1083         if (NULL == l)
1084                 return;
1085
1086         l = g_list_sort(l, _cal_server_alarm_sort_cb);
1087         g_list_foreach(l, (GFunc)_cal_server_alarm_print_cb, NULL);
1088         _cal_server_alarm_register(l);
1089
1090         g_list_free_full(l, free);
1091 }
1092
1093 static void cal_server_alarm_alert(time_t tt_alert)
1094 {
1095         GList *l = NULL;
1096         _cal_server_alarm_get_latest(tt_alert, true, &l);
1097         if (NULL == l)
1098                 return;
1099
1100         _cal_server_alarm_noti_with_callback(l);
1101         _cal_server_alarm_noti_with_control(l);
1102         g_list_free_full(l, free);
1103 }
1104
1105 static int _alert_cb(alarm_id_t alarm_id, void *data)
1106 {
1107         CAL_FN_CALL();
1108         DBG("alarm_id (%d)", (int)alarm_id);
1109
1110         time_t tt_alert = 0;
1111         cal_server_alarm_get_alert_time(alarm_id, &tt_alert);
1112         cal_server_alarm_alert(tt_alert);
1113         cal_server_alarm_unset_alerted_alarmmgr_id(alarm_id);
1114         cal_server_alarm_start();
1115         return 0;
1116 }
1117
1118 static void _timechanged_cb(keynode_t *node, void *data)
1119 {
1120         cal_server_alarm_alert(time(NULL));
1121         cal_server_alarm_start();
1122 }
1123
1124 static void _cal_server_alarm_set_timechange(void)
1125 {
1126         vconf_notify_key_changed(VCONFKEY_SYSTEM_TIME_CHANGED, _timechanged_cb, NULL);
1127         vconf_notify_key_changed(VCONFKEY_TELEPHONY_NITZ_GMT, _timechanged_cb, NULL);
1128         vconf_notify_key_changed(VCONFKEY_TELEPHONY_NITZ_ZONE, _timechanged_cb, NULL);
1129         vconf_notify_key_changed(VCONFKEY_TELEPHONY_NITZ_EVENT_GMT, _timechanged_cb, NULL);
1130 }
1131
1132 static void _cal_server_alarm_unset_timechange(void)
1133 {
1134         vconf_ignore_key_changed(VCONFKEY_SYSTEM_TIME_CHANGED, _timechanged_cb);
1135         vconf_ignore_key_changed(VCONFKEY_TELEPHONY_NITZ_GMT, _timechanged_cb);
1136         vconf_ignore_key_changed(VCONFKEY_TELEPHONY_NITZ_ZONE, _timechanged_cb);
1137         vconf_ignore_key_changed(VCONFKEY_TELEPHONY_NITZ_EVENT_GMT, _timechanged_cb);
1138 }
1139
1140 static void _changed_cb(const char* view_uri, void* data)
1141 {
1142         DBG("Receive alarm change signal");
1143         cal_server_alarm_start();
1144 }
1145
1146 static int _cal_server_alarm_set_inotify(calendar_db_changed_cb callback)
1147 {
1148         cal_inotify_subscribe(CAL_NOTI_TYPE_EVENT, CAL_NOTI_FILE_EVENT, callback, NULL);
1149         cal_inotify_subscribe(CAL_NOTI_TYPE_TODO, CAL_NOTI_FILE_TODO, callback, NULL);
1150         return 0;
1151 }
1152
1153 static void _cal_server_alarm_unset_inotify(calendar_db_changed_cb callback)
1154 {
1155         cal_inotify_unsubscribe(CAL_NOTI_FILE_EVENT, callback, NULL);
1156         cal_inotify_unsubscribe(CAL_NOTI_FILE_TODO, callback, NULL);
1157 }
1158
1159 static int cal_server_alarm_init(void)
1160 {
1161         int ret = 0;
1162
1163         _cal_server_alarm_set_timechange();
1164         _cal_server_alarm_set_inotify(_changed_cb);
1165
1166         ret = alarmmgr_set_cb(_alert_cb, NULL);
1167         if (ret < 0) {
1168                 /* LCOV_EXCL_START */
1169                 ERR("alarmmgr_set_cb() Fail(%d)", ret);
1170                 return CALENDAR_ERROR_SYSTEM;
1171                 /* LCOV_EXCL_STOP */
1172         }
1173
1174         ret = alarmmgr_init("calendar-service");
1175         if (ret < 0) {
1176                 /* LCOV_EXCL_START */
1177                 ERR("alarmmgr_init() Fail(%d)", ret);
1178                 return CALENDAR_ERROR_SYSTEM;
1179                 /* LCOV_EXCL_STOP */
1180         }
1181
1182         return CALENDAR_ERROR_NONE;
1183 }
1184
1185 static gpointer _cal_server_alarm_main(gpointer user_data)
1186 {
1187         DBG("thread alarm: start");
1188
1189         int ret = 0;
1190         bool is_initialized = false;
1191
1192         while (1) {
1193                 g_mutex_lock(&_cal_server_alarm_mutex);
1194                 /*
1195                  * While syncing with contacts,
1196                  * because calendar-service could be stopped by on-demand,
1197                  * holding on-demand is needed.
1198                  */
1199                 cal_server_ondemand_hold();
1200
1201                 do {
1202                         if (false == is_initialized) {
1203                                 ret = cal_server_alarm_init();
1204                                 if (CALENDAR_ERROR_NONE != ret) {
1205                                         /* LCOV_EXCL_START */
1206                                         ERR("cal_server_alarm_init() Fail(%d)", ret);
1207                                         break;
1208                                         /* LCOV_EXCL_STOP */
1209                                 }
1210                                 DBG("thread alarm: init");
1211                                 is_initialized = true;
1212                         }
1213
1214                         ret = cal_connect();
1215                         if (CALENDAR_ERROR_NONE != ret) {
1216                                 /* LCOV_EXCL_START */
1217                                 ERR("cal_connect() Fail(%d)", ret);
1218                                 break;
1219                                 /* LCOV_EXCL_STOP */
1220                         }
1221
1222                         cal_server_alarm_register_next_alarm(time(NULL));
1223                         cal_disconnect();
1224
1225                 } while (0);
1226
1227                 cal_server_ondemand_release();
1228                 cal_server_ondemand_start();
1229
1230                 DBG("thread alarm: wait");
1231                 while (false == signal_called)
1232                         g_cond_wait(&_cal_server_alarm_cond, &_cal_server_alarm_mutex);
1233                 signal_called = false;
1234                 g_mutex_unlock(&_cal_server_alarm_mutex);
1235
1236                 if (server_killed)
1237                         break;
1238         }
1239         DBG("thread alarm: end");
1240         g_thread_exit(NULL);
1241
1242         return NULL;
1243 }
1244
1245 void cal_server_alarm_send_signal(void)
1246 {
1247         g_mutex_lock(&_cal_server_alarm_mutex);
1248         signal_called = true;
1249         g_cond_signal(&_cal_server_alarm_cond);
1250         g_mutex_unlock(&_cal_server_alarm_mutex);
1251 }
1252
1253 void cal_server_alarm_start(void)
1254 {
1255         CAL_FN_CALL();
1256
1257         if (NULL == _cal_server_alarm_thread) {
1258                 g_mutex_init(&_cal_server_alarm_mutex);
1259                 g_cond_init(&_cal_server_alarm_cond);
1260                 _cal_server_alarm_thread = g_thread_new(CAL_SERVER_ALARM_THREAD_NAME,
1261                                 _cal_server_alarm_main, NULL);
1262         }
1263         cal_server_alarm_send_signal();
1264 }
1265
1266 static void cal_server_alarm_deinit(void)
1267 {
1268         alarmmgr_fini();
1269         _cal_server_alarm_unset_inotify(_changed_cb);
1270         _cal_server_alarm_unset_timechange();
1271 }
1272
1273 void cal_server_alarm_end(void)
1274 {
1275         CAL_FN_CALL();
1276
1277         server_killed = true;
1278
1279         cal_server_alarm_deinit();
1280         cal_server_alarm_send_signal();
1281
1282         g_cond_clear(&_cal_server_alarm_cond);
1283         g_thread_join(_cal_server_alarm_thread);
1284         g_thread_unref(_cal_server_alarm_thread);
1285         _cal_server_alarm_thread = NULL;
1286 }