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 "com.samsung.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 SECURE_LOGD("%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;
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;
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;
235 duetime_tm.tm_isdst = -1;
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;
263 alarm_info_t *alarm_info = &__alarm_info->alarm_info;
264 alarm_date_t *start = &alarm_info->start;
267 localtime_r(¤t_time, &duetime_tm);
268 duetime_tm.tm_hour = start->hour;
269 duetime_tm.tm_min = start->min;
270 duetime_tm.tm_sec = start->sec;
272 if (start->year != 0) {
273 duetime_tm.tm_year = start->year - 1900;
276 duetime_tm.tm_mon = start->month - 1;
277 duetime_tm.tm_mday = start->day;
279 due_time = mktime(&duetime_tm);
281 while (__alarm_info->start > due_time || current_time > due_time) {
282 duetime_tm.tm_year += 1;
283 due_time = mktime(&duetime_tm);
290 static time_t __alarm_next_duetime_monthly(__alarm_info_t *__alarm_info)
293 time_t current_time = 0;
294 struct tm duetime_tm;
296 alarm_info_t *alarm_info = &__alarm_info->alarm_info;
297 alarm_date_t *start = &alarm_info->start;
300 localtime_r(¤t_time, &duetime_tm);
301 duetime_tm.tm_hour = start->hour;
302 duetime_tm.tm_min = start->min;
303 duetime_tm.tm_sec = start->sec;
305 if (start->year != 0) {
306 duetime_tm.tm_year = start->year - 1900;
309 if (start->month != 0) {
311 duetime_tm.tm_mon = start->month - 1;
314 duetime_tm.tm_mday = start->day;
316 due_time = mktime(&duetime_tm);
318 while (__alarm_info->start > due_time || current_time > due_time) {
319 duetime_tm.tm_mon += 1;
320 if (duetime_tm.tm_mon == 12) {
321 duetime_tm.tm_mon = 0;
322 duetime_tm.tm_year += 1;
324 due_time = mktime(&duetime_tm);
331 static time_t __alarm_next_duetime_weekly(__alarm_info_t *__alarm_info)
334 time_t current_time = 0;
335 struct tm duetime_tm;
340 alarm_info_t *alarm_info = &__alarm_info->alarm_info;
341 alarm_date_t *start = &alarm_info->start;
343 alarm_mode_t *mode = &alarm_info->mode;
346 localtime_r(¤t_time, &duetime_tm);
347 wday = duetime_tm.tm_wday;
348 duetime_tm.tm_hour = start->hour;
349 duetime_tm.tm_min = start->min;
350 duetime_tm.tm_sec = start->sec;
351 current_dst = duetime_tm.tm_isdst;
352 duetime_tm.tm_isdst = -1;
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);
368 if( current_dst == 1 && due_time < current_time) {
369 duetime_tm.tm_isdst = 0;
370 due_time = mktime(&duetime_tm);
371 localtime_r(&due_time, &tmp_tm);
372 SECURE_LOGD("%d %d %d : %d", tmp_tm.tm_hour, tmp_tm.tm_min, tmp_tm.tm_sec, due_time);
373 if( tmp_tm.tm_hour != start->hour || tmp_tm.tm_min != start->min || tmp_tm.tm_sec != start->sec ) {
374 duetime_tm.tm_hour = start->hour;
375 duetime_tm.tm_min = start->min;
376 duetime_tm.tm_sec = start->sec;
377 duetime_tm.tm_isdst = -1;
378 due_time = mktime(&duetime_tm);
379 SECURE_LOGD("%d",due_time);
382 wday = duetime_tm.tm_wday;
383 SECURE_LOGD("current_time(%d) due_time(%d)", current_time, due_time);
385 /* CQ defect(72810) : only one time alarm function is not working
386 under all recurrence_disabled. */
387 if (due_time > current_time && mode->u_interval.day_of_week == 0)
390 if (current_time >= due_time
391 || !(mode->u_interval.day_of_week & 1 << wday)) {
400 while (!(mode->u_interval.day_of_week & 1 << day)
410 ALARM_MGR_LOG_PRINT("interval : %d\n", interval);
411 due_time += 60 * 60 * 24 * interval;
418 time_t _alarm_next_duetime(__alarm_info_t *__alarm_info)
421 time_t current_time = 0;
423 struct tm *cur_tm = NULL ;
424 struct tm *due_tm = NULL ;
426 alarm_info_t *alarm_info = &__alarm_info->alarm_info;
427 alarm_mode_t *mode = &alarm_info->mode;
430 cur_tm = localtime(¤t_time);
431 if (cur_tm->tm_isdst > 0)
434 ALARM_MGR_LOG_PRINT("mode->repeat is %d\n", mode->repeat);
436 if (mode->repeat == ALARM_REPEAT_MODE_ONCE) {
437 due_time = __alarm_next_duetime_once(__alarm_info);
438 } else if (mode->repeat == ALARM_REPEAT_MODE_REPEAT) {
439 due_time = __alarm_next_duetime_repeat(__alarm_info);
440 } else if (mode->repeat == ALARM_REPEAT_MODE_ANNUALLY) {
441 due_time = __alarm_next_duetime_annually(__alarm_info);
442 } else if (mode->repeat == ALARM_REPEAT_MODE_MONTHLY) {
443 due_time = __alarm_next_duetime_monthly(__alarm_info);
444 } else if (mode->repeat == ALARM_REPEAT_MODE_WEEKLY) {
445 due_time = __alarm_next_duetime_weekly(__alarm_info);
447 ALARM_MGR_EXCEPTION_PRINT("repeat mode(%d) is wrong\n",
452 if (mode->repeat != ALARM_REPEAT_MODE_WEEKLY) {
453 due_tm = localtime(&due_time);
454 if (is_dst==0 && due_tm->tm_isdst==1){
455 ALARM_MGR_LOG_PRINT("DST alarm found, enable\n");
456 due_tm->tm_hour = due_tm->tm_hour - DST_TIME_DIFF;
457 } else if (is_dst==1 && due_tm->tm_isdst==0){
458 ALARM_MGR_LOG_PRINT("DST alarm found. disable\n");
459 due_tm->tm_hour = due_tm->tm_hour + DST_TIME_DIFF;
461 due_time = mktime(due_tm);
464 ALARM_MGR_LOG_PRINT("due_time %d\n", due_time);
466 if (__alarm_info->end != 0 && __alarm_info->end < due_time) {
467 ALARM_MGR_LOG_PRINT("due time > end time");
468 __alarm_info->due_time = 0;
471 __alarm_info->due_time = due_time;
477 static bool __find_next_alarm_to_be_scheduled(time_t *min_due_time)
480 time_t min_time = -1;
483 __alarm_info_t *entry = NULL;
487 for (iter = alarm_context.alarms; iter != NULL;
488 iter = g_slist_next(iter)) {
490 due_time = entry->due_time;
494 SECURE_LOGD("alarm[%d] with duetime(%u) at current(%u) pid: (%d)\n",
495 entry->alarm_id, due_time, current_time, entry->pid);
496 if (due_time == 0) /*0 means this alarm
497 has been disabled*/ {
501 interval = difftime(due_time, current_time);
503 if (interval <= 0) /*2008.08.06 when the alarm expires,
504 it may makes an error.*/ {
505 ALARM_MGR_LOG_PRINT("this may be error.. alarm[%d]\n",
510 interval = difftime(due_time, min_time);
512 if ((interval < 0) || min_time == -1) {
518 *min_due_time = min_time;
524 static bool __find_next_alarm_to_be_scheduled_power_on(time_t *min_due_time)
527 time_t min_time = -1;
529 struct tm duetime_tm;
530 __alarm_info_t *entry = NULL;
531 struct tm *temp_info;
536 tzset(); /*for portability tzset() need to be called
537 before locatime_r,refer manpage localtime_r*/
538 temp_info = localtime_r(¤t_time, &duetime_tm);
540 if (temp_info != NULL)
542 ("__find_next_alarm_to_be_scheduled_power_on "
543 ": %d %d %d %d %d\n", temp_info->tm_year,
544 temp_info->tm_mon, temp_info->tm_mday, temp_info->tm_hour,
547 for (iter = alarm_context.alarms; iter != NULL;
548 iter = g_slist_next(iter)) {
550 due_time = entry->due_time;
554 SECURE_LOGD("%s\n", g_quark_to_string(
555 entry->quark_dst_service_name));
557 /*if(entry->quark_dst_service_name != g_quark_from_string
558 (WAKEUP_ALARM_APP_ID)) continue; */
561 (g_quark_to_string(entry->quark_dst_service_name),
562 WAKEUP_ALARM_APP_ID) != 0)
566 "alarm[%d] with duetime(%u) at current(%u)\n",
567 entry->alarm_id, due_time, current_time);
568 if (due_time == 0) /* 0 means this alarm has
573 interval = difftime(due_time, current_time);
575 if (interval <= 0) /*2008.08.06 when the alarm expires,
576 it may makes an error.*/ {
577 ALARM_MGR_LOG_PRINT("this may be error.. alarm[%d]\n",
582 interval = difftime(due_time, min_time);
584 if ((interval < 0) || min_time == -1) {
590 *min_due_time = min_time;
595 bool _alarm_schedule()
601 __alarm_info_t *entry = NULL;
609 __find_next_alarm_to_be_scheduled(&min_time);
611 if (min_time == -1) {
612 ALARM_MGR_LOG_PRINT("[alarm-server][schedule]: There is no "
613 "alarm to be scheduled..\n");
615 for (iter = alarm_context.alarms; iter != NULL;
616 iter = g_slist_next(iter)) {
618 due_time = entry->due_time;
620 if (due_time == min_time) {
621 _add_to_scheduled_alarm_list(entry);
626 _alarm_set_timer(&alarm_context, alarm_context.timer, min_time,
636 bool _alarm_find_mintime_power_on(time_t *min_time)
639 __find_next_alarm_to_be_scheduled_power_on(min_time);
641 if ((*min_time) == -1) {
642 ALARM_MGR_LOG_PRINT("[alarm-server][schedule]: There is no "
643 "alarm boot to be scheduled..\n");