2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
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
8 // http://www.apache.org/licenses/LICENSE-2.0
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.
18 * @file FSys_AlarmManager.cpp
19 * @brief This is the implementation file for _AlarmManager class.
22 #include <unique_ptr.h>
24 #include <appfw/app.h>
26 #include <appsvc/appsvc.h>
28 #include <FBaseSysLog.h>
29 #include <FSysSystemTime.h>
31 #include <FBaseColArrayList.h>
33 #include <FBase_NativeError.h>
34 #include <FBase_StringConverter.h>
36 #include "inc/FSys_AlarmManager.h"
38 using namespace Tizen::Base;
39 using namespace Tizen::Base::Runtime;
40 using namespace Tizen::Base::Collection;
41 using namespace Tizen::Io;
43 namespace Tizen { namespace System
45 static const long _SECOND_OF_MINUTE = 60;
47 _AlarmManager* _AlarmManager::__pAlarmManager = null;
49 _AlarmManager::_AlarmManager()
50 : __pAlarmHashMap(null)
53 int ret = pthread_mutex_init(&__lock, null);
54 SysTryCatch(NID_SYS, ret == 0, r = E_SYSTEM, E_SYSTEM, "It is failed to init mutex.");
56 __alarmList.Construct();
60 __pAlarmHashMap = new (std::nothrow) MultiHashMap();
61 SysTryCatch(NID_SYS, __pAlarmHashMap != null, r = E_SYSTEM, E_SYSTEM, "__pAlarmHashMap should not be null");
63 r = __pAlarmHashMap->Construct();
64 SysTryCatch(NID_SYS, r == E_SUCCESS, r= E_SYSTEM, E_SYSTEM, "[%s] Propagated.", GetErrorMessage(r));
67 //Checks for any alarm existence
74 _AlarmManager::~_AlarmManager()
76 int ret = pthread_mutex_destroy(&__lock);
79 SysLogException(NID_SYS, E_SYSTEM, "It is failed to destroy mutex.");
82 delete __pAlarmHashMap;
83 __pAlarmHashMap = null;
85 //Cancel all the alarms before exiting
90 _AlarmManager::GetInstance(void)
92 static pthread_once_t onceBlock = PTHREAD_ONCE_INIT;
93 if(__pAlarmManager == null)
95 pthread_once(&onceBlock, InitSingleton);
97 return __pAlarmManager;
101 _AlarmManager::InitSingleton(void)
103 _AlarmManager* pAlarmManager = new (std::nothrow) _AlarmManager();
104 SysTryReturnVoidResult(NID_SYS, pAlarmManager, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
105 GetErrorMessage(E_OUT_OF_MEMORY));
107 __pAlarmManager = pAlarmManager;
108 std::atexit(DestroySingleton);
112 _AlarmManager::DestroySingleton(void)
114 delete __pAlarmManager;
118 _AlarmManager::ReserveAlarm(Tizen::Base::String appId, Tizen::Base::DateTime startTime, int period)
120 int reservedAlarmId = -1;
121 result r = E_SUCCESS;
126 SysLog(NID_SYS, "Reserve time is %d/%d/%d %d:%d:%d", startTime.GetYear(), startTime.GetMonth(), startTime.GetDay(), startTime.GetHour(), startTime.GetMinute(), startTime.GetSecond());
128 bundle* pBundle = null;
129 alarm_entry_t* pAlarmInfo = null;
130 alarm_date_t expireTime = {0,};
132 std::unique_ptr<char[]> pId(_StringConverter::CopyToCharArrayN(appId));
134 pBundle = bundle_create();
135 SysTryCatch(NID_SYS, pBundle != null, r = E_SYSTEM, r, "It is failed to create bundle");
137 ret = appsvc_set_operation(pBundle,"osp.operation.ALARM");
138 SysTryCatch(NID_SYS, ret == SERVICE_ERROR_NONE, r = E_SYSTEM, r, "It is failed to set operation");
140 ret = appsvc_set_appid(pBundle, (const char*)(pId.get()));
141 SysTryCatch(NID_SYS, ret == SERVICE_ERROR_NONE, r = E_SYSTEM, r, "It is failed to set appid for %ls", appId.GetPointer());
143 pAlarmInfo = alarmmgr_create_alarm();
144 SysTryCatch(NID_SYS, pAlarmInfo != null, r = E_SYSTEM, r, "It is failed to create alarm entry");
146 expireTime.year = startTime.GetYear();
147 expireTime.month = startTime.GetMonth();
148 expireTime.day = startTime.GetDay();
149 expireTime.hour = startTime.GetHour();
150 expireTime.min = startTime.GetMinute();
151 expireTime.sec = startTime.GetSecond();
153 ret = alarmmgr_set_time(pAlarmInfo, expireTime);
154 SysTryCatch(NID_SYS, ret == ALARMMGR_RESULT_SUCCESS, r = E_SYSTEM, r, "It is failed to set new alarm time");
158 SysLog(NID_SYS, "It is repeated alarm and period time is %d minutes", period);
159 ret = alarmmgr_set_repeat_mode(pAlarmInfo, ALARM_REPEAT_MODE_REPEAT, period * _SECOND_OF_MINUTE);
160 SysTryCatch(NID_SYS, ret == ALARMMGR_RESULT_SUCCESS, r = E_SYSTEM, r, "It is failed to set repeat mode");
163 ret = alarmmgr_set_type(pAlarmInfo, ALARM_TYPE_NOLAUNCH);
164 SysTryCatch(NID_SYS, ret == ALARMMGR_RESULT_SUCCESS, r = E_SYSTEM, r, "It is failed to set repeat mode");
166 ret = alarmmgr_add_alarm_appsvc_with_localtime(pAlarmInfo,(void *)pBundle, &reservedAlarmId);
167 SysTryCatch(NID_SYS, ret == ALARMMGR_RESULT_SUCCESS, r = E_SYSTEM, r, "Alarm creation failed!!! Alrmgr error code is %d", ret);
172 reservedAlarmId = -1;
174 if(pAlarmInfo != null)
176 alarmmgr_free_alarm(pAlarmInfo);
181 bundle_free(pBundle);
184 return reservedAlarmId;
188 _AlarmManager::AddAlarmList(int alarmId, int period, String appId, DateTime* endTime)
190 result r = E_SUCCESS;
192 SysTryReturnResult(NID_SYS, __pAlarmHashMap != null, E_SYSTEM, "Alarm list does not initialized");
193 SysLog(NID_SYS, "New Alarm Id is added (%d, %d, %ls)", alarmId, period, appId.GetPointer());
195 Integer* reservedAlarmId = null;
196 Integer* alarmPeriod = null;
197 String* alarmAppId = null;
199 Integer* reverseAlarmId = null;
200 String* reverseAppId = null;
202 reservedAlarmId = new (std::nothrow) Integer(alarmId);
203 SysTryCatch(NID_SYS, reservedAlarmId != null, r = E_SYSTEM, E_SYSTEM, "reservedAlarmId should not be null");
205 alarmPeriod = new (std::nothrow) Integer(period);
206 SysTryCatch(NID_SYS, alarmPeriod != null, r = E_SYSTEM, E_SYSTEM, "alarmPeriod should not be null");
208 alarmAppId = new (std::nothrow) String(appId);
209 SysTryCatch(NID_SYS, alarmAppId != null, r = E_SYSTEM, E_SYSTEM, "alarmAppId should not be null");
212 r = __pAlarmHashMap->Add(*reservedAlarmId, *alarmAppId);
213 SysTryCatch(NID_SYS, r == E_SUCCESS, r, r, "Fail to add new alarm app id on the alarm list");
215 r = __pAlarmHashMap->Add(*reservedAlarmId, *alarmPeriod);
216 SysTryCatch(NID_SYS, r == E_SUCCESS, r, r, "Fail to add new alarm period on the alarm list");
220 DateTime* alarmEndTime = new DateTime(*endTime);
222 SysLog(NID_SYS, "Endtime exists %d:%d:%d", alarmEndTime->GetHour(), alarmEndTime->GetMinute(), alarmEndTime->GetSecond());
223 r = __pAlarmHashMap->Add(*reservedAlarmId, *alarmEndTime);
224 SysTryCatch(NID_SYS, r == E_SUCCESS, r, r, "Fail to add new alarm endtime on the alarm list");
228 reverseAlarmId = new (std::nothrow) Integer(alarmId);
229 SysTryCatch(NID_SYS, reverseAlarmId != null, r = E_SYSTEM, E_SYSTEM, "reverseAlarmId should not be null");
231 reverseAppId = new (std::nothrow) String(appId);
232 SysTryCatch(NID_SYS, reverseAppId != null, r = E_SYSTEM, E_SYSTEM, "reverseAppId should not be null");
234 r = __pAlarmHashMap->Add(*reverseAppId, *reverseAlarmId);
235 SysTryCatch(NID_SYS, r == E_SUCCESS, r, r, "Fail to add new alarm on the alarm list");
240 if(reservedAlarmId != null)
242 __pAlarmHashMap->Remove(*reservedAlarmId, false);
243 delete reservedAlarmId;
246 if(alarmPeriod != null)
251 if(alarmAppId != null)
256 if(reverseAppId != null)
258 __pAlarmHashMap->Remove(*reverseAppId, false);
262 if(reverseAlarmId != null)
264 delete reverseAlarmId;
271 _AlarmManager::RemoveAlarmList(int alarmId)
273 result r = E_SUCCESS;
274 Integer requiredAlarmId(alarmId);
275 std::unique_ptr<IEnumerator>pValueEnum(null);
277 SysTryReturnResult(NID_SYS, __pAlarmHashMap != null, E_SYSTEM, "Alarm list does not initialized");
279 alarm_cancel(alarmId);
280 SysLog(NID_SYS, "AlarmId %d disarms the timer.", alarmId);
282 pValueEnum.reset(__pAlarmHashMap->GetValuesN(requiredAlarmId));
284 if(pValueEnum != null)
286 SysLog(NID_SYS, "Reserved Alarms are exist");
287 String* alarmAppId = null;
288 r = pValueEnum->MoveNext();
289 SysTryReturnResult(NID_SYS, r == E_SUCCESS, E_SYSTEM, "Reserved Alarm List is not valid.");
290 alarmAppId = static_cast< String* >(pValueEnum->GetCurrent());
292 if(alarmAppId != null)
294 SysLog(NID_SYS, "Alarm AppId is %S", alarmAppId->GetPointer());
295 std::unique_ptr<IEnumerator>pAlarmEnum(__pAlarmHashMap->GetValuesN(*alarmAppId));
296 if(pAlarmEnum != null)
298 while(pAlarmEnum->MoveNext() == E_SUCCESS)
300 Integer* reverseAlarmId = static_cast< Integer* >(pAlarmEnum->GetCurrent());
301 if(reverseAlarmId != null)
303 SysLog(NID_SYS, "Reserved Alarm is %d", reverseAlarmId->ToInt());
304 if(reverseAlarmId->ToInt() == alarmId)
306 SysLog(NID_SYS, "Remove reservedAlarmId for reverse look-up");
307 __pAlarmHashMap->Remove(*alarmAppId, *reverseAlarmId);
308 delete reverseAlarmId;
316 __pAlarmHashMap->GetCount(*alarmAppId, count);
319 SysLog(NID_SYS, "There is no more reserved alarm for AppId:%S", alarmAppId->GetPointer());
320 __pAlarmHashMap->Remove(*alarmAppId, true);
324 r = __pAlarmHashMap->Remove(requiredAlarmId, true);
330 _AlarmManager::RemoveAlarmList(String appId)
332 result r = E_SUCCESS;
333 Integer requiredAlarmId;
334 IEnumerator *pValueEnum = null;
336 SysTryReturnResult(NID_SYS, __pAlarmHashMap != null, E_SYSTEM, "Alarm list does not initialized");
337 pValueEnum = __pAlarmHashMap->GetValuesN(appId);
339 if(pValueEnum != null)
341 SysLog(NID_SYS, "Reserved Alarms are exist for AppId:%S", appId.GetPointer());
342 while(pValueEnum->MoveNext() == E_SUCCESS)
344 Integer* reverseAlarmId = static_cast< Integer* >(pValueEnum->GetCurrent());
345 if(reverseAlarmId != null)
347 SysLog(NID_SYS, "Reserved AlarmId is %d", reverseAlarmId->ToInt());
348 alarm_cancel(reverseAlarmId->ToInt());
349 __pAlarmHashMap->Remove(*reverseAlarmId, true);
354 r = __pAlarmHashMap->Remove(appId, true);
360 _AlarmManager::RegisterAlarm(_AlarmImpl* pAlarmImpl)
362 SysTryReturnResult(NID_SYS, pAlarmImpl != null, E_INVALID_ARG, "There is no alarmImpl.");
363 Integer alarmId(pAlarmImpl->__alarmId.value);
364 SysTryReturnResult(NID_SYS, __alarmList.ContainsKey(alarmId) == false, E_OBJ_ALREADY_EXIST, "Required Alarm[%d] is already registered.", pAlarmImpl->__alarmId.value);
366 result r = E_SUCCESS;
367 ArrayList requestMessage;
368 ArrayList responseMessage;
375 int reservedAlarmId = 0;
376 int period = pAlarmImpl->GetPeriod();
378 Tizen::App::App* pApp = null;
380 DateTime currentTime;
381 DateTime startTime = pAlarmImpl->GetStartTime();
382 const DateTime* pEndTime = pAlarmImpl->GetEndTime();
386 startTime.AddMilliseconds(-1 * startTime.GetMillisecond());
387 r = SystemTime::GetCurrentTime(WALL_TIME, currentTime);
388 currentTime.AddMilliseconds(-1 * currentTime.GetMillisecond());
390 SysTryReturnResult(NID_SYS, r == E_SUCCESS, E_SYSTEM, "It is failed to get current time.");
391 SysTryReturnResult(NID_SYS, DateTime::Compare(currentTime, startTime) < 0, E_INVALID_ARG, "Designated start time has to be greater than current time.");
392 SysTryReturnResult(NID_SYS, period > -1, E_INVALID_ARG, "Period has to greater than -1");
394 ret = pthread_mutex_lock(&__lock);
395 SysTryCatch(NID_SYS, ret == 0, r = E_INVALID_ARG, r, "It is failed to lock mutex.");
400 endTime.AddMilliseconds(-1 * endTime.GetMillisecond());
402 SysTryCatch(NID_SYS, DateTime::Compare(startTime, endTime) < 0, r = E_INVALID_ARG, r, "Designated end time is less than start time.");
404 //End Alarm validation check
406 pApp = Tizen::App::App::GetInstance();
407 SysTryCatch(NID_SYS, pApp != null, r = E_SYSTEM, r, "[%s] A system error has been occurred. App::GetInstance() failed.", GetErrorMessage(E_SYSTEM));
408 appId = pApp->GetAppId();
410 reservedAlarmId = ReserveAlarm(appId, startTime, period);
411 SysTryCatch(NID_SYS, reservedAlarmId != -1, r = E_SYSTEM, r, "It is failed to register alarm.");
413 SysLog(NID_SYS, "Reserved AppId %ls, alarmId: %d", appId.GetPointer(), reservedAlarmId);
417 r = AddAlarmList(reservedAlarmId, period, appId, null);
421 r = AddAlarmList(reservedAlarmId, period, appId, (DateTime*)(&endTime));
423 SysTryCatch(NID_SYS, r == E_SUCCESS, r = E_SYSTEM, r, "It is failed to add new alarm on the alarm list.");
425 pAlarmImpl->__alarmId.value = reservedAlarmId;
426 r = __alarmList.Add(&(pAlarmImpl->__alarmId), pAlarmImpl);
429 ret = pthread_mutex_unlock(&__lock);
430 SysTryReturnResult(NID_SYS, ret == 0, E_INVALID_ARG, "It is failed to unlock mutex.");
435 _AlarmManager::UnregisterAlarm(_AlarmImpl* pAlarmImpl)
437 result r = E_SUCCESS;
440 SysLog(NID_SYS, "Alarm Cancel request");
441 SysTryCatch(NID_SYS, pAlarmImpl != null, r = E_INVALID_ARG, r, "There is no alarmImpl.");
443 ret = pthread_mutex_lock(&__lock);
444 SysTryCatch(NID_SYS, ret == 0, r = E_SYSTEM, r, "It is failed to lock mutex.");
446 alarmId.value = pAlarmImpl->__alarmId.value;
447 SysTryCatch(NID_SYS, __alarmList.ContainsKey(alarmId) == true, r = E_OBJ_NOT_FOUND, r, "There is no registered alarm.");
449 r = __alarmList.Remove(alarmId);
450 SysTryCatch(NID_SYS, r == E_SUCCESS, r = E_SYSTEM, r, "It is failed to remove reserved alarmImpl instance.");
452 r = RemoveAlarmList(alarmId.ToInt());
453 SysTryCatch(NID_SYS, r == E_SUCCESS, r = E_SYSTEM, r, "It is failed to remove reserved alarm list.");
456 ret = pthread_mutex_unlock(&__lock);
457 SysTryReturnResult(NID_SYS, ret == 0, E_SYSTEM, "It is failed to unlock mutex.");
462 _AlarmManager::UpdateAlarm(_AlarmImpl* pAlarmImpl)
464 result r = E_SUCCESS;
466 SysTryReturnResult(NID_SYS, pAlarmImpl != null, E_SYSTEM, "There is no alarmImpl.");
468 alarmId.value = pAlarmImpl->__alarmId.value;
469 SysTryReturnResult(NID_SYS, __alarmList.ContainsKey(alarmId) == true, E_SYSTEM, "There is no registered alarm.");
471 r = UnregisterAlarm(pAlarmImpl);
472 SysTryReturnResult(NID_SYS, r == E_SUCCESS, E_SYSTEM, "It is failed to unregister reserved alarm list.");
474 r = RegisterAlarm(pAlarmImpl);
475 SysTryReturnResult(NID_SYS, r == E_SUCCESS, E_SYSTEM, "It is failed to register alarm.");
480 _AlarmManager::OnAlarmExpired(int alarmId)
482 result r = E_SUCCESS;
484 String* pAppId = null;
485 Integer* pPeriod = null;
487 std::unique_ptr<IEnumerator> pValueEnum(null);
488 Integer reservedAlarmId(alarmId);
489 DateTime* endTime = null;
490 _AlarmImpl* pAlarmImpl = null;
492 SysTryCatch(NID_SYS, __pAlarmHashMap != null, r = E_SYSTEM, r, "Alarm list does not initialized");
493 pValueEnum.reset(__pAlarmHashMap->GetValuesN(reservedAlarmId));
495 SysLog(NID_SYS, "Alarm expire event is delivered. alarm id is %d", alarmId);
497 pAlarmImpl = (_AlarmImpl*)__alarmList.GetValue(reservedAlarmId);
498 if(pAlarmImpl == null)
500 SysLog(NID_SYS, "pAlarmImpl of reserved alarm[%d] is not found.", alarmId);
503 if(pValueEnum != null)
505 ret = pthread_mutex_lock(&__lock);
506 SysTryCatch(NID_SYS, ret == 0, r = E_SYSTEM, r, "It is failed to lock mutex.");
508 SysLog(NID_SYS, "Matching Alarm Id is %d \n", alarmId);
509 r = pValueEnum->MoveNext();
510 SysTryCatch(NID_SYS, r == E_SUCCESS, r = E_SYSTEM, r, "Alarm enum value is not valid.");
511 pAppId = static_cast< String* >(pValueEnum->GetCurrent());
512 alarmAppId.Append(*pAppId);
513 r = pValueEnum->MoveNext();
514 pPeriod = static_cast< Integer* >(pValueEnum->GetCurrent());
515 SysTryCatch(NID_SYS, r == E_SUCCESS, r = E_SYSTEM, r, "Alarm enum value is not valid.");
517 if(pValueEnum->MoveNext() == E_SUCCESS)
519 endTime = static_cast< DateTime* >(pValueEnum->GetCurrent());
522 SysLog(NID_SYS, "Reserved Alarm AppId:%ls, Period:%d\n", pAppId->GetPointer(), pPeriod->ToInt());
524 if (pPeriod->ToInt() > 0)
528 DateTime currentTime;
530 SystemTime::GetCurrentTime(WALL_TIME, currentTime);
531 currentTime.AddMilliseconds(-1 * currentTime.GetMillisecond()); //Remove millisecond
532 currentTime.AddMinutes(pPeriod->ToInt());
533 SysLog(NID_SYS, "Next time[%d min]: %d:%d:%d:%d", pPeriod->ToInt(), currentTime.GetHour(), currentTime.GetMinute(), currentTime.GetSecond(), currentTime.GetMillisecond());
534 SysLog(NID_SYS, "Endtime exists %d:%d:%d:%d", endTime->GetHour(), endTime->GetMinute(), endTime->GetSecond(), endTime->GetMillisecond());
536 if (currentTime.CompareTo(*endTime) > 0)
538 SysLog(NID_SYS, "Next time is greater than end time.");
539 RemoveAlarmList(alarmId);
542 if(pAlarmImpl != null)
544 pAlarmImpl->__alarmId.value = 0;
549 else if (pPeriod->ToInt() == 0)
551 RemoveAlarmList(alarmId);
553 if(pAlarmImpl != null)
555 pAlarmImpl->__alarmId.value = 0;
563 ret = pthread_mutex_unlock(&__lock);
566 if(pAlarmImpl != null)
568 pAlarmImpl->OnAlarmExpired(alarmId);
571 if(__pAlarmHashMap->ContainsKey(reservedAlarmId) == false)
573 ret = pthread_mutex_lock(&__lock);
574 SysLog(NID_SYS, "Remove an alarm list[%d].", reservedAlarmId.value);
575 r = __alarmList.Remove(reservedAlarmId);
576 ret = pthread_mutex_unlock(&__lock);
581 ret = pthread_mutex_unlock(&__lock);
582 SysTryReturnVoidResult(NID_SYS, ret == 0, E_SYSTEM, "It is failed to unlock mutex.");