Merge "Change the way to conver Mbs to Wcs and vice versa" 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 = null;
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                 SysLog(NID_SYS, "It is repeated alarm and period time is %d minutes", period);
131                 ret = alarmmgr_set_repeat_mode(pAlarmInfo, ALARM_REPEAT_MODE_REPEAT, period * _SECOND_OF_MINUTE);
132                 SysTryCatch(NID_SYS, ret == ALARMMGR_RESULT_SUCCESS, r = E_SYSTEM, r, "It is failed to set repeat mode");
133         }
134
135         ret = alarmmgr_set_type(pAlarmInfo, ALARM_TYPE_NOLAUNCH);
136         SysTryCatch(NID_SYS, ret == ALARMMGR_RESULT_SUCCESS, r = E_SYSTEM, r, "It is failed to set repeat mode");
137
138         ret = alarmmgr_add_alarm_appsvc_with_localtime(pAlarmInfo,(void *)pBundle, &reservedAlarmId);
139         SysTryCatch(NID_SYS, ret == ALARMMGR_RESULT_SUCCESS, r = E_SYSTEM, r, "Alarm creation failed!!! Alrmgr error code is %d", ret);
140
141 CATCH:
142         if(r == E_SYSTEM)
143         {
144                 reservedAlarmId = -1;
145         }
146         if(pAlarmInfo != null)
147         {
148                 alarmmgr_free_alarm(pAlarmInfo);
149         }
150
151         if(pBundle != null)
152         {
153                 bundle_free(pBundle);
154         }
155
156         return reservedAlarmId;
157 }
158
159 result
160 _AlarmManager::AddAlarmList(int alarmId, int period, String appId, DateTime* endTime)
161 {
162         result r = E_SUCCESS;
163
164         SysTryReturnResult(NID_SYS, __pAlarmHashMap != null, E_SYSTEM, "Alarm list does not initialized");
165         SysLog(NID_SYS, "New Alarm Id is added (%d, %d, %ls)", alarmId, period, appId.GetPointer());
166
167         Integer* reservedAlarmId = null;
168         Integer* alarmPeriod = null;
169         String* alarmAppId = null;
170
171         Integer* reverseAlarmId = null;
172         String* reverseAppId = null;
173
174         reservedAlarmId = new (std::nothrow) Integer(alarmId);
175         SysTryCatch(NID_SYS, reservedAlarmId != null, r = E_SYSTEM, E_SYSTEM, "reservedAlarmId should not be null");
176
177         alarmPeriod = new (std::nothrow) Integer(period);
178         SysTryCatch(NID_SYS, alarmPeriod != null, r = E_SYSTEM, E_SYSTEM, "alarmPeriod should not be null");
179
180         alarmAppId = new (std::nothrow) String(appId);
181         SysTryCatch(NID_SYS, alarmAppId != null, r = E_SYSTEM, E_SYSTEM, "alarmAppId should not be null");
182
183         //Forward
184         r = __pAlarmHashMap->Add(*reservedAlarmId, *alarmAppId);
185         SysTryCatch(NID_SYS, r == E_SUCCESS, r, r, "Fail to add new alarm app id on the alarm list");
186
187         r = __pAlarmHashMap->Add(*reservedAlarmId, *alarmPeriod);
188         SysTryCatch(NID_SYS, r == E_SUCCESS, r, r, "Fail to add new alarm period on the alarm list");
189
190         if(endTime != null)
191         {
192                 DateTime* alarmEndTime = new DateTime(*endTime);
193
194                 SysLog(NID_SYS, "Endtime exists %d:%d:%d", alarmEndTime->GetHour(), alarmEndTime->GetMinute(), alarmEndTime->GetSecond());
195                 r = __pAlarmHashMap->Add(*reservedAlarmId, *alarmEndTime);
196                 SysTryCatch(NID_SYS, r == E_SUCCESS, r, r, "Fail to add new alarm endtime on the alarm list");
197         }
198
199         //Reverse
200         reverseAlarmId = new (std::nothrow) Integer(alarmId);
201         SysTryCatch(NID_SYS, reverseAlarmId != null, r = E_SYSTEM, E_SYSTEM, "reverseAlarmId should not be null");
202
203         reverseAppId = new (std::nothrow) String(appId);
204         SysTryCatch(NID_SYS, reverseAppId != null, r = E_SYSTEM, E_SYSTEM, "reverseAppId should not be null");
205
206         r = __pAlarmHashMap->Add(*reverseAppId, *reverseAlarmId);
207         SysTryCatch(NID_SYS, r == E_SUCCESS, r, r, "Fail to add new alarm on the alarm list");
208
209 CATCH:
210         if(r != E_SUCCESS)
211         {
212                 if(reservedAlarmId != null)
213                 {
214                         __pAlarmHashMap->Remove(*reservedAlarmId, false);
215                         delete reservedAlarmId;
216                 }
217
218                 if(alarmPeriod != null)
219                 {
220                         delete alarmPeriod;
221                 }
222
223                 if(alarmAppId != null)
224                 {
225                         delete alarmAppId;
226                 }
227
228                 if(reverseAppId != null)
229                 {
230                         __pAlarmHashMap->Remove(*reverseAppId, false);
231                         delete reverseAppId;
232                 }
233
234                 if(reverseAlarmId != null)
235                 {
236                         delete reverseAlarmId;
237                 }
238         }
239         return r;
240 }
241
242 result
243 _AlarmManager::RemoveAlarmList(int alarmId)
244 {
245         result r = E_SUCCESS;
246         Integer requiredAlarmId(alarmId);
247         std::unique_ptr<IEnumerator>pValueEnum(null);
248
249         SysTryReturnResult(NID_SYS, __pAlarmHashMap != null, E_SYSTEM, "Alarm list does not initialized");
250
251         alarm_cancel(alarmId);
252         SysLog(NID_SYS, "AlarmId %d disarms the timer.", alarmId);
253
254         pValueEnum.reset(__pAlarmHashMap->GetValuesN(requiredAlarmId));
255
256         if(pValueEnum != null)
257         {
258                 SysLog(NID_SYS, "Reserved Alarms are exist");
259                 String* alarmAppId = null;
260                 r = pValueEnum->MoveNext();
261                 SysTryReturnResult(NID_SYS, r == E_SUCCESS, E_SYSTEM, "Reserved Alarm List is not valid.");
262                 alarmAppId = static_cast< String* >(pValueEnum->GetCurrent());
263
264                 if(alarmAppId != null)
265                 {
266                         SysLog(NID_SYS, "Alarm AppId is %S", alarmAppId->GetPointer());
267                         std::unique_ptr<IEnumerator>pAlarmEnum(__pAlarmHashMap->GetValuesN(*alarmAppId));
268                         if(pAlarmEnum != null)
269                         {
270                                 while(pAlarmEnum->MoveNext() == E_SUCCESS)
271                                 {
272                                         Integer* reverseAlarmId = static_cast< Integer* >(pAlarmEnum->GetCurrent());
273                                         if(reverseAlarmId != null)
274                                         {
275                                                 SysLog(NID_SYS, "Reserved Alarm is %d", reverseAlarmId->ToInt());
276                                                 if(reverseAlarmId->ToInt() == alarmId)
277                                                 {
278                                                         SysLog(NID_SYS, "Remove reservedAlarmId for reverse look-up");
279                                                          __pAlarmHashMap->Remove(*alarmAppId, *reverseAlarmId);
280                                                         delete reverseAlarmId;
281                                                         break;
282                                                 }
283                                         }
284                                 }
285                         }
286
287                         int count = 0;
288                         __pAlarmHashMap->GetCount(*alarmAppId, count);
289                         if(count == 0)
290                         {
291                                 SysLog(NID_SYS, "There is no more reserved alarm for AppId:%S", alarmAppId->GetPointer());
292                                 __pAlarmHashMap->Remove(*alarmAppId, true);
293                         }
294                 }
295         }
296         r = __pAlarmHashMap->Remove(requiredAlarmId, true);
297
298         return r;
299 }
300
301 result
302 _AlarmManager::RemoveAlarmList(String appId)
303 {
304         result r = E_SUCCESS;
305         Integer requiredAlarmId;
306         IEnumerator *pValueEnum = null;
307
308         SysTryReturnResult(NID_SYS, __pAlarmHashMap != null, E_SYSTEM, "Alarm list does not initialized");
309         pValueEnum = __pAlarmHashMap->GetValuesN(appId);
310
311         if(pValueEnum != null)
312         {
313                 SysLog(NID_SYS, "Reserved Alarms are exist for AppId:%S", appId.GetPointer());
314                 while(pValueEnum->MoveNext() == E_SUCCESS)
315                 {
316                         Integer* reverseAlarmId = static_cast< Integer* >(pValueEnum->GetCurrent());
317                         if(reverseAlarmId != null)
318                         {
319                                 SysLog(NID_SYS, "Reserved AlarmId is %d", reverseAlarmId->ToInt());
320                                 alarm_cancel(reverseAlarmId->ToInt());
321                                 __pAlarmHashMap->Remove(*reverseAlarmId, true);
322                         }
323                 }
324                 delete pValueEnum;
325         }
326         r = __pAlarmHashMap->Remove(appId, true);
327
328         return r;
329 }
330
331 result
332 _AlarmManager::RegisterAlarm(_AlarmImpl* pAlarmImpl)
333 {
334         SysTryReturnResult(NID_SYS, pAlarmImpl != null, E_INVALID_ARG, "There is no alarmImpl.");
335         Integer alarmId(pAlarmImpl->__alarmId.value);
336         SysTryReturnResult(NID_SYS, __alarmList.ContainsKey(alarmId) == false, E_OBJ_ALREADY_EXIST, "Required Alarm[%d] is already registered.", pAlarmImpl->__alarmId.value);
337
338         result r = E_SUCCESS;
339         ArrayList requestMessage;
340         ArrayList responseMessage;
341
342         String startTimeStr;
343         String periodStr;
344         String endTimeStr;
345         String appId;
346
347         int period = pAlarmImpl->GetPeriod();
348  
349         DateTime currentTime;
350         DateTime startTime = pAlarmImpl->GetStartTime();
351         const DateTime* pEndTime = pAlarmImpl->GetEndTime();
352         DateTime endTime;
353
354         //Argument check
355         startTime.AddMilliseconds(-1 * startTime.GetMillisecond());
356         r = SystemTime::GetCurrentTime(WALL_TIME, currentTime);
357         currentTime.AddMilliseconds(-1 * currentTime.GetMillisecond());
358
359         SysTryReturnResult(NID_SYS, r == E_SUCCESS, E_SYSTEM, "It is failed to get current time.");
360         SysTryReturnResult(NID_SYS, DateTime::Compare(currentTime, startTime) < 0, E_INVALID_ARG, "Designated start time has to be greater than current time.");
361         SysTryReturnResult(NID_SYS, period > -1, E_INVALID_ARG, "Period has to greater than -1");
362
363         if(pEndTime != null)
364         {
365                 endTime = *pEndTime;
366                 endTime.AddMilliseconds(-1 * endTime.GetMillisecond());
367
368                 SysTryReturnResult(NID_SYS, DateTime::Compare(startTime, endTime) < 0, E_INVALID_ARG, "Designated end time is less than start time.");
369         }
370         //End Alarm validation check
371
372         Tizen::App::App* pApp = Tizen::App::App::GetInstance();
373         SysTryReturnResult(NID_SYS, pApp != null, E_SYSTEM, "[%s] A system error has been occurred. App::GetInstance() failed.", GetErrorMessage(E_SYSTEM));
374         appId = pApp->GetAppId();
375
376         String* result = null;
377         int reservedAlarmId = 0;
378
379         SysLog(NID_SYS, "Alarm setting request");
380
381         reservedAlarmId = ReserveAlarm(appId, startTime, period);
382         SysTryReturnResult(NID_SYS, reservedAlarmId != -1, E_SYSTEM, "It is failed to register alarm.");
383
384         SysLog(NID_SYS, "Reserved AppId %ls, alarmId: %d", appId.GetPointer(), reservedAlarmId);
385
386         if(pEndTime == null)
387         {
388                 r = AddAlarmList(reservedAlarmId, period, appId, null);
389         }
390         else
391         {
392                 r = AddAlarmList(reservedAlarmId, period, appId, (DateTime*)(&endTime));
393         }
394         SysTryReturnResult(NID_SYS, r == E_SUCCESS, E_SYSTEM, "It is failed to add new alarm on the alarm list.");
395
396         pAlarmImpl->__alarmId.value = reservedAlarmId;
397         r = __alarmList.Add(&(pAlarmImpl->__alarmId), pAlarmImpl);
398
399         return r;
400 }
401
402 result
403 _AlarmManager::UnregisterAlarm(_AlarmImpl* pAlarmImpl)
404 {
405         SysLog(NID_SYS, "Alarm Cancel request");
406
407         result r = E_SUCCESS;
408         SysTryReturnResult(NID_SYS, pAlarmImpl != null, E_INVALID_ARG, "There is no alarmImpl.");
409
410         Integer alarmId(pAlarmImpl->__alarmId.value);
411         SysTryReturnResult(NID_SYS, __alarmList.ContainsKey(alarmId) == true, E_OBJ_NOT_FOUND, "There is no registered alarm.");
412
413         r = __alarmList.Remove(alarmId);
414         SysTryReturnResult(NID_SYS, r == E_SUCCESS, E_SYSTEM, "It is failed to remove reserved alarmImpl instance.");
415
416         r = RemoveAlarmList(alarmId.ToInt());
417         SysTryReturnResult(NID_SYS, r == E_SUCCESS, E_SYSTEM, "It is failed to remove reserved alarm list.");
418
419         return r;
420 }
421
422 result
423 _AlarmManager::UpdateAlarm(_AlarmImpl* pAlarmImpl)
424 {
425         result r = E_SUCCESS;
426         SysTryReturnResult(NID_SYS, pAlarmImpl != null, E_INVALID_ARG, "There is no alarmImpl.");
427
428         Integer alarmId(pAlarmImpl->__alarmId.value);
429         SysTryReturnResult(NID_SYS, __alarmList.ContainsKey(alarmId) == true, E_OBJ_NOT_FOUND, "There is no registered alarm.");
430
431         r = UnregisterAlarm(pAlarmImpl);
432         SysTryReturnResult(NID_SYS, r == E_SUCCESS, E_SYSTEM, "It is failed to unregister reserved alarm list.");
433
434         r = RegisterAlarm(pAlarmImpl);
435         return r;
436 }
437
438 void
439 _AlarmManager::OnAlarmExpired(int alarmId)
440 {
441         result r = E_SUCCESS;
442         String* pAppId = null;
443         Integer* pPeriod = null;
444         std::unique_ptr<IEnumerator> pValueEnum(null);
445         Integer reservedAlarmId(alarmId);
446         DateTime* endTime = null;
447
448         SysTryReturnVoidResult(NID_SYS, __pAlarmHashMap != null, E_SYSTEM, "Alarm list does not initialized");
449         pValueEnum.reset(__pAlarmHashMap->GetValuesN(reservedAlarmId));
450
451         SysLog(NID_SYS, "Alarm expire event is delivered. alarm id is %d", alarmId);
452
453         _AlarmImpl* pAlarmImpl = (_AlarmImpl*)__alarmList.GetValue(reservedAlarmId);
454         if(pAlarmImpl == null)
455         {
456                 SysLog(NID_SYS, "pAlarmImpl of reserved alarm[%d] is not found.", alarmId);
457         }
458
459         if(pValueEnum != null)
460         {
461                 String alarmAppId;
462                 SysLog(NID_SYS, "Matching Alarm Id is %d \n", alarmId);
463                 r = pValueEnum->MoveNext();
464                 SysTryReturnVoidResult(NID_SYS,  r == E_SUCCESS, E_SYSTEM, "Alarm enum value is not valid.");
465                 pAppId = static_cast< String* >(pValueEnum->GetCurrent());
466                 alarmAppId.Append(*pAppId);
467                 r = pValueEnum->MoveNext();
468                 pPeriod = static_cast< Integer* >(pValueEnum->GetCurrent());
469                 SysTryReturnVoidResult(NID_SYS, r == E_SUCCESS, E_SYSTEM, "Alarm enum value is not valid.");
470
471                 if(pValueEnum->MoveNext() == E_SUCCESS)
472                 {
473                         endTime = static_cast< DateTime* >(pValueEnum->GetCurrent());
474                 }
475
476                 SysLog(NID_SYS, "Reserved Alarm AppId:%ls, Period:%d\n", pAppId->GetPointer(), pPeriod->ToInt());
477
478                 if (pPeriod->ToInt() > 0)
479                 {
480                         if(endTime != null)
481                         {
482                                 DateTime currentTime;
483
484                                 SystemTime::GetCurrentTime(WALL_TIME, currentTime);
485                                 currentTime.AddMilliseconds(-1 * currentTime.GetMillisecond()); //Remove millisecond
486                                 currentTime.AddMinutes(pPeriod->ToInt());
487                                 SysLog(NID_SYS, "Next time[%d min]: %d:%d:%d:%d", pPeriod->ToInt(), currentTime.GetHour(), currentTime.GetMinute(), currentTime.GetSecond(), currentTime.GetMillisecond());
488                                 SysLog(NID_SYS, "Endtime exists %d:%d:%d:%d", endTime->GetHour(), endTime->GetMinute(), endTime->GetSecond(), endTime->GetMillisecond());
489
490                                 if (currentTime.CompareTo(*endTime) > 0)
491                                 {
492                                         SysLog(NID_SYS, "Next time is greater than end time.");
493                                         RemoveAlarmList(alarmId);
494                                         pValueEnum->Reset();
495
496                                         if(pAlarmImpl != null)
497                                         {
498                                                 pAlarmImpl->__alarmId.value = 0;
499                                         }
500                                 }
501                         }
502                 }
503                 else if (pPeriod->ToInt() == 0)
504                 {
505                         RemoveAlarmList(alarmId);
506
507                         if(pAlarmImpl != null)
508                         {
509                                 pAlarmImpl->__alarmId.value = 0;
510                         }
511                 }
512                 else
513                 {
514                         pValueEnum->Reset();
515                 }
516         }
517
518         if(pAlarmImpl != null)
519         {
520                 pAlarmImpl->OnAlarmExpired(alarmId);
521         }
522
523         if(__pAlarmHashMap->ContainsKey(reservedAlarmId) == false)
524         {
525                 SysLog(NID_SYS, "Remove an alarm list[%d].", reservedAlarmId.value);
526                 r = __alarmList.Remove(reservedAlarmId);
527                 SetLastResult(r);
528         }
529
530         return;
531 }
532
533 } } // Tizen::System