Migrate from 2.4 code repo
[platform/core/context/context-service.git] / src / context_trigger / timer.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdlib.h>
18 #include <time.h>
19 #include <types_internal.h>
20 #include <scope_mutex.h>
21 #include <timer_mgr.h>
22 #include "timer.h"
23 #include "trigger.h"
24 #include "timer_types.h"
25
26 #define MAX_HOUR        24
27 #define MAX_DAY         7
28
29 using namespace ctx::timer_manager;
30 static GMutex timer_mutex;
31
32 ctx::trigger_timer::ref_count_array_s::ref_count_array_s()
33 {
34         memset(count, 0, sizeof(int) * MAX_DAY);
35 }
36
37 ctx::trigger_timer::trigger_timer(ctx::context_trigger* tr, std::string z)
38         : trigger(tr)
39         , zone(z)
40 {
41 }
42
43 ctx::trigger_timer::~trigger_timer()
44 {
45         clear();
46 }
47
48 int ctx::trigger_timer::merge_day_of_week(int* ref_cnt)
49 {
50         int day_of_week = 0;
51
52         for (int d = 0; d < MAX_DAY; ++d) {
53                 if (ref_cnt[d] > 0) {
54                         day_of_week |= (0x01 << d);
55                 }
56         }
57
58         return day_of_week;
59 }
60
61 bool ctx::trigger_timer::add(int minute, int day_of_week)
62 {
63         IF_FAIL_RETURN_TAG(minute >=0 && minute < 1440 &&
64                         day_of_week > 0 && day_of_week <= timer_manager::EVERYDAY,
65                         false, _E, "Invalid parameter");
66
67         ctx::scope_mutex sm(&timer_mutex);
68
69         ref_count_array_s &ref = ref_count_map[minute];
70
71         for (int d = 0; d < MAX_DAY; ++d) {
72                 if ((day_of_week & (0x01 << d)) != 0) {
73                         ref.count[d] += 1;
74                 }
75         }
76
77         return reset_timer(minute);
78 }
79
80 bool ctx::trigger_timer::remove(int minute, int day_of_week)
81 {
82         IF_FAIL_RETURN_TAG(minute >=0 && minute < 1440 &&
83                         day_of_week > 0 && day_of_week <= timer_manager::EVERYDAY,
84                         false, _E, "Invalid parameter");
85
86         ctx::scope_mutex sm(&timer_mutex);
87
88         ref_count_array_s &ref = ref_count_map[minute];
89
90         for (int d = 0; d < MAX_DAY; ++d) {
91                 if ((day_of_week & (0x01 << d)) != 0 && ref.count[d] > 0) {
92                         ref.count[d] -= 1;
93                 }
94         }
95
96         return reset_timer(minute);
97 }
98
99 bool ctx::trigger_timer::reset_timer(int minute)
100 {
101         int day_of_week = merge_day_of_week(ref_count_map[minute].count);
102         timer_state_s &timer = timer_state_map[minute];
103
104         if (day_of_week == timer.day_of_week) {
105                 /* Necessary timers are already running... */
106                 return true;
107         }
108
109         if (day_of_week == 0 && timer.timer_id > 0) {
110                 /* Turn off the timer at hour, if it is not necessray anymore. */
111                 timer_manager::remove(timer.timer_id);
112                 timer_state_map.erase(minute);
113                 ref_count_map.erase(minute);
114                 return true;
115         }
116
117         if (timer.timer_id > 0) {
118                 /* Turn off the current timer, to set a new one. */
119                 timer_manager::remove(timer.timer_id);
120                 timer.timer_id = -1;
121                 timer.day_of_week = 0;
122         }
123
124         /* Create a new timer, w.r.t. the new day_of_week value. */
125         int h = minute / 60;
126         int m = minute - h * 60;
127         int tid = timer_manager::set_at(h, m, day_of_week, this);
128         IF_FAIL_RETURN_TAG(tid > 0, false, _E, "Timer setting failed");
129
130         timer.timer_id = tid;
131         timer.day_of_week = day_of_week;
132
133         return true;
134 }
135
136 void ctx::trigger_timer::clear()
137 {
138         ctx::scope_mutex sm(&timer_mutex);
139
140         for (timer_state_map_t::iterator it = timer_state_map.begin(); it != timer_state_map.end(); ++it) {
141                 if (it->second.timer_id > 0) {
142                         timer_manager::remove(it->second.timer_id);
143                 }
144         }
145
146         timer_state_map.clear();
147         ref_count_map.clear();
148 }
149
150 bool ctx::trigger_timer::on_timer_expired(int timer_id, void* user_data)
151 {
152         time_t rawtime;
153         struct tm timeinfo;
154
155         time(&rawtime);
156         tzset();
157         localtime_r(&rawtime, &timeinfo);
158
159         int hour = timeinfo.tm_hour;
160         int min = timeinfo.tm_min;
161         int day_of_week = (0x01 << timeinfo.tm_wday);
162
163         on_timer_expired(hour, min, day_of_week);
164
165         return true;
166 }
167
168 void ctx::trigger_timer::on_timer_expired(int hour, int min, int day_of_week)
169 {
170         _I("[Timer-%s] Time: %02d:%02d, Day of Week: %#x", zone.c_str(), hour, min, day_of_week);
171
172         ctx::json result;
173         result.set(NULL, TIMER_RESPONSE_KEY_TIME_OF_DAY, hour * 60 + min);
174         result.set(NULL, TIMER_RESPONSE_KEY_DAY_OF_WEEK, convert_day_of_week_to_string(day_of_week));
175
176         ctx::json dummy = NULL;
177         trigger->push_fact(TIMER_EVENT_REQ_ID, ERR_NONE, TIMER_EVENT_SUBJECT, dummy, result, zone.c_str());
178 }
179
180 int ctx::trigger_timer::get_day_of_month()
181 {
182         time_t rawtime;
183         struct tm timeinfo;
184
185         time(&rawtime);
186         tzset();
187         localtime_r(&rawtime, &timeinfo);
188
189         int day_of_month = timeinfo.tm_mday;
190
191         return day_of_month;
192 }
193
194 std::string ctx::trigger_timer::get_day_of_week()
195 {
196         time_t rawtime;
197         struct tm timeinfo;
198
199         time(&rawtime);
200         tzset();
201         localtime_r(&rawtime, &timeinfo);
202
203         int day_of_week = (0x01 << timeinfo.tm_wday);
204
205         return convert_day_of_week_to_string(day_of_week);
206 }
207
208 int ctx::trigger_timer::get_minute_of_day()
209 {
210         time_t rawtime;
211         struct tm timeinfo;
212
213         time(&rawtime);
214         tzset();
215         localtime_r(&rawtime, &timeinfo);
216
217         int hour = timeinfo.tm_hour;
218         int minute = timeinfo.tm_min;
219
220         return hour * 60 + minute;
221 }
222
223 int ctx::trigger_timer::convert_string_to_day_of_week(std::string d)
224 {
225         int day = 0;
226         d = d.substr(1, d.length() - 2);
227
228         if (d.compare(TIMER_SUN) == 0) {
229                 day = SUN;
230         } else if (d.compare(TIMER_MON) == 0) {
231                 day = MON;
232         } else if (d.compare(TIMER_TUE) == 0) {
233                 day = TUE;
234         } else if (d.compare(TIMER_WED) == 0) {
235                 day = WED;
236         } else if (d.compare(TIMER_THU) == 0) {
237                 day = THU;
238         } else if (d.compare(TIMER_FRI) == 0) {
239                 day = FRI;
240         } else if (d.compare(TIMER_SAT) == 0) {
241                 day = SAT;
242         } else if (d.compare(TIMER_WEEKDAY) == 0) {
243                 day = WEEKDAY;
244         } else if (d.compare(TIMER_WEEKEND) == 0) {
245                 day = WEEKEND;
246         } else if (d.compare(TIMER_EVERYDAY) == 0) {
247                 day = EVERYDAY;
248         }
249
250         return day;
251 }
252
253 std::string ctx::trigger_timer::convert_day_of_week_to_string(int d)
254 {
255         std::string day;
256
257         if (d == SUN) {
258                 day = TIMER_SUN;
259         } else if (d == MON) {
260                 day = TIMER_MON;
261         } else if (d == TUE) {
262                 day = TIMER_TUE;
263         } else if (d == WED) {
264                 day = TIMER_WED;
265         } else if (d == THU) {
266                 day = TIMER_THU;
267         } else if (d == FRI) {
268                 day = TIMER_FRI;
269         } else if (d == SAT) {
270                 day = TIMER_SAT;
271         } else if (d == WEEKDAY) {
272                 day = TIMER_WEEKDAY;
273         } else if (d == WEEKEND) {
274                 day = TIMER_WEEKEND;
275         } else if (d == EVERYDAY) {
276                 day = TIMER_EVERYDAY;
277         }
278
279         return day;
280 }
281
282 bool ctx::trigger_timer::empty()
283 {
284         return timer_state_map.empty();
285 }