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
89 int alarm_callback(alarm_id_t alarmId, void *user_param)
91 _AlarmManager* pAlarmManager = _AlarmManager::GetInstance();
92 pAlarmManager->OnAlarmExpired((int)alarmId);
97 _AlarmManager::Construct(void)
100 Tizen::App::App* pApp = null;
101 pApp = Tizen::App::App::GetInstance();
102 String appId = pApp->GetAppId();
103 std::unique_ptr<char[]> pAppId(_StringConverter::CopyToCharArrayN(appId));
105 errorCode = alarmmgr_init(pAppId.get());
106 SysTryReturnResult(NID_SYS, errorCode == ALARMMGR_RESULT_SUCCESS, E_SYSTEM, "It is failed to init alarmmgr. error [%d]", errorCode);
107 errorCode = alarmmgr_set_cb(alarm_callback, null);
108 SysTryReturnResult(NID_SYS, errorCode == ALARMMGR_RESULT_SUCCESS, E_SYSTEM, "It is failed to set cb to alarmmgr. error [%d]", errorCode);
113 _AlarmManager::GetInstance(void)
115 static pthread_once_t onceBlock = PTHREAD_ONCE_INIT;
116 if(__pAlarmManager == null)
118 pthread_once(&onceBlock, InitSingleton);
120 return __pAlarmManager;
124 _AlarmManager::InitSingleton(void)
126 result r = E_SUCCESS;
127 _AlarmManager* pAlarmManager = new (std::nothrow) _AlarmManager();
128 SysTryReturnVoidResult(NID_SYS, pAlarmManager, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
129 GetErrorMessage(E_OUT_OF_MEMORY));
130 r = pAlarmManager->Construct();
131 SysTryReturnVoidResult(NID_SYS, r == E_SUCCESS, E_SYSTEM, "It is failed to construct alarm manager.");
132 __pAlarmManager = pAlarmManager;
133 std::atexit(DestroySingleton);
137 _AlarmManager::DestroySingleton(void)
139 delete __pAlarmManager;
143 _AlarmManager::ReserveAlarm(Tizen::Base::String appId, Tizen::Base::DateTime startTime, int period)
145 int reservedAlarmId = -1;
146 result r = E_SUCCESS;
151 SysLog(NID_SYS, "Reserve time is %d/%d/%d %d:%d:%d", startTime.GetYear(), startTime.GetMonth(), startTime.GetDay(), startTime.GetHour(), startTime.GetMinute(), startTime.GetSecond());
153 bundle* pBundle = null;
154 alarm_entry_t* pAlarmInfo = null;
155 alarm_date_t expireTime = {0,};
157 std::unique_ptr<char[]> pId(_StringConverter::CopyToCharArrayN(appId));
159 pBundle = bundle_create();
160 SysTryCatch(NID_SYS, pBundle != null, r = E_SYSTEM, r, "It is failed to create bundle");
162 ret = appsvc_set_operation(pBundle,"osp.operation.ALARM");
163 SysTryCatch(NID_SYS, ret == SERVICE_ERROR_NONE, r = E_SYSTEM, r, "It is failed to set operation");
165 ret = appsvc_set_appid(pBundle, (const char*)(pId.get()));
166 SysTryCatch(NID_SYS, ret == SERVICE_ERROR_NONE, r = E_SYSTEM, r, "It is failed to set appid for %ls", appId.GetPointer());
168 pAlarmInfo = alarmmgr_create_alarm();
169 SysTryCatch(NID_SYS, pAlarmInfo != null, r = E_SYSTEM, r, "It is failed to create alarm entry");
171 expireTime.year = startTime.GetYear();
172 expireTime.month = startTime.GetMonth();
173 expireTime.day = startTime.GetDay();
174 expireTime.hour = startTime.GetHour();
175 expireTime.min = startTime.GetMinute();
176 expireTime.sec = startTime.GetSecond();
178 ret = alarmmgr_set_time(pAlarmInfo, expireTime);
179 SysTryCatch(NID_SYS, ret == ALARMMGR_RESULT_SUCCESS, r = E_SYSTEM, r, "It is failed to set new alarm time");
183 SysLog(NID_SYS, "It is repeated alarm and period time is %d minutes", period);
184 ret = alarmmgr_set_repeat_mode(pAlarmInfo, ALARM_REPEAT_MODE_REPEAT, period * _SECOND_OF_MINUTE);
185 SysTryCatch(NID_SYS, ret == ALARMMGR_RESULT_SUCCESS, r = E_SYSTEM, r, "It is failed to set repeat mode");
188 ret = alarmmgr_set_type(pAlarmInfo, ALARM_TYPE_NOLAUNCH);
189 SysTryCatch(NID_SYS, ret == ALARMMGR_RESULT_SUCCESS, r = E_SYSTEM, r, "It is failed to set repeat mode");
191 ret = alarmmgr_add_alarm_with_localtime(pAlarmInfo, null, &reservedAlarmId);
192 SysTryCatch(NID_SYS, ret == ALARMMGR_RESULT_SUCCESS, r = E_SYSTEM, r, "Alarm creation failed!!! Alrmgr error code is %d", ret);
197 reservedAlarmId = -1;
199 if(pAlarmInfo != null)
201 alarmmgr_free_alarm(pAlarmInfo);
206 bundle_free(pBundle);
209 return reservedAlarmId;
213 _AlarmManager::AddAlarmList(int alarmId, int period, String appId, DateTime* endTime)
215 result r = E_SUCCESS;
217 SysTryReturnResult(NID_SYS, __pAlarmHashMap != null, E_SYSTEM, "Alarm list does not initialized");
218 SysLog(NID_SYS, "New Alarm Id is added (%d, %d, %ls)", alarmId, period, appId.GetPointer());
220 Integer* reservedAlarmId = null;
221 Integer* alarmPeriod = null;
222 String* alarmAppId = null;
224 Integer* reverseAlarmId = null;
225 String* reverseAppId = null;
227 reservedAlarmId = new (std::nothrow) Integer(alarmId);
228 SysTryCatch(NID_SYS, reservedAlarmId != null, r = E_SYSTEM, E_SYSTEM, "reservedAlarmId should not be null");
230 alarmPeriod = new (std::nothrow) Integer(period);
231 SysTryCatch(NID_SYS, alarmPeriod != null, r = E_SYSTEM, E_SYSTEM, "alarmPeriod should not be null");
233 alarmAppId = new (std::nothrow) String(appId);
234 SysTryCatch(NID_SYS, alarmAppId != null, r = E_SYSTEM, E_SYSTEM, "alarmAppId should not be null");
237 r = __pAlarmHashMap->Add(*reservedAlarmId, *alarmAppId);
238 SysTryCatch(NID_SYS, r == E_SUCCESS, r, r, "Fail to add new alarm app id on the alarm list");
240 r = __pAlarmHashMap->Add(*reservedAlarmId, *alarmPeriod);
241 SysTryCatch(NID_SYS, r == E_SUCCESS, r, r, "Fail to add new alarm period on the alarm list");
245 DateTime* alarmEndTime = new DateTime(*endTime);
247 SysLog(NID_SYS, "Endtime exists %d:%d:%d", alarmEndTime->GetHour(), alarmEndTime->GetMinute(), alarmEndTime->GetSecond());
248 r = __pAlarmHashMap->Add(*reservedAlarmId, *alarmEndTime);
249 SysTryCatch(NID_SYS, r == E_SUCCESS, r, r, "Fail to add new alarm endtime on the alarm list");
253 reverseAlarmId = new (std::nothrow) Integer(alarmId);
254 SysTryCatch(NID_SYS, reverseAlarmId != null, r = E_SYSTEM, E_SYSTEM, "reverseAlarmId should not be null");
256 reverseAppId = new (std::nothrow) String(appId);
257 SysTryCatch(NID_SYS, reverseAppId != null, r = E_SYSTEM, E_SYSTEM, "reverseAppId should not be null");
259 r = __pAlarmHashMap->Add(*reverseAppId, *reverseAlarmId);
260 SysTryCatch(NID_SYS, r == E_SUCCESS, r, r, "Fail to add new alarm on the alarm list");
265 if(reservedAlarmId != null)
267 __pAlarmHashMap->Remove(*reservedAlarmId, false);
268 delete reservedAlarmId;
271 if(alarmPeriod != null)
276 if(alarmAppId != null)
281 if(reverseAppId != null)
283 __pAlarmHashMap->Remove(*reverseAppId, false);
287 if(reverseAlarmId != null)
289 delete reverseAlarmId;
296 _AlarmManager::RemoveAlarmList(int alarmId)
298 result r = E_SUCCESS;
299 Integer requiredAlarmId(alarmId);
300 std::unique_ptr<IEnumerator>pValueEnum(null);
302 SysTryReturnResult(NID_SYS, __pAlarmHashMap != null, E_SYSTEM, "Alarm list does not initialized");
304 alarm_cancel(alarmId);
305 SysLog(NID_SYS, "AlarmId %d disarms the timer.", alarmId);
307 pValueEnum.reset(__pAlarmHashMap->GetValuesN(requiredAlarmId));
309 if(pValueEnum != null)
311 SysLog(NID_SYS, "Reserved Alarms are exist");
312 String* alarmAppId = null;
313 r = pValueEnum->MoveNext();
314 SysTryReturnResult(NID_SYS, r == E_SUCCESS, E_SYSTEM, "Reserved Alarm List is not valid.");
315 alarmAppId = static_cast< String* >(pValueEnum->GetCurrent());
317 if(alarmAppId != null)
319 SysLog(NID_SYS, "Alarm AppId is %S", alarmAppId->GetPointer());
320 std::unique_ptr<IEnumerator>pAlarmEnum(__pAlarmHashMap->GetValuesN(*alarmAppId));
321 if(pAlarmEnum != null)
323 while(pAlarmEnum->MoveNext() == E_SUCCESS)
325 Integer* reverseAlarmId = static_cast< Integer* >(pAlarmEnum->GetCurrent());
326 if(reverseAlarmId != null)
328 SysLog(NID_SYS, "Reserved Alarm is %d", reverseAlarmId->ToInt());
329 if(reverseAlarmId->ToInt() == alarmId)
331 SysLog(NID_SYS, "Remove reservedAlarmId for reverse look-up");
332 __pAlarmHashMap->Remove(*alarmAppId, *reverseAlarmId);
333 delete reverseAlarmId;
341 __pAlarmHashMap->GetCount(*alarmAppId, count);
344 SysLog(NID_SYS, "There is no more reserved alarm for AppId:%S", alarmAppId->GetPointer());
345 __pAlarmHashMap->Remove(*alarmAppId, true);
349 r = __pAlarmHashMap->Remove(requiredAlarmId, true);
355 _AlarmManager::RemoveAlarmList(String appId)
357 result r = E_SUCCESS;
358 Integer requiredAlarmId;
359 IEnumerator *pValueEnum = null;
361 SysTryReturnResult(NID_SYS, __pAlarmHashMap != null, E_SYSTEM, "Alarm list does not initialized");
362 pValueEnum = __pAlarmHashMap->GetValuesN(appId);
364 if(pValueEnum != null)
366 SysLog(NID_SYS, "Reserved Alarms are exist for AppId:%S", appId.GetPointer());
367 while(pValueEnum->MoveNext() == E_SUCCESS)
369 Integer* reverseAlarmId = static_cast< Integer* >(pValueEnum->GetCurrent());
370 if(reverseAlarmId != null)
372 SysLog(NID_SYS, "Reserved AlarmId is %d", reverseAlarmId->ToInt());
373 alarm_cancel(reverseAlarmId->ToInt());
374 __pAlarmHashMap->Remove(*reverseAlarmId, true);
379 r = __pAlarmHashMap->Remove(appId, true);
385 _AlarmManager::RegisterAlarm(_AlarmImpl* pAlarmImpl)
387 SysTryReturnResult(NID_SYS, pAlarmImpl != null, E_INVALID_ARG, "There is no alarmImpl.");
388 Integer alarmId(pAlarmImpl->__alarmId.value);
389 SysTryReturnResult(NID_SYS, __alarmList.ContainsKey(alarmId) == false, E_OBJ_ALREADY_EXIST, "Required Alarm[%d] is already registered.", pAlarmImpl->__alarmId.value);
391 result r = E_SUCCESS;
392 ArrayList requestMessage;
393 ArrayList responseMessage;
400 int reservedAlarmId = 0;
401 int period = pAlarmImpl->GetPeriod();
403 Tizen::App::App* pApp = null;
405 DateTime currentTime;
406 DateTime startTime = pAlarmImpl->GetStartTime();
407 const DateTime* pEndTime = pAlarmImpl->GetEndTime();
411 startTime.AddMilliseconds(-1 * startTime.GetMillisecond());
412 r = SystemTime::GetCurrentTime(WALL_TIME, currentTime);
413 currentTime.AddMilliseconds(-1 * currentTime.GetMillisecond());
415 SysTryReturnResult(NID_SYS, r == E_SUCCESS, E_SYSTEM, "It is failed to get current time.");
416 SysTryReturnResult(NID_SYS, DateTime::Compare(currentTime, startTime) < 0, E_INVALID_ARG, "Designated start time has to be greater than current time.");
417 SysTryReturnResult(NID_SYS, period > -1, E_INVALID_ARG, "Period has to greater than -1");
419 ret = pthread_mutex_lock(&__lock);
420 SysTryCatch(NID_SYS, ret == 0, r = E_INVALID_ARG, r, "It is failed to lock mutex.");
425 endTime.AddMilliseconds(-1 * endTime.GetMillisecond());
427 SysTryCatch(NID_SYS, DateTime::Compare(startTime, endTime) < 0, r = E_INVALID_ARG, r, "Designated end time is less than start time.");
429 //End Alarm validation check
431 pApp = Tizen::App::App::GetInstance();
432 SysTryCatch(NID_SYS, pApp != null, r = E_SYSTEM, r, "[%s] A system error has been occurred. App::GetInstance() failed.", GetErrorMessage(E_SYSTEM));
433 appId = pApp->GetAppId();
435 reservedAlarmId = ReserveAlarm(appId, startTime, period);
436 SysTryCatch(NID_SYS, reservedAlarmId != -1, r = E_SYSTEM, r, "It is failed to register alarm.");
438 SysLog(NID_SYS, "Reserved AppId %ls, alarmId: %d", appId.GetPointer(), reservedAlarmId);
442 r = AddAlarmList(reservedAlarmId, period, appId, null);
446 r = AddAlarmList(reservedAlarmId, period, appId, (DateTime*)(&endTime));
448 SysTryCatch(NID_SYS, r == E_SUCCESS, r = E_SYSTEM, r, "It is failed to add new alarm on the alarm list.");
450 pAlarmImpl->__alarmId.value = reservedAlarmId;
451 r = __alarmList.Add(&(pAlarmImpl->__alarmId), pAlarmImpl);
454 ret = pthread_mutex_unlock(&__lock);
455 SysTryReturnResult(NID_SYS, ret == 0, E_INVALID_ARG, "It is failed to unlock mutex.");
460 _AlarmManager::UnregisterAlarm(_AlarmImpl* pAlarmImpl)
462 result r = E_SUCCESS;
465 SysLog(NID_SYS, "Alarm Cancel request");
466 SysTryCatch(NID_SYS, pAlarmImpl != null, r = E_INVALID_ARG, r, "There is no alarmImpl.");
468 ret = pthread_mutex_lock(&__lock);
469 SysTryCatch(NID_SYS, ret == 0, r = E_SYSTEM, r, "It is failed to lock mutex.");
471 alarmId.value = pAlarmImpl->__alarmId.value;
472 SysTryCatch(NID_SYS, __alarmList.ContainsKey(alarmId) == true, r = E_OBJ_NOT_FOUND, r, "There is no registered alarm.");
474 r = __alarmList.Remove(alarmId);
475 SysTryCatch(NID_SYS, r == E_SUCCESS, r = E_SYSTEM, r, "It is failed to remove reserved alarmImpl instance.");
477 r = RemoveAlarmList(alarmId.ToInt());
478 SysTryCatch(NID_SYS, r == E_SUCCESS, r = E_SYSTEM, r, "It is failed to remove reserved alarm list.");
481 ret = pthread_mutex_unlock(&__lock);
482 SysTryReturnResult(NID_SYS, ret == 0, E_SYSTEM, "It is failed to unlock mutex.");
487 _AlarmManager::UpdateAlarm(_AlarmImpl* pAlarmImpl)
489 result r = E_SUCCESS;
491 SysTryReturnResult(NID_SYS, pAlarmImpl != null, E_SYSTEM, "There is no alarmImpl.");
493 alarmId.value = pAlarmImpl->__alarmId.value;
494 SysTryReturnResult(NID_SYS, __alarmList.ContainsKey(alarmId) == true, E_SYSTEM, "There is no registered alarm.");
496 r = UnregisterAlarm(pAlarmImpl);
497 SysTryReturnResult(NID_SYS, r == E_SUCCESS, E_SYSTEM, "It is failed to unregister reserved alarm list.");
499 r = RegisterAlarm(pAlarmImpl);
500 SysTryReturnResult(NID_SYS, r == E_SUCCESS, E_SYSTEM, "It is failed to register alarm.");
505 _AlarmManager::OnAlarmExpired(int alarmId)
507 result r = E_SUCCESS;
509 String* pAppId = null;
510 Integer* pPeriod = null;
512 std::unique_ptr<IEnumerator> pValueEnum(null);
513 Integer reservedAlarmId(alarmId);
514 DateTime* endTime = null;
515 _AlarmImpl* pAlarmImpl = null;
517 SysTryCatch(NID_SYS, __pAlarmHashMap != null, r = E_SYSTEM, r, "Alarm list does not initialized");
519 ret = pthread_mutex_lock(&__lock);
520 SysTryReturnVoidResult(NID_SYS, ret == 0, E_SYSTEM, "It is failed to lock mutex.");
522 pValueEnum.reset(__pAlarmHashMap->GetValuesN(reservedAlarmId));
524 SysLog(NID_SYS, "Alarm expire event is delivered. alarm id is %d", alarmId);
526 pAlarmImpl = (_AlarmImpl*)__alarmList.GetValue(reservedAlarmId);
527 if(pAlarmImpl == null)
529 SysLog(NID_SYS, "pAlarmImpl of reserved alarm[%d] is not found.", alarmId);
532 if(pValueEnum != null)
534 SysLog(NID_SYS, "Matching Alarm Id is %d \n", alarmId);
536 r = pValueEnum->MoveNext();
537 SysTryCatch(NID_SYS, r == E_SUCCESS, r = E_SYSTEM, r, "Alarm enum value is not valid.");
538 pAppId = static_cast< String* >(pValueEnum->GetCurrent());
539 alarmAppId.Append(*pAppId);
540 r = pValueEnum->MoveNext();
541 pPeriod = static_cast< Integer* >(pValueEnum->GetCurrent());
542 SysTryCatch(NID_SYS, r == E_SUCCESS, r = E_SYSTEM, r, "Alarm enum value is not valid.");
544 if(pValueEnum->MoveNext() == E_SUCCESS)
546 endTime = static_cast< DateTime* >(pValueEnum->GetCurrent());
549 SysLog(NID_SYS, "Reserved Alarm AppId:%ls, Period:%d\n", pAppId->GetPointer(), pPeriod->ToInt());
551 if (pPeriod->ToInt() > 0)
555 DateTime currentTime;
557 SystemTime::GetCurrentTime(WALL_TIME, currentTime);
558 currentTime.AddMilliseconds(-1 * currentTime.GetMillisecond()); //Remove millisecond
559 currentTime.AddMinutes(pPeriod->ToInt());
560 SysLog(NID_SYS, "Next time[%d min]: %d:%d:%d:%d", pPeriod->ToInt(), currentTime.GetHour(), currentTime.GetMinute(), currentTime.GetSecond(), currentTime.GetMillisecond());
561 SysLog(NID_SYS, "Endtime exists %d:%d:%d:%d", endTime->GetHour(), endTime->GetMinute(), endTime->GetSecond(), endTime->GetMillisecond());
563 if (currentTime.CompareTo(*endTime) > 0)
565 SysLog(NID_SYS, "Next time is greater than end time.");
566 RemoveAlarmList(alarmId);
569 if(pAlarmImpl != null)
571 pAlarmImpl->__alarmId.value = 0;
576 else if (pPeriod->ToInt() == 0)
578 RemoveAlarmList(alarmId);
580 if(pAlarmImpl != null)
582 pAlarmImpl->__alarmId.value = 0;
592 ret = pthread_mutex_unlock(&__lock);
594 if(pAlarmImpl != null)
596 pAlarmImpl->OnAlarmExpired(alarmId);
599 if(__pAlarmHashMap->ContainsKey(reservedAlarmId) == false)
601 ret = pthread_mutex_lock(&__lock);
602 SysLog(NID_SYS, "Remove an alarm list[%d].", reservedAlarmId.value);
603 r = __alarmList.Remove(reservedAlarmId);
604 ret = pthread_mutex_unlock(&__lock);
611 ret = pthread_mutex_unlock(&__lock);
612 SysTryReturnVoidResult(NID_SYS, ret == 0, E_SYSTEM, "It is failed to unlock mutex.");