Merge "Fix alarm setting on the listener" into tizen_2.1
[platform/framework/native/appfw.git] / src / system / FSys_AlarmManager.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /**
19  * @file                FSys_AlarmManager.cpp
20  * @brief               This is the implementation file for _AlarmManager class.
21  */
22
23 #include <unique_ptr.h>
24 #include <appfw/app.h>
25 #include <alarm.h>
26 #include <appsvc/appsvc.h>
27
28 #include <FBaseSysLog.h>
29 #include <FSysSystemTime.h>
30
31 #include <FBase_NativeError.h>
32 #include <FAppApp.h>
33 #include <FBase_StringConverter.h>
34
35 #include "inc/FSys_AlarmManager.h"
36
37 using namespace Tizen::Base;
38 using namespace Tizen::Base::Runtime;
39 using namespace Tizen::Base::Collection;
40 using namespace Tizen::Io;
41
42 namespace Tizen { namespace System
43 {
44 static const long _SECOND_OF_MINUTE = 60;
45
46 _AlarmManager* _AlarmManager::pAlarmManager = null;
47
48 _AlarmManager::_AlarmManager()
49         : __pAlarmHashMap(null)
50 {
51         result r = E_SUCCESS;
52         __alarmList.Construct();
53
54         if (!__pAlarmHashMap)
55         {
56                 __pAlarmHashMap = new (std::nothrow) MultiHashMap();
57                 SysTryCatch(NID_SYS, __pAlarmHashMap != null, r = E_SYSTEM, E_SYSTEM, "__pAlarmHashMap should not be null");
58
59                 r = __pAlarmHashMap->Construct();
60                 SysTryCatch(NID_SYS, r == E_SUCCESS, r= E_SYSTEM, E_SYSTEM, "[%s] Propagated.", GetErrorMessage(r));
61         }
62
63         //Checks for any alarm existence
64         alarm_cancel_all();
65
66 CATCH:
67         SetLastResult(r);
68 }
69
70 _AlarmManager::~_AlarmManager()
71 {
72         delete __pAlarmHashMap;
73         __pAlarmHashMap = null;
74
75         //Cancel all the alarms before exiting
76         alarm_cancel_all();
77 }
78
79 _AlarmManager*
80 _AlarmManager::GetInstance(void)
81 {
82         if(pAlarmManager == null)
83         {
84                 pAlarmManager = new (std::nothrow) _AlarmManager();
85         }
86         return pAlarmManager;
87 }
88
89 int
90 _AlarmManager::ReserveAlarm(Tizen::Base::String appId, Tizen::Base::DateTime startTime, int period)
91 {
92         int reservedAlarmId = -1;
93         result r = E_SUCCESS;
94
95         int ret = 0;
96         service_h service;
97
98         SysLog(NID_SYS, "Reserve time is %d/%d/%d %d:%d:%d", startTime.GetYear(), startTime.GetMonth(), startTime.GetDay(), startTime.GetHour(), startTime.GetMinute(), startTime.GetSecond());
99
100         bundle* pBundle = null;
101         alarm_entry_t* pAlarmInfo;
102         alarm_date_t expireTime = {0,};
103
104         std::unique_ptr<char[]> pId(_StringConverter::CopyToCharArrayN(appId));
105
106         pBundle = bundle_create();
107         SysTryCatch(NID_SYS, pBundle != null, r = E_SYSTEM, r, "It is failed to create bundle");
108
109         ret = appsvc_set_operation(pBundle,"osp.operation.ALARM");
110         SysTryCatch(NID_SYS, ret == SERVICE_ERROR_NONE, r = E_SYSTEM, r, "It is failed to set operation");
111
112         ret = appsvc_set_appid(pBundle, (const char*)(pId.get()));
113         SysTryCatch(NID_SYS, ret == SERVICE_ERROR_NONE, r = E_SYSTEM, r, "It is failed to set appid for %ls", appId.GetPointer());
114
115         pAlarmInfo = alarmmgr_create_alarm();
116         SysTryCatch(NID_SYS, pAlarmInfo != null, r = E_SYSTEM, r, "It is failed to create alarm entry");
117
118         expireTime.year = startTime.GetYear();
119         expireTime.month = startTime.GetMonth();
120         expireTime.day = startTime.GetDay();
121         expireTime.hour = startTime.GetHour();
122         expireTime.min = startTime.GetMinute();
123         expireTime.sec = startTime.GetSecond();
124
125         ret = alarmmgr_set_time(pAlarmInfo, expireTime);
126         SysTryCatch(NID_SYS, ret == ALARMMGR_RESULT_SUCCESS, r = E_SYSTEM, r, "It is failed to set new alarm time");
127
128         if(period > 0)
129         {
130                 ret = alarmmgr_set_repeat_mode(pAlarmInfo, ALARM_REPEAT_MODE_REPEAT, period * _SECOND_OF_MINUTE);
131                 SysTryCatch(NID_SYS, ret == ALARMMGR_RESULT_SUCCESS, r = E_SYSTEM, r, "It is failed to set repeat mode");
132         }
133
134         ret = alarmmgr_set_type(pAlarmInfo, 0x04/*ALARM_TYPE_NOLAUNCH*/);
135         SysTryCatch(NID_SYS, ret == ALARMMGR_RESULT_SUCCESS, r = E_SYSTEM, r, "It is failed to set repeat mode");
136
137         ret = alarmmgr_add_alarm_appsvc_with_localtime(pAlarmInfo,(void *)pBundle, &reservedAlarmId);
138         SysTryCatch(NID_SYS, ret == ALARMMGR_RESULT_SUCCESS, r = E_SYSTEM, r, "Alarm creation failed!!! Alrmgr error code is %d", ret);
139
140 CATCH:
141         if(r == E_SYSTEM)
142         {
143                 reservedAlarmId = -1;
144         }
145         if(pAlarmInfo != null)
146         {
147                 alarmmgr_free_alarm(pAlarmInfo);
148         }
149
150         if(pBundle != null)
151         {
152                 bundle_free(pBundle);
153         }
154
155         return reservedAlarmId;
156 }
157
158 result
159 _AlarmManager::AddAlarmList(int alarmId, int period, String appId, DateTime* endTime)
160 {
161         result r = E_SUCCESS;
162
163         SysTryReturnResult(NID_SYS, __pAlarmHashMap != null, E_SYSTEM, "Alarm list does not initialized");
164         SysLog(NID_SYS, "New Alarm Id is added (%d, %d, %ls)", alarmId, period, appId.GetPointer());
165
166         Integer* reservedAlarmId = null;
167         Integer* alarmPeriod = null;
168         String* alarmAppId = null;
169
170         Integer* reverseAlarmId = null;
171         String* reverseAppId = null;
172
173         reservedAlarmId = new (std::nothrow) Integer(alarmId);
174         SysTryCatch(NID_SYS, reservedAlarmId != null, r = E_SYSTEM, E_SYSTEM, "reservedAlarmId should not be null");
175
176         alarmPeriod = new (std::nothrow) Integer(period);
177         SysTryCatch(NID_SYS, alarmPeriod != null, r = E_SYSTEM, E_SYSTEM, "alarmPeriod should not be null");
178
179         alarmAppId = new (std::nothrow) String(appId);
180         SysTryCatch(NID_SYS, alarmAppId != null, r = E_SYSTEM, E_SYSTEM, "alarmAppId should not be null");
181
182         //Forward
183         r = __pAlarmHashMap->Add(*reservedAlarmId, *alarmAppId);
184         SysTryCatch(NID_SYS, r == E_SUCCESS, r, r, "Fail to add new alarm app id on the alarm list");
185
186         r = __pAlarmHashMap->Add(*reservedAlarmId, *alarmPeriod);
187         SysTryCatch(NID_SYS, r == E_SUCCESS, r, r, "Fail to add new alarm period on the alarm list");
188
189         if(endTime != null)
190         {
191                 DateTime* alarmEndTime = new DateTime(*endTime);
192
193                 SysLog(NID_SYS, "Endtime exists %d:%d:%d", alarmEndTime->GetHour(), alarmEndTime->GetMinute(), alarmEndTime->GetSecond());
194                 r = __pAlarmHashMap->Add(*reservedAlarmId, *alarmEndTime);
195                 SysTryCatch(NID_SYS, r == E_SUCCESS, r, r, "Fail to add new alarm endtime on the alarm list");
196         }
197
198         //Reverse
199         reverseAlarmId = new (std::nothrow) Integer(alarmId);
200         SysTryCatch(NID_SYS, reverseAlarmId != null, r = E_SYSTEM, E_SYSTEM, "reverseAlarmId should not be null");
201
202         reverseAppId = new (std::nothrow) String(appId);
203         SysTryCatch(NID_SYS, reverseAppId != null, r = E_SYSTEM, E_SYSTEM, "reverseAppId should not be null");
204
205         r = __pAlarmHashMap->Add(*reverseAppId, *reverseAlarmId);
206         SysTryCatch(NID_SYS, r == E_SUCCESS, r, r, "Fail to add new alarm on the alarm list");
207
208 CATCH:
209         if(r != E_SUCCESS)
210         {
211                 if(reservedAlarmId != null)
212                 {
213                         __pAlarmHashMap->Remove(*reservedAlarmId, false);
214                         delete reservedAlarmId;
215                 }
216
217                 if(alarmPeriod != null)
218                 {
219                         delete alarmPeriod;
220                 }
221
222                 if(alarmAppId != null)
223                 {
224                         delete alarmAppId;
225                 }
226
227                 if(reverseAppId != null)
228                 {
229                         __pAlarmHashMap->Remove(*reverseAppId, false);
230                         delete reverseAppId;
231                 }
232
233                 if(reverseAlarmId != null)
234                 {
235                         delete reverseAlarmId;
236                 }
237         }
238         return r;
239 }
240
241 result
242 _AlarmManager::RemoveAlarmList(int alarmId)
243 {
244         result r = E_SUCCESS;
245         Integer requiredAlarmId(alarmId);
246         std::unique_ptr<IEnumerator>pValueEnum(null);
247
248         SysTryReturnResult(NID_SYS, __pAlarmHashMap != null, E_SYSTEM, "Alarm list does not initialized");
249
250         alarm_cancel(alarmId);
251         SysLog(NID_SYS, "AlarmId %d disarms the timer.", alarmId);
252
253         pValueEnum.reset(__pAlarmHashMap->GetValuesN(requiredAlarmId));
254
255         if(pValueEnum != null)
256         {
257                 SysLog(NID_SYS, "Reserved Alarms are exist");
258                 String* alarmAppId = null;
259                 r = pValueEnum->MoveNext();
260                 SysTryReturnResult(NID_SYS, r == E_SUCCESS, E_SYSTEM, "Reserved Alarm List is not valid.");
261                 alarmAppId = static_cast< String* >(pValueEnum->GetCurrent());
262
263                 if(alarmAppId != null)
264                 {
265                         SysLog(NID_SYS, "Alarm AppId is %S", alarmAppId->GetPointer());
266                         std::unique_ptr<IEnumerator>pAlarmEnum(__pAlarmHashMap->GetValuesN(*alarmAppId));
267                         if(pAlarmEnum != null)
268                         {
269                                 while(pAlarmEnum->MoveNext() == E_SUCCESS)
270                                 {
271                                         Integer* reverseAlarmId = static_cast< Integer* >(pAlarmEnum->GetCurrent());
272                                         if(reverseAlarmId != null)
273                                         {
274                                                 SysLog(NID_SYS, "Reserved Alarm is %d", reverseAlarmId->ToInt());
275                                                 if(reverseAlarmId->ToInt() == alarmId)
276                                                 {
277                                                         SysLog(NID_SYS, "Remove reservedAlarmId for reverse look-up");
278                                                          __pAlarmHashMap->Remove(*alarmAppId, *reverseAlarmId);
279                                                         delete reverseAlarmId;
280                                                         break;
281                                                 }
282                                         }
283                                 }
284                         }
285
286                         int count = 0;
287                         __pAlarmHashMap->GetCount(*alarmAppId, count);
288                         if(count == 0)
289                         {
290                                 SysLog(NID_SYS, "There is no more reserved alarm for AppId:%S", alarmAppId->GetPointer());
291                                 __pAlarmHashMap->Remove(*alarmAppId, true);
292                         }
293                 }
294         }
295         r = __pAlarmHashMap->Remove(requiredAlarmId, true);
296
297         return r;
298 }
299
300 result
301 _AlarmManager::RemoveAlarmList(String appId)
302 {
303         result r = E_SUCCESS;
304         Integer requiredAlarmId;
305         IEnumerator *pValueEnum = null;
306
307         SysTryReturnResult(NID_SYS, __pAlarmHashMap != null, E_SYSTEM, "Alarm list does not initialized");
308         pValueEnum = __pAlarmHashMap->GetValuesN(appId);
309
310         if(pValueEnum != null)
311         {
312                 SysLog(NID_SYS, "Reserved Alarms are exist for AppId:%S", appId.GetPointer());
313                 while(pValueEnum->MoveNext() == E_SUCCESS)
314                 {
315                         Integer* reverseAlarmId = static_cast< Integer* >(pValueEnum->GetCurrent());
316                         if(reverseAlarmId != null)
317                         {
318                                 SysLog(NID_SYS, "Reserved AlarmId is %d", reverseAlarmId->ToInt());
319                                 alarm_cancel(reverseAlarmId->ToInt());
320                                 __pAlarmHashMap->Remove(*reverseAlarmId, true);
321                         }
322                 }
323                 delete pValueEnum;
324         }
325         r = __pAlarmHashMap->Remove(appId, true);
326
327         return r;
328 }
329
330 result
331 _AlarmManager::RegisterAlarm(_AlarmImpl* pAlarmImpl)
332 {
333         SysTryReturnResult(NID_SYS, pAlarmImpl != null, E_INVALID_ARG, "There is no alarmImpl.");
334         Integer alarmId(pAlarmImpl->__alarmId.value);
335         SysTryReturnResult(NID_SYS, __alarmList.ContainsKey(alarmId) == false, E_OBJ_ALREADY_EXIST, "Required Alarm[%d] is already registered.", pAlarmImpl->__alarmId.value);
336
337         result r = E_SUCCESS;
338         ArrayList requestMessage;
339         ArrayList responseMessage;
340
341         String startTimeStr;
342         String periodStr;
343         String endTimeStr;
344         String appId;
345
346         int period = pAlarmImpl->GetPeriod();
347  
348         DateTime currentTime;
349         DateTime startTime = pAlarmImpl->GetStartTime();
350         const DateTime* pEndTime = pAlarmImpl->GetEndTime();
351         DateTime endTime;
352
353         //Argument check
354         startTime.AddMilliseconds(-1 * startTime.GetMillisecond());
355         r = SystemTime::GetCurrentTime(WALL_TIME, currentTime);
356         currentTime.AddMilliseconds(-1 * currentTime.GetMillisecond());
357
358         SysTryReturnResult(NID_SYS, r == E_SUCCESS, E_SYSTEM, "It is failed to get current time.");
359         SysTryReturnResult(NID_SYS, DateTime::Compare(currentTime, startTime) < 0, E_INVALID_ARG, "Designated start time has to be greater than current time.");
360         SysTryReturnResult(NID_SYS, period > -1, E_INVALID_ARG, "Period has to greater than -1");
361
362         if(pEndTime != null)
363         {
364                 endTime = *pEndTime;
365                 endTime.AddMilliseconds(-1 * endTime.GetMillisecond());
366
367                 SysTryReturnResult(NID_SYS, DateTime::Compare(startTime, endTime) < 0, E_INVALID_ARG, "Designated end time is less than start time.");
368         }
369         //End Alarm validation check
370
371         Tizen::App::App* pApp = Tizen::App::App::GetInstance();
372         SysTryReturnResult(NID_SYS, pApp != null, E_SYSTEM, "[%s] A system error has been occurred. App::GetInstance() failed.", GetErrorMessage(E_SYSTEM));
373         appId = pApp->GetAppId();
374
375         String* result = null;
376         int reservedAlarmId = 0;
377
378         SysLog(NID_SYS, "Alarm setting request");
379
380         reservedAlarmId = ReserveAlarm(appId, startTime, period);
381         SysTryReturnResult(NID_SYS, reservedAlarmId != -1, E_SYSTEM, "It is failed to register alarm.");
382
383         SysLog(NID_SYS, "Reserved AppId %ls, alarmId: %d", appId.GetPointer(), reservedAlarmId);
384
385         if(pEndTime == null)
386         {
387                 r = AddAlarmList(reservedAlarmId, period, appId, null);
388         }
389         else
390         {
391                 r = AddAlarmList(reservedAlarmId, period, appId, (DateTime*)(&endTime));
392         }
393         SysTryReturnResult(NID_SYS, r == E_SUCCESS, E_SYSTEM, "It is failed to add new alarm on the alarm list.");
394
395         pAlarmImpl->__alarmId.value = reservedAlarmId;
396         r = __alarmList.Add(&(pAlarmImpl->__alarmId), pAlarmImpl);
397
398         return r;
399 }
400
401 result
402 _AlarmManager::UnregisterAlarm(_AlarmImpl* pAlarmImpl)
403 {
404         SysLog(NID_SYS, "Alarm Cancel request");
405
406         result r = E_SUCCESS;
407         SysTryReturnResult(NID_SYS, pAlarmImpl != null, E_INVALID_ARG, "There is no alarmImpl.");
408
409         Integer alarmId(pAlarmImpl->__alarmId.value);
410         SysTryReturnResult(NID_SYS, __alarmList.ContainsKey(alarmId) == true, E_OBJ_NOT_FOUND, "There is no registered alarm.");
411
412         r = __alarmList.Remove(alarmId);
413         SysTryReturnResult(NID_SYS, r == E_SUCCESS, E_SYSTEM, "It is failed to remove reserved alarmImpl instance.");
414
415         r = RemoveAlarmList(alarmId.ToInt());
416         SysTryReturnResult(NID_SYS, r == E_SUCCESS, E_SYSTEM, "It is failed to remove reserved alarm list.");
417
418         return r;
419 }
420
421 result
422 _AlarmManager::UpdateAlarm(_AlarmImpl* pAlarmImpl)
423 {
424         result r = E_SUCCESS;
425         SysTryReturnResult(NID_SYS, pAlarmImpl != null, E_INVALID_ARG, "There is no alarmImpl.");
426
427         Integer alarmId(pAlarmImpl->__alarmId.value);
428         SysTryReturnResult(NID_SYS, __alarmList.ContainsKey(alarmId) == true, E_OBJ_NOT_FOUND, "There is no registered alarm.");
429
430         r = UnregisterAlarm(pAlarmImpl);
431         SysTryReturnResult(NID_SYS, r == E_SUCCESS, E_SYSTEM, "It is failed to unregister reserved alarm list.");
432
433         r = RegisterAlarm(pAlarmImpl);
434         return r;
435 }
436
437 void
438 _AlarmManager::OnAlarmExpired(int alarmId)
439 {
440         result r = E_SUCCESS;
441         String* pAppId = null;
442         Integer* pPeriod = null;
443         std::unique_ptr<IEnumerator> pValueEnum(null);
444         Integer reservedAlarmId(alarmId);
445         DateTime* endTime = null;
446
447         SysTryReturnVoidResult(NID_SYS, __pAlarmHashMap != null, E_SYSTEM, "Alarm list does not initialized");
448         pValueEnum.reset(__pAlarmHashMap->GetValuesN(reservedAlarmId));
449
450         SysLog(NID_SYS, "Alarm expire event is delivered. alarm id is %d", alarmId);
451
452         _AlarmImpl* pAlarmImpl = (_AlarmImpl*)__alarmList.GetValue(reservedAlarmId);
453         if(pAlarmImpl == null)
454         {
455                 SysLog(NID_SYS, "pAlarmImpl of reserved alarm[%d] is not found.", alarmId);
456         }
457
458         if(pValueEnum != null)
459         {
460                 String alarmAppId;
461                 SysLog(NID_SYS, "Matching Alarm Id is %d \n", alarmId);
462                 r = pValueEnum->MoveNext();
463                 SysTryReturnVoidResult(NID_SYS,  r == E_SUCCESS, E_SYSTEM, "Alarm enum value is not valid.");
464                 pAppId = static_cast< String* >(pValueEnum->GetCurrent());
465                 alarmAppId.Append(*pAppId);
466                 r = pValueEnum->MoveNext();
467                 pPeriod = static_cast< Integer* >(pValueEnum->GetCurrent());
468                 SysTryReturnVoidResult(NID_SYS, r == E_SUCCESS, E_SYSTEM, "Alarm enum value is not valid.");
469
470                 if(pValueEnum->MoveNext() == E_SUCCESS)
471                 {
472                         endTime = static_cast< DateTime* >(pValueEnum->GetCurrent());
473                 }
474
475                 SysLog(NID_SYS, "Reserved Alarm AppId:%ls, Period:%d\n", pAppId->GetPointer(), pPeriod->ToInt());
476
477                 if (pPeriod->ToInt() > 0)
478                 {
479                         if(endTime != null)
480                         {
481                                 DateTime currentTime;
482
483                                 SystemTime::GetCurrentTime(WALL_TIME, currentTime);
484                                 currentTime.AddMilliseconds(-1 * currentTime.GetMillisecond()); //Remove millisecond
485                                 currentTime.AddMinutes(pPeriod->ToInt());
486                                 SysLog(NID_SYS, "Next time[%d min]: %d:%d:%d:%d", pPeriod->ToInt(), currentTime.GetHour(), currentTime.GetMinute(), currentTime.GetSecond(), currentTime.GetMillisecond());
487                                 SysLog(NID_SYS, "Endtime exists %d:%d:%d:%d", endTime->GetHour(), endTime->GetMinute(), endTime->GetSecond(), endTime->GetMillisecond());
488
489                                 if (currentTime.CompareTo(*endTime) > 0)
490                                 {
491                                         SysLog(NID_SYS, "Next time is greater than end time.");
492                                         RemoveAlarmList(alarmId);
493                                         pValueEnum->Reset();
494                                         pAlarmImpl->__alarmId.value = 0;
495                                 }
496                         }
497                 }
498                 else if (pPeriod->ToInt() == 0)
499                 {
500                         RemoveAlarmList(alarmId);
501                         pAlarmImpl->__alarmId.value = 0;
502                 }
503                 else
504                 {
505                         pValueEnum->Reset();
506                 }
507         }
508
509         if(pAlarmImpl != null)
510         {
511                 pAlarmImpl->OnAlarmExpired(alarmId);
512         }
513
514         if(__pAlarmHashMap->ContainsKey(reservedAlarmId) == false)
515         {
516                 SysLog(NID_SYS, "Remove an alarm list[%d].", reservedAlarmId.value);
517                 r = __alarmList.Remove(reservedAlarmId);
518                 SetLastResult(r);
519         }
520
521         return;
522 }
523
524 } } // Tizen::System