Merge "Implement seperated server-so model" 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 is exist %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 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
352         //Argument check
353         r = SystemTime::GetCurrentTime(WALL_TIME, currentTime);
354         SysTryReturnResult(NID_SYS, r == E_SUCCESS, E_SYSTEM, "It is failed to get current time.");
355         SysTryReturnResult(NID_SYS, DateTime::Compare(currentTime, startTime) < 0, E_INVALID_ARG, "Designated start time has to be greater than current time.");
356         SysTryReturnResult(NID_SYS, period > -1, E_INVALID_ARG, "Period has to greater then -1");
357
358         if(pEndTime != null)
359         {
360                 SysTryReturnResult(NID_SYS, DateTime::Compare(startTime, *pEndTime) < 0, E_INVALID_ARG, "Designated end time is less then start time.");
361         }
362         //End Alarm validation check
363
364         Tizen::App::App* pApp = Tizen::App::App::GetInstance();
365         SysTryReturnResult(NID_SYS, pApp != null, E_SYSTEM, "[%s] A system error has been occurred. App::GetInstance() failed.", GetErrorMessage(E_SYSTEM));
366         appId = pApp->GetAppId();
367
368         String* result = null;
369         int reservedAlarmId = 0;
370
371         SysLog(NID_SYS, "Alarm setting request");
372
373         reservedAlarmId = ReserveAlarm(appId, startTime, period);
374         SysTryReturnResult(NID_SYS, reservedAlarmId != -1, E_SYSTEM, "It is failed to register alarm.");
375
376         SysLog(NID_SYS, "Reserved AppId %ls, alarmId: %d", appId.GetPointer(), reservedAlarmId);
377
378         if(pEndTime == null)
379         {
380                 r = AddAlarmList(reservedAlarmId, period, appId, null);
381         }
382         else
383         {
384                 r = AddAlarmList(reservedAlarmId, period, appId, const_cast<DateTime*>(pEndTime));
385         }
386         SysTryReturnResult(NID_SYS, r == E_SUCCESS, E_SYSTEM, "It is failed to add new alarm on the alarm list.");
387
388         pAlarmImpl->__alarmId.value = reservedAlarmId;
389         r = __alarmList.Add(&(pAlarmImpl->__alarmId), pAlarmImpl);
390
391         return r;
392 }
393
394 result
395 _AlarmManager::UnregisterAlarm(_AlarmImpl* pAlarmImpl)
396 {
397         SysLog(NID_SYS, "Alarm Cancel request");
398
399         result r = E_SUCCESS;
400         SysTryReturnResult(NID_SYS, pAlarmImpl != null, E_INVALID_ARG, "There is no alarmImpl.");
401
402         Integer alarmId(pAlarmImpl->__alarmId.value);
403         SysTryReturnResult(NID_SYS, __alarmList.ContainsKey(alarmId) == true, E_OBJ_NOT_FOUND, "There is no registered alarm.");
404
405         r = __alarmList.Remove(alarmId);
406         SysTryReturnResult(NID_SYS, r == E_SUCCESS, E_SYSTEM, "It is failed to remove reserved alarmImpl instance.");
407
408         r = RemoveAlarmList(alarmId.ToInt());
409         SysTryReturnResult(NID_SYS, r == E_SUCCESS, E_SYSTEM, "It is failed to remove reserved alarm list.");
410
411         return r;
412 }
413
414 result
415 _AlarmManager::UpdateAlarm(_AlarmImpl* pAlarmImpl)
416 {
417         result r = E_SUCCESS;
418         SysTryReturnResult(NID_SYS, pAlarmImpl != null, E_INVALID_ARG, "There is no alarmImpl.");
419
420         Integer alarmId(pAlarmImpl->__alarmId.value);
421         SysTryReturnResult(NID_SYS, __alarmList.ContainsKey(alarmId) == true, E_OBJ_NOT_FOUND, "There is no registered alarm.");
422
423         r = UnregisterAlarm(pAlarmImpl);
424         SysTryReturnResult(NID_SYS, r == E_SUCCESS, E_SYSTEM, "It is failed to unregister reserved alarm list.");
425
426         r = RegisterAlarm(pAlarmImpl);
427         return r;
428 }
429
430 void
431 _AlarmManager::OnAlarmExpired(int alarmId)
432 {
433         result r = E_SUCCESS;
434         String* pAppId = null;
435         Integer* pPeriod = null;
436         std::unique_ptr<IEnumerator> pValueEnum(null);
437         Integer reservedAlarmId(alarmId);
438         DateTime* endTime = null;
439
440         SysTryReturnVoidResult(NID_SYS, __pAlarmHashMap != null, E_SYSTEM, "Alarm list does not initialized");
441         pValueEnum.reset(__pAlarmHashMap->GetValuesN(reservedAlarmId));
442
443         SysLog(NID_SYS, "Alarm expire event is delivered. alarm id is %d", alarmId);
444
445         if(pValueEnum != null)
446         {
447                 String alarmAppId;
448                 SysLog(NID_SYS, "Matching Alarm Id is %d \n", alarmId);
449                 r = pValueEnum->MoveNext();
450                 SysTryReturnVoidResult(NID_SYS,  r == E_SUCCESS, E_SYSTEM, "Alarm enum value is not valid.");
451                 pAppId = static_cast< String* >(pValueEnum->GetCurrent());
452                 alarmAppId.Append(*pAppId);
453                 r = pValueEnum->MoveNext();
454                 pPeriod = static_cast< Integer* >(pValueEnum->GetCurrent());
455                 SysTryReturnVoidResult(NID_SYS, r == E_SUCCESS, E_SYSTEM, "Alarm enum value is not valid.");
456
457                 if(pValueEnum->MoveNext() == E_SUCCESS)
458                 {
459                         endTime = static_cast< DateTime* >(pValueEnum->GetCurrent());
460                 }
461
462                 SysLog(NID_SYS, "Reserved Alarm AppId:%ls, Period:%d\n", pAppId->GetPointer(), pPeriod->ToInt());
463
464                 if (pPeriod->ToInt() > 0)
465                 {
466                         if(endTime != null)
467                         {
468                                 DateTime currentTime;
469                                 SystemTime::GetCurrentTime(WALL_TIME, currentTime);
470                                 SysLog(NID_SYS, "Current time: %d:%d:%d", currentTime.GetHour(), currentTime.GetMinute(), currentTime.GetSecond());
471                                 currentTime.AddMinutes(pPeriod->ToInt());
472                                 SysLog(NID_SYS, "Next time: %d:%d:%d", currentTime.GetHour(), currentTime.GetMinute(), currentTime.GetSecond());
473                                 SysLog(NID_SYS, "Endtime is exist %d:%d:%d", endTime->GetHour(), endTime->GetMinute(), endTime->GetSecond());
474
475                                 if (currentTime.CompareTo(*endTime) >= 0)
476                                 {
477                                         SysLog(NID_SYS, "Next time is greater then end time.");
478                                         RemoveAlarmList(alarmId);
479                                         pValueEnum->Reset();
480                                 }
481                         }
482                 }
483                 else if (pPeriod->ToInt() == 0)
484                 {
485                         RemoveAlarmList(alarmId);
486                 }
487                 else
488                 {
489                         pValueEnum->Reset();
490                 }
491         }
492
493         _AlarmImpl* pAlarmImpl = (_AlarmImpl*)__alarmList.GetValue(reservedAlarmId);
494         if(pAlarmImpl != null)
495         {
496                 SysLog(NID_SYS, "Reserved Alarm[%d] is found.", alarmId);
497                 pAlarmImpl->OnAlarmExpired(alarmId);
498         }
499
500         if(__pAlarmHashMap->ContainsKey(reservedAlarmId) == false)
501         {
502                 r = __alarmList.Remove(reservedAlarmId);
503                 SetLastResult(r);
504         }
505
506         return;
507 }
508
509 } } // Tizen::System