4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Venkatesha Sarpangala <sarpangala.v@samsung.com>, Jayoun Lee <airjany@samsung.com>,
7 * Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
26 #define _BSD_SOURCE /*localtime_r requires */
38 #include"alarm-internal.h"
39 #define WAKEUP_ALARM_APP_ID "org.tizen.alarm.ALARM" /*alarm ui
40 application's alarm's dbus_service name instead of 21 value */
41 #define DST_TIME_DIFF 1
43 extern __alarm_server_context_t alarm_context;
44 extern GSList *g_scheduled_alarm_list;
47 extern bool enable_power_on_alarm;
50 static void __free_scheduled_alarm(gpointer data, gpointer user_data);
51 static time_t __alarm_next_duetime_once(__alarm_info_t *__alarm_info);
52 static time_t __alarm_next_duetime_repeat(__alarm_info_t *__alarm_info);
53 static time_t __alarm_next_duetime_annually(__alarm_info_t *__alarm_info);
54 static time_t __alarm_next_duetime_monthly(__alarm_info_t *__alarm_info);
55 static time_t __alarm_next_duetime_weekly(__alarm_info_t *__alarm_info);
56 static bool __find_next_alarm_to_be_scheduled(time_t *min_due_time);
59 static bool __find_next_alarm_to_be_scheduled_power_on(time_t *min_due_time);
60 bool _alarm_find_mintime_power_on(time_t *min_time);
62 bool _alarm_schedule(void);
64 static void __free_scheduled_alarm(gpointer data, gpointer user_data)
71 bool _clear_scheduled_alarm_list()
74 g_slist_foreach(g_scheduled_alarm_list, __free_scheduled_alarm, NULL);
75 g_slist_free(g_scheduled_alarm_list);
77 g_scheduled_alarm_list = NULL;
82 bool _init_scheduled_alarm_list()
84 _clear_scheduled_alarm_list();
89 bool _add_to_scheduled_alarm_list(__alarm_info_t *__alarm_info)
92 * 20080328. Sewook Park(sewook7.park@samsung.com)
93 * When multiple alarms are expired at same time, dbus rpc call for alarm
94 * ui should be invoked first.(Ui conflicting manager cannot manage the
95 * different kinds of alarm popups(wake up alarm/org alarm) correctly,
96 * when they are displayed at same time)So when arranging the schedule
97 * alarm list, wake up alarm element is located ahead.
103 __scheduled_alarm_t *alarm = NULL;
104 __scheduled_alarm_t *entry = NULL;
106 alarm = g_malloc(sizeof(__scheduled_alarm_t));
112 alarm->alarm_id = __alarm_info->alarm_id;
113 alarm->pid = __alarm_info->pid;
114 alarm->__alarm_info = __alarm_info;
116 ALARM_MGR_LOG_PRINT("%s :alarm->pid =%d, app_service_name=%s(%u)\n",
117 __FUNCTION__, alarm->pid,
118 g_quark_to_string(alarm->
119 __alarm_info->quark_app_service_name),
120 alarm->__alarm_info->quark_app_service_name);
122 if (alarm->__alarm_info->quark_app_service_name !=
123 g_quark_from_string(WAKEUP_ALARM_APP_ID)) {
124 g_scheduled_alarm_list =
125 g_slist_append(g_scheduled_alarm_list, alarm);
128 for (iter = g_scheduled_alarm_list; iter != NULL;
129 iter = g_slist_next(iter)) {
132 if (entry->__alarm_info->quark_app_service_name !=
133 g_quark_from_string(WAKEUP_ALARM_APP_ID)) {
140 g_scheduled_alarm_list =
141 g_slist_append(g_scheduled_alarm_list, alarm);
143 "appended : prior is %d\tcount is %d\n", prior,
146 g_scheduled_alarm_list =
147 g_slist_insert(g_scheduled_alarm_list, alarm,
150 "appended : prior is %d\tcount is %d\n", prior,
158 bool _remove_from_scheduled_alarm_list(int pid, alarm_id_t alarm_id)
162 __scheduled_alarm_t *alarm = NULL;
164 for (iter = g_scheduled_alarm_list; iter != NULL;
165 iter = g_slist_next(iter)) {
167 if (alarm->alarm_id == alarm_id) {
168 g_scheduled_alarm_list =
169 g_slist_remove(g_scheduled_alarm_list, iter->data);
170 /*g_free(iter->data); */
177 if (g_slist_length(g_scheduled_alarm_list) == 0) {
178 alarm_context.c_due_time = -1;
184 static time_t __alarm_next_duetime_once(__alarm_info_t *__alarm_info)
187 time_t current_time = 0;
188 struct tm duetime_tm;
190 alarm_info_t *alarm_info = &__alarm_info->alarm_info;
191 alarm_date_t *start = &alarm_info->start;
193 _alarm_time(¤t_time);
194 localtime_r(¤t_time, &duetime_tm);
195 duetime_tm.tm_hour = start->hour;
196 duetime_tm.tm_min = start->min;
197 duetime_tm.tm_sec = start->sec;
199 if (start->year == 0 && start->month == 0 && start->day == 0)
201 due_time = mktime(&duetime_tm);
202 if (!(due_time > current_time)) {
203 due_time = due_time + 60 * 60 * 24;
205 } else /*specific date*/ {
206 duetime_tm.tm_year = start->year - 1900;
207 duetime_tm.tm_mon = start->month - 1;
208 duetime_tm.tm_mday = start->day;
209 due_time = mktime(&duetime_tm);
216 static time_t __alarm_next_duetime_repeat(__alarm_info_t *__alarm_info)
219 time_t current_time = 0;
220 struct tm duetime_tm;
222 alarm_info_t *alarm_info = &__alarm_info->alarm_info;
223 alarm_date_t *start = &alarm_info->start;
225 _alarm_time(¤t_time);
226 /*localtime_r(¤t_time, &duetime_tm); */
228 duetime_tm.tm_hour = start->hour;
229 duetime_tm.tm_min = start->min;
230 duetime_tm.tm_sec = start->sec;
232 duetime_tm.tm_year = start->year - 1900;
233 duetime_tm.tm_mon = start->month - 1;
234 duetime_tm.tm_mday = start->day;
236 due_time = mktime(&duetime_tm);
238 while (__alarm_info->start > due_time || current_time >= due_time) {
239 due_time += alarm_info->mode.u_interval.interval;
241 /* due_time = mktime(&duetime_tm); */
243 localtime_r(&due_time, &duetime_tm);
245 start->year = duetime_tm.tm_year + 1900;
246 start->month = duetime_tm.tm_mon + 1;
247 start->day = duetime_tm.tm_mday;
248 start->hour = duetime_tm.tm_hour;
249 start->min = duetime_tm.tm_min;
250 start->sec = duetime_tm.tm_sec;
256 static time_t __alarm_next_duetime_annually(__alarm_info_t *__alarm_info)
259 time_t current_time = 0;
260 struct tm duetime_tm;
262 alarm_info_t *alarm_info = &__alarm_info->alarm_info;
263 alarm_date_t *start = &alarm_info->start;
265 _alarm_time(¤t_time);
266 localtime_r(¤t_time, &duetime_tm);
267 duetime_tm.tm_hour = start->hour;
268 duetime_tm.tm_min = start->min;
269 duetime_tm.tm_sec = start->sec;
271 if (start->year != 0) {
272 duetime_tm.tm_year = start->year - 1900;
275 duetime_tm.tm_mon = start->month - 1;
276 duetime_tm.tm_mday = start->day;
278 due_time = mktime(&duetime_tm);
280 while (__alarm_info->start > due_time || current_time > due_time) {
281 duetime_tm.tm_year += 1;
282 due_time = mktime(&duetime_tm);
289 static time_t __alarm_next_duetime_monthly(__alarm_info_t *__alarm_info)
292 time_t current_time = 0;
293 struct tm duetime_tm;
295 alarm_info_t *alarm_info = &__alarm_info->alarm_info;
296 alarm_date_t *start = &alarm_info->start;
298 _alarm_time(¤t_time);
299 localtime_r(¤t_time, &duetime_tm);
300 duetime_tm.tm_hour = start->hour;
301 duetime_tm.tm_min = start->min;
302 duetime_tm.tm_sec = start->sec;
304 if (start->year != 0) {
305 duetime_tm.tm_year = start->year - 1900;
308 if (start->month != 0) {
310 duetime_tm.tm_mon = start->month - 1;
313 duetime_tm.tm_mday = start->day;
315 due_time = mktime(&duetime_tm);
317 while (__alarm_info->start > due_time || current_time > due_time) {
318 duetime_tm.tm_mon += 1;
319 if (duetime_tm.tm_mon == 12) {
320 duetime_tm.tm_mon = 0;
321 duetime_tm.tm_year += 1;
323 due_time = mktime(&duetime_tm);
330 static time_t __alarm_next_duetime_weekly(__alarm_info_t *__alarm_info)
333 time_t current_time = 0;
334 struct tm duetime_tm;
337 alarm_info_t *alarm_info = &__alarm_info->alarm_info;
338 alarm_date_t *start = &alarm_info->start;
340 alarm_mode_t *mode = &alarm_info->mode;
342 _alarm_time(¤t_time);
343 localtime_r(¤t_time, &duetime_tm);
344 wday = duetime_tm.tm_wday;
345 duetime_tm.tm_hour = start->hour;
346 duetime_tm.tm_min = start->min;
347 duetime_tm.tm_sec = start->sec;
349 if (__alarm_info->start != 0) {
351 if (__alarm_info->start >= current_time) /*case 1*/ {
352 duetime_tm.tm_year = start->year - 1900;
353 duetime_tm.tm_mon = start->month - 1;
354 duetime_tm.tm_mday = start->day;
356 /*don't need to be set */
361 due_time = mktime(&duetime_tm);
362 wday = duetime_tm.tm_wday;
364 /* CQ defect(72810) : only one time alarm function is not working
365 under all recurrence_disabled. */
366 if (due_time > current_time && mode->u_interval.day_of_week == 0)
369 if (current_time >= due_time
370 || !(mode->u_interval.day_of_week & 1 << wday)) {
379 while (!(mode->u_interval.day_of_week & 1 << day)
389 ALARM_MGR_LOG_PRINT("interval : %d\n", interval);
390 due_time += 60 * 60 * 24 * interval;
397 time_t _alarm_next_duetime(__alarm_info_t *__alarm_info)
400 time_t current_time = 0;
402 struct tm *cur_tm = NULL ;
403 struct tm *due_tm = NULL ;
405 alarm_info_t *alarm_info = &__alarm_info->alarm_info;
406 alarm_mode_t *mode = &alarm_info->mode;
408 _alarm_time(¤t_time);
409 cur_tm = localtime(¤t_time);
410 if (cur_tm->tm_isdst > 0)
413 ALARM_MGR_LOG_PRINT("mode->repeat is %d\n", mode->repeat);
415 if (mode->repeat == ALARM_REPEAT_MODE_ONCE) {
416 due_time = __alarm_next_duetime_once(__alarm_info);
417 } else if (mode->repeat == ALARM_REPEAT_MODE_REPEAT) {
418 due_time = __alarm_next_duetime_repeat(__alarm_info);
419 } else if (mode->repeat == ALARM_REPEAT_MODE_ANNUALLY) {
420 due_time = __alarm_next_duetime_annually(__alarm_info);
421 } else if (mode->repeat == ALARM_REPEAT_MODE_MONTHLY) {
422 due_time = __alarm_next_duetime_monthly(__alarm_info);
423 } else if (mode->repeat == ALARM_REPEAT_MODE_WEEKLY) {
424 due_time = __alarm_next_duetime_weekly(__alarm_info);
426 ALARM_MGR_EXCEPTION_PRINT("repeat mode(%d) is wrong\n",
431 due_tm = localtime(&due_time);
432 if (is_dst==0 && due_tm->tm_isdst==1){
433 ALARM_MGR_LOG_PRINT("DST alarm found, enable\n");
434 due_tm->tm_hour = due_tm->tm_hour - DST_TIME_DIFF;
435 } else if (is_dst==1 && due_tm->tm_isdst==0){
436 ALARM_MGR_LOG_PRINT("DST alarm found. disable\n");
437 due_tm->tm_hour = due_tm->tm_hour + DST_TIME_DIFF;
439 due_time = mktime(due_tm);
441 ALARM_MGR_LOG_PRINT("due_time %d\n", due_time);
443 if (__alarm_info->end != 0 && __alarm_info->end < due_time) {
444 ALARM_MGR_LOG_PRINT("due time > end time");
445 __alarm_info->due_time = 0;
448 __alarm_info->due_time = due_time;
454 static bool __find_next_alarm_to_be_scheduled(time_t *min_due_time)
457 time_t min_time = -1;
460 __alarm_info_t *entry = NULL;
462 _alarm_time(¤t_time);
464 for (iter = alarm_context.alarms; iter != NULL;
465 iter = g_slist_next(iter)) {
467 due_time = entry->due_time;
471 ALARM_MGR_LOG_PRINT("alarm[%d] with duetime(%u) at "
472 "current(%u) pid: (%d)\n",
473 entry->alarm_id, due_time, current_time, entry->pid);
474 if (due_time == 0) /*0 means this alarm
475 has been disabled*/ {
479 interval = difftime(due_time, current_time);
481 if (interval <= 0) /*2008.08.06 when the alarm expires,
482 it may makes an error.*/ {
483 ALARM_MGR_LOG_PRINT("this may be error.. alarm[%d]\n",
488 interval = difftime(due_time, min_time);
490 if ((interval < 0) || min_time == -1) {
496 *min_due_time = min_time;
502 static bool __find_next_alarm_to_be_scheduled_power_on(time_t *min_due_time)
505 time_t min_time = -1;
507 struct tm duetime_tm;
508 __alarm_info_t *entry = NULL;
509 struct tm *temp_info;
512 _alarm_time(¤t_time);
514 tzset(); /*for portability tzset() need to be called
515 before locatime_r,refer manpage localtime_r*/
516 temp_info = localtime_r(¤t_time, &duetime_tm);
518 if (temp_info != NULL)
520 ("__find_next_alarm_to_be_scheduled_power_on "
521 ": %d %d %d %d %d\n", temp_info->tm_year,
522 temp_info->tm_mon, temp_info->tm_mday, temp_info->tm_hour,
525 for (iter = alarm_context.alarms; iter != NULL;
526 iter = g_slist_next(iter)) {
528 due_time = entry->due_time;
532 ALARM_MGR_LOG_PRINT("%s\n", g_quark_to_string(
533 entry->quark_dst_service_name));
535 /*if(entry->quark_dst_service_name != g_quark_from_string
536 (WAKEUP_ALARM_APP_ID)) continue; */
539 (g_quark_to_string(entry->quark_dst_service_name),
540 WAKEUP_ALARM_APP_ID) != 0)
544 "alarm[%d] with duetime(%u) at current(%u)\n",
545 entry->alarm_id, due_time, current_time);
546 if (due_time == 0) /* 0 means this alarm has
551 interval = difftime(due_time, current_time);
553 if (interval <= 0) /*2008.08.06 when the alarm expires,
554 it may makes an error.*/ {
555 ALARM_MGR_LOG_PRINT("this may be error.. alarm[%d]\n",
560 interval = difftime(due_time, min_time);
562 if ((interval < 0) || min_time == -1) {
568 *min_due_time = min_time;
573 bool _alarm_schedule()
579 __alarm_info_t *entry = NULL;
583 _alarm_time(¤t_time);
587 __find_next_alarm_to_be_scheduled(&min_time);
589 if (min_time == -1) {
590 ALARM_MGR_LOG_PRINT("[alarm-server][schedule]: There is no "
591 "alarm to be scheduled..\n");
593 for (iter = alarm_context.alarms; iter != NULL;
594 iter = g_slist_next(iter)) {
596 due_time = entry->due_time;
598 if (due_time == min_time) {
599 _add_to_scheduled_alarm_list(entry);
604 _alarm_set_timer(&alarm_context, alarm_context.timer, min_time,
614 bool _alarm_find_mintime_power_on(time_t *min_time)
617 __find_next_alarm_to_be_scheduled_power_on(min_time);
619 if ((*min_time) == -1) {
620 ALARM_MGR_LOG_PRINT("[alarm-server][schedule]: There is no "
621 "alarm boot to be scheduled..\n");