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 */
42 extern __alarm_server_context_t alarm_context;
43 extern GSList *g_scheduled_alarm_list;
46 extern bool enable_power_on_alarm;
49 static void __free_scheduled_alarm(gpointer data, gpointer user_data);
50 static time_t __alarm_next_duetime_once(__alarm_info_t *__alarm_info);
51 static time_t __alarm_next_duetime_repeat(__alarm_info_t *__alarm_info);
52 static time_t __alarm_next_duetime_annually(__alarm_info_t *__alarm_info);
53 static time_t __alarm_next_duetime_monthly(__alarm_info_t *__alarm_info);
54 static time_t __alarm_next_duetime_weekly(__alarm_info_t *__alarm_info);
55 static bool __find_next_alarm_to_be_scheduled(time_t *min_due_time);
58 static bool __find_next_alarm_to_be_scheduled_power_on(time_t *min_due_time);
59 bool _alarm_find_mintime_power_on(time_t *min_time);
61 bool _alarm_schedule(void);
63 static void __free_scheduled_alarm(gpointer data, gpointer user_data)
70 bool _clear_scheduled_alarm_list()
73 g_slist_foreach(g_scheduled_alarm_list, __free_scheduled_alarm, NULL);
74 g_slist_free(g_scheduled_alarm_list);
76 g_scheduled_alarm_list = NULL;
81 bool _init_scheduled_alarm_list()
83 _clear_scheduled_alarm_list();
88 bool _add_to_scheduled_alarm_list(__alarm_info_t *__alarm_info)
91 * 20080328. Sewook Park(sewook7.park@samsung.com)
92 * When multiple alarms are expired at same time, dbus rpc call for alarm
93 * ui should be invoked first.(Ui conflicting manager cannot manage the
94 * different kinds of alarm popups(wake up alarm/org alarm) correctly,
95 * when they are displayed at same time)So when arranging the schedule
96 * alarm list, wake up alarm element is located ahead.
102 __scheduled_alarm_t *alarm = NULL;
103 __scheduled_alarm_t *entry = NULL;
105 alarm = g_malloc(sizeof(__scheduled_alarm_t));
111 alarm->alarm_id = __alarm_info->alarm_id;
112 alarm->pid = __alarm_info->pid;
113 alarm->__alarm_info = __alarm_info;
115 ALARM_MGR_LOG_PRINT("%s :alarm->pid =%d, app_service_name=%s(%u)\n",
116 __FUNCTION__, alarm->pid,
117 g_quark_to_string(alarm->
118 __alarm_info->quark_app_service_name),
119 alarm->__alarm_info->quark_app_service_name);
121 if (alarm->__alarm_info->quark_app_service_name !=
122 g_quark_from_string(WAKEUP_ALARM_APP_ID)) {
123 g_scheduled_alarm_list =
124 g_slist_append(g_scheduled_alarm_list, alarm);
127 for (iter = g_scheduled_alarm_list; iter != NULL;
128 iter = g_slist_next(iter)) {
131 if (entry->__alarm_info->quark_app_service_name !=
132 g_quark_from_string(WAKEUP_ALARM_APP_ID)) {
139 g_scheduled_alarm_list =
140 g_slist_append(g_scheduled_alarm_list, alarm);
142 "appended : prior is %d\tcount is %d\n", prior,
145 g_scheduled_alarm_list =
146 g_slist_insert(g_scheduled_alarm_list, alarm,
149 "appended : prior is %d\tcount is %d\n", prior,
157 bool _remove_from_scheduled_alarm_list(int pid, alarm_id_t alarm_id)
161 __scheduled_alarm_t *alarm = NULL;
163 for (iter = g_scheduled_alarm_list; iter != NULL;
164 iter = g_slist_next(iter)) {
166 if (alarm->alarm_id == alarm_id) {
167 g_scheduled_alarm_list =
168 g_slist_remove(g_scheduled_alarm_list, iter->data);
169 /*g_free(iter->data); */
176 if (g_slist_length(g_scheduled_alarm_list) == 0) {
177 alarm_context.c_due_time = -1;
183 static time_t __alarm_next_duetime_once(__alarm_info_t *__alarm_info)
186 time_t current_time = 0;
187 struct tm duetime_tm;
190 alarm_info_t *alarm_info = &__alarm_info->alarm_info;
191 alarm_date_t *start = &alarm_info->start;
194 localtime_r(¤t_time, &duetime_tm);
195 wday = duetime_tm.tm_wday;
196 duetime_tm.tm_hour = start->hour;
197 duetime_tm.tm_min = start->min;
198 duetime_tm.tm_sec = start->sec;
200 if (start->year == 0 && start->month == 0 && start->day == 0)
202 due_time = mktime(&duetime_tm);
203 if (!(due_time > current_time)) {
204 due_time = due_time + 60 * 60 * 24;
206 } else /*specific date*/ {
207 duetime_tm.tm_year = start->year - 1900;
208 duetime_tm.tm_mon = start->month - 1;
209 duetime_tm.tm_mday = start->day;
210 due_time = mktime(&duetime_tm);
217 static time_t __alarm_next_duetime_repeat(__alarm_info_t *__alarm_info)
220 time_t current_time = 0;
221 struct tm duetime_tm;
223 alarm_info_t *alarm_info = &__alarm_info->alarm_info;
224 alarm_date_t *start = &alarm_info->start;
227 /*localtime_r(¤t_time, &duetime_tm); */
229 duetime_tm.tm_hour = start->hour;
230 duetime_tm.tm_min = start->min;
231 duetime_tm.tm_sec = start->sec;
233 duetime_tm.tm_year = start->year - 1900;
234 duetime_tm.tm_mon = start->month - 1;
235 duetime_tm.tm_mday = start->day;
237 due_time = mktime(&duetime_tm);
239 while (__alarm_info->start > due_time || current_time >= due_time) {
240 due_time += alarm_info->mode.u_interval.interval;
242 /* due_time = mktime(&duetime_tm); */
244 localtime_r(&due_time, &duetime_tm);
246 start->year = duetime_tm.tm_year + 1900;
247 start->month = duetime_tm.tm_mon + 1;
248 start->day = duetime_tm.tm_mday;
249 start->hour = duetime_tm.tm_hour;
250 start->min = duetime_tm.tm_min;
251 start->sec = duetime_tm.tm_sec;
257 static time_t __alarm_next_duetime_annually(__alarm_info_t *__alarm_info)
260 time_t current_time = 0;
261 struct tm duetime_tm;
264 alarm_info_t *alarm_info = &__alarm_info->alarm_info;
265 alarm_date_t *start = &alarm_info->start;
268 localtime_r(¤t_time, &duetime_tm);
269 wday = duetime_tm.tm_wday;
270 duetime_tm.tm_hour = start->hour;
271 duetime_tm.tm_min = start->min;
272 duetime_tm.tm_sec = start->sec;
274 if (start->year != 0) {
275 duetime_tm.tm_year = start->year - 1900;
278 duetime_tm.tm_mon = start->month - 1;
279 duetime_tm.tm_mday = start->day;
281 due_time = mktime(&duetime_tm);
283 while (__alarm_info->start > due_time || current_time > due_time) {
284 duetime_tm.tm_year += 1;
285 due_time = mktime(&duetime_tm);
292 static time_t __alarm_next_duetime_monthly(__alarm_info_t *__alarm_info)
295 time_t current_time = 0;
296 struct tm duetime_tm;
299 alarm_info_t *alarm_info = &__alarm_info->alarm_info;
300 alarm_date_t *start = &alarm_info->start;
303 localtime_r(¤t_time, &duetime_tm);
304 wday = duetime_tm.tm_wday;
305 duetime_tm.tm_hour = start->hour;
306 duetime_tm.tm_min = start->min;
307 duetime_tm.tm_sec = start->sec;
309 if (start->year != 0) {
310 duetime_tm.tm_year = start->year - 1900;
313 if (start->month != 0) {
315 duetime_tm.tm_mon = start->month - 1;
318 duetime_tm.tm_mday = start->day;
320 due_time = mktime(&duetime_tm);
322 while (__alarm_info->start > due_time || current_time > due_time) {
323 duetime_tm.tm_mon += 1;
324 if (duetime_tm.tm_mon == 12) {
325 duetime_tm.tm_mon = 0;
326 duetime_tm.tm_year += 1;
328 due_time = mktime(&duetime_tm);
335 static time_t __alarm_next_duetime_weekly(__alarm_info_t *__alarm_info)
338 time_t current_time = 0;
339 struct tm duetime_tm;
342 alarm_info_t *alarm_info = &__alarm_info->alarm_info;
343 alarm_date_t *start = &alarm_info->start;
345 alarm_mode_t *mode = &alarm_info->mode;
348 localtime_r(¤t_time, &duetime_tm);
349 wday = duetime_tm.tm_wday;
350 duetime_tm.tm_hour = start->hour;
351 duetime_tm.tm_min = start->min;
352 duetime_tm.tm_sec = start->sec;
354 if (__alarm_info->start != 0) {
356 if (__alarm_info->start >= current_time) /*case 1*/ {
357 duetime_tm.tm_year = start->year - 1900;
358 duetime_tm.tm_mon = start->month - 1;
359 duetime_tm.tm_mday = start->day;
361 /*don't need to be set */
366 due_time = mktime(&duetime_tm);
367 wday = duetime_tm.tm_wday;
369 /* CQ defect(72810) : only one time alarm function is not working
370 under all recurrence_disabled. */
371 if (due_time > current_time && mode->u_interval.day_of_week == 0)
374 if (current_time >= due_time
375 || !(mode->u_interval.day_of_week & 1 << wday)) {
386 while (!(mode->u_interval.day_of_week & 1 << day)
397 ALARM_MGR_LOG_PRINT("interval : %d\n", interval);
398 due_time += 60 * 60 * 24 * interval;
405 time_t _alarm_next_duetime(__alarm_info_t *__alarm_info)
408 time_t current_time = 0;
411 alarm_info_t *alarm_info = &__alarm_info->alarm_info;
412 alarm_mode_t *mode = &alarm_info->mode;
416 ALARM_MGR_LOG_PRINT("mode->repeat is %d\n", mode->repeat);
418 if (mode->repeat == ALARM_REPEAT_MODE_ONCE) {
419 due_time = __alarm_next_duetime_once(__alarm_info);
420 } else if (mode->repeat == ALARM_REPEAT_MODE_REPEAT) {
421 due_time = __alarm_next_duetime_repeat(__alarm_info);
422 } else if (mode->repeat == ALARM_REPEAT_MODE_ANNUALLY) {
423 due_time = __alarm_next_duetime_annually(__alarm_info);
424 } else if (mode->repeat == ALARM_REPEAT_MODE_MONTHLY) {
425 due_time = __alarm_next_duetime_monthly(__alarm_info);
426 } else if (mode->repeat == ALARM_REPEAT_MODE_WEEKLY) {
427 due_time = __alarm_next_duetime_weekly(__alarm_info);
429 ALARM_MGR_EXCEPTION_PRINT("repeat mode(%d) is wrong\n",
434 ALARM_MGR_LOG_PRINT("due_time %d\n", due_time);
436 if (__alarm_info->end != 0 && __alarm_info->end < due_time) {
437 ALARM_MGR_LOG_PRINT("due time > end time");
438 __alarm_info->due_time = 0;
441 __alarm_info->due_time = due_time;
447 static bool __find_next_alarm_to_be_scheduled(time_t *min_due_time)
450 time_t min_time = -1;
453 __alarm_info_t *entry = NULL;
457 for (iter = alarm_context.alarms; iter != NULL;
458 iter = g_slist_next(iter)) {
460 due_time = entry->due_time;
464 ALARM_MGR_LOG_PRINT("alarm[%d] with duetime(%u) at "
465 "current(%u) pid: (%d)\n",
466 entry->alarm_id, due_time, current_time, entry->pid);
467 if (due_time == 0) /*0 means this alarm
468 has been disabled*/ {
472 interval = difftime(due_time, current_time);
474 if (interval <= 0) /*2008.08.06 when the alarm expires,
475 it may makes an error.*/ {
476 ALARM_MGR_LOG_PRINT("this may be error.. alarm[%d]\n",
481 interval = difftime(due_time, min_time);
483 if ((interval < 0) || min_time == -1) {
489 *min_due_time = min_time;
495 static bool __find_next_alarm_to_be_scheduled_power_on(time_t *min_due_time)
498 time_t min_time = -1;
500 struct tm duetime_tm;
501 __alarm_info_t *entry = NULL;
502 struct tm *temp_info;
507 tzset(); /*for portability tzset() need to be called
508 before locatime_r,refer manpage localtime_r*/
509 temp_info = localtime_r(¤t_time, &duetime_tm);
511 if (temp_info != NULL)
513 ("__find_next_alarm_to_be_scheduled_power_on "
514 ": %d %d %d %d %d\n", temp_info->tm_year,
515 temp_info->tm_mon, temp_info->tm_mday, temp_info->tm_hour,
518 for (iter = alarm_context.alarms; iter != NULL;
519 iter = g_slist_next(iter)) {
521 due_time = entry->due_time;
525 ALARM_MGR_LOG_PRINT("%s\n", g_quark_to_string(
526 entry->quark_dst_service_name));
528 /*if(entry->quark_dst_service_name != g_quark_from_string
529 (WAKEUP_ALARM_APP_ID)) continue; */
532 (g_quark_to_string(entry->quark_dst_service_name),
533 WAKEUP_ALARM_APP_ID) != 0)
537 "alarm[%d] with duetime(%u) at current(%u)\n",
538 entry->alarm_id, due_time, current_time);
539 if (due_time == 0) /* 0 means this alarm has
544 interval = difftime(due_time, current_time);
546 if (interval <= 0) /*2008.08.06 when the alarm expires,
547 it may makes an error.*/ {
548 ALARM_MGR_LOG_PRINT("this may be error.. alarm[%d]\n",
553 interval = difftime(due_time, min_time);
555 if ((interval < 0) || min_time == -1) {
561 *min_due_time = min_time;
566 bool _alarm_schedule()
572 __alarm_info_t *entry = NULL;
580 __find_next_alarm_to_be_scheduled(&min_time);
582 if (min_time == -1) {
583 ALARM_MGR_LOG_PRINT("[alarm-server][schedule]: There is no "
584 "alarm to be scheduled..\n");
586 for (iter = alarm_context.alarms; iter != NULL;
587 iter = g_slist_next(iter)) {
589 due_time = entry->due_time;
591 if (due_time == min_time) {
592 _add_to_scheduled_alarm_list(entry);
597 _alarm_set_timer(&alarm_context, alarm_context.timer, min_time,
607 bool _alarm_find_mintime_power_on(time_t *min_time)
610 __find_next_alarm_to_be_scheduled_power_on(min_time);
612 if ((*min_time) == -1) {
613 ALARM_MGR_LOG_PRINT("[alarm-server][schedule]: There is no "
614 "alarm boot to be scheduled..\n");