Tizen 2.1 base
[platform/framework/native/app-service.git] / plugins / alarm-condition-handler / AlarmConditionHandler.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         alarm_condition_candler.cpp
20  * @brief       This is the declaration file of the _AlarmConditionHandler class.
21  *
22  */
23
24 #include <new>
25 #include <unique_ptr.h>
26
27 #include <appfw/app.h>
28
29 #include <FBaseInteger.h>
30 #include <FSysSystemTime.h>
31 #include <FBaseUtilRegularExpression.h>
32
33 #include <FBase_StringConverter.h>
34 #include <FSys_AlarmImpl.h>
35
36 #include "AlarmConditionHandler.h"
37
38 using namespace std;
39
40 using namespace Tizen::App;
41 using namespace Tizen::Base;
42 using namespace Tizen::Base::Collection;
43 using namespace Tizen::Base::Utility;
44 using namespace Tizen::System;
45
46 namespace {
47         static const long _ADJUST_MONTH_FOR_TM = 1;
48         static const long _ADJUST_YEAR_FOR_TM = 1900;
49         static const long _SECOND_OF_MINUTE = 60;
50
51         static const int ALARM_CONDITION_FIELD = 1;
52         static const int ALARM_CONDITION_VALUE = 1;
53 }
54 _AlarmConditionHandler* pAlarmConditionHandler = null;
55 int RefAlarmConditionHandler = 0;
56 _AlarmConditionHandler*
57 _AlarmConditionHandler::GetInstance()
58 {
59         if(pAlarmConditionHandler == null)
60         {
61                 pAlarmConditionHandler = new (std::nothrow) _AlarmConditionHandler;
62         }
63         RefAlarmConditionHandler ++;
64         return pAlarmConditionHandler;
65 }
66
67 void
68 _AlarmConditionHandler::ReleaseInstance()
69 {
70         if(RefAlarmConditionHandler == 0)
71         {
72                 return;
73         }
74
75         RefAlarmConditionHandler --;
76         if(RefAlarmConditionHandler == 0)
77         {
78                 delete pAlarmConditionHandler;
79                 pAlarmConditionHandler = null;
80         }
81 }
82
83 _AlarmConditionHandler::_AlarmConditionHandler()
84 {
85         conditionList.Construct();
86 }
87
88 _AlarmConditionHandler::~_AlarmConditionHandler()
89 {
90 }
91
92 result
93 _AlarmConditionHandler::Convert(_AppLaunchCondition& appLaunchCondition, struct tm* pConvertedTime, int& period)
94 {
95         int ret = 0;
96         char garbage[128] = {0};
97         SysTryReturnResult(NID_SYS, pConvertedTime != null, E_INVALID_ARG, "pConvertedTime is null");
98
99         String buf(appLaunchCondition.GetConditionString());
100         SysLog(NID_SYS, "%ls", buf.GetPointer());
101         unique_ptr<char[]> convertedString(_StringConverter::CopyToCharArrayN(buf));
102         SysTryReturnResult(NID_SYS, convertedString.get() != null, E_OUT_OF_MEMORY, "Memory allocation failure.");
103
104         if(buf.StartsWith(L"DueTime", 0) == true)
105         {
106
107                 ret = sscanf(convertedString.get(), "DueTime='%d/%d/%d %d:%d:%d' LaunchPeriod='%d'%s", &(pConvertedTime->tm_mon), &(pConvertedTime->tm_mday), &(pConvertedTime->tm_year), &(pConvertedTime->tm_hour), &(pConvertedTime->tm_min), &(pConvertedTime->tm_sec), &period, &garbage);
108
109                 SysTryReturnResult(NID_SYS, ret == 7, E_INVALID_FORMAT, "The specified condition format is not compatible.");
110         }
111         else if(buf.StartsWith(L"DateTime", 0) == true)
112         {
113                 ret = sscanf(convertedString.get(), "DateTime='%d/%d/%d %d:%d:%d'%s", &(pConvertedTime->tm_mon), &(pConvertedTime->tm_mday), &(pConvertedTime->tm_year), &(pConvertedTime->tm_hour), &(pConvertedTime->tm_min), &(pConvertedTime->tm_sec), &garbage);
114                 SysTryReturnResult(NID_SYS, ret == 6, E_INVALID_FORMAT, "The specified condition format is not compatible.");   
115         }
116         else
117         {
118                 SysLog(NID_SYS, "wrong alarm condition");
119                 return E_INVALID_FORMAT;
120         }
121         return E_SUCCESS;
122 }
123
124 result
125 _AlarmConditionHandler::Register( _AppLaunchCondition& appLaunchCondition)
126 {
127         //For condition parsing.
128         int ret = 0;
129
130         //For alarm reserve.
131         struct tm expireTime = {0,};
132         int period = 0;
133         int reservedAlarmId = -1;
134         service_h service = null;
135         char* packageName = null;
136         result r = E_SUCCESS;
137         _AppLaunchCondition* pReservedCondition = null;
138
139         r = Convert(appLaunchCondition, &expireTime, period);
140         SysTryReturnResult(NID_SYS, r == E_SUCCESS, E_INVALID_FORMAT, "It is not valid date time format.");
141
142         DateTime validationCheck;
143         r =  validationCheck.SetValue(expireTime.tm_year, expireTime.tm_mon, expireTime.tm_mday, expireTime.tm_hour, expireTime.tm_min, expireTime.tm_sec);
144         SysTryReturnResult(NID_SYS, r == E_SUCCESS, E_INVALID_CONDITION, "It is not valid date time.");
145
146         DateTime currentTime;
147         SystemTime::GetCurrentTime(TIME_MODE_WALL, currentTime);
148
149         TimeSpan validateTs(validationCheck.GetTime());
150         TimeSpan currentTs(currentTime.GetTime());
151
152         if(appLaunchCondition.GetConditionString().StartsWith(L"DueTime", 0) == true)
153         {
154                 SysTryReturnResult(NID_SYS, period >= 60 && period <= 525600, E_INVALID_CONDITION, "Required period is not valid. (%d)", period);
155         }
156
157         SysTryReturnResult(NID_SYS, (validateTs.GetTicks() - currentTs.GetTicks()) > 0 , E_INVALID_CONDITION, "Required time does not greater thancurrent time. (%lld)", validateTs.GetTicks() - currentTs.GetTicks());
158
159         unique_ptr<IMapEnumerator>pMapEnum(conditionList.GetMapEnumeratorN());
160
161         while(pMapEnum->MoveNext() == E_SUCCESS)
162         {
163                 struct tm reservedTime = {0,};
164                 int reservedPeriod = 0;
165                 pReservedCondition = static_cast<_AppLaunchCondition*>(pMapEnum->GetValue());
166                 r = Convert(*pReservedCondition, &reservedTime, reservedPeriod);
167                 SysTryReturnResult(NID_SYS, r == E_SUCCESS, E_SYSTEM, "Reserved condition has wrong format.");
168
169                 if(reservedPeriod == period && expireTime.tm_year == reservedTime.tm_year
170                         && expireTime.tm_mon == reservedTime.tm_mon && expireTime.tm_mday == reservedTime.tm_mday
171                         && expireTime.tm_hour == reservedTime.tm_hour && expireTime.tm_min == reservedTime.tm_min
172                         && expireTime.tm_sec == reservedTime.tm_sec)
173                 {
174                         SysLogException(NID_SYS, E_OBJ_ALREADY_EXIST, "The specified condition is already registered.");
175                         return E_OBJ_ALREADY_EXIST;
176                 }               
177         }
178
179         expireTime.tm_year -= _ADJUST_YEAR_FOR_TM;
180         expireTime.tm_mon -= _ADJUST_MONTH_FOR_TM;
181
182         ret = service_create(&service);
183         SysTryCatch(NID_SYS, ret == SERVICE_ERROR_NONE, r = E_SYSTEM, r, "It is failed to create service");
184
185         ret = app_get_package(&packageName);
186         SysTryCatch(NID_SYS, ret == APP_ERROR_NONE, r = E_SYSTEM, r, "It is failed to get package name");
187
188         ret = service_set_operation(service, "osp.appsvc.operation.ALARM");
189         SysTryCatch(NID_SYS, ret == SERVICE_ERROR_NONE, r = E_SYSTEM, r, "It is failed to set operation");
190
191         ret = service_set_package(service, packageName);
192         SysTryCatch(NID_SYS, ret == SERVICE_ERROR_NONE, r = E_SYSTEM, r, "It is failed to create service for %s", packageName);
193         
194         ret = alarm_schedule_at_date(service, &expireTime, period * _SECOND_OF_MINUTE, &reservedAlarmId);
195         SysTryCatch(NID_SYS, ret == ALARM_ERROR_NONE, r = E_SYSTEM, r, "It is failed to set the Alarm time for %s", packageName);
196
197         r = conditionList.Add(new Integer(reservedAlarmId), &appLaunchCondition);
198
199         if(r == E_OBJ_ALREADY_EXIST)
200         {
201                 SysLogException(NID_SYS, E_OBJ_ALREADY_EXIST, "The sspecified condition is already registered.");
202                 r = E_OBJ_ALREADY_EXIST;
203         }
204         else if(r != E_SUCCESS)
205         {
206                 SysLogException(NID_SYS, E_SYSTEM, "It is failed to register requested condition.");
207                 r = E_SYSTEM;
208         }
209
210 CATCH:
211         if (packageName != null)
212         {
213                 free (packageName);
214         }
215
216         if (service != null)
217         {
218                 service_destroy(service);
219         }
220
221         return r;
222 }
223
224
225 result
226 _AlarmConditionHandler::Unregister( _AppLaunchCondition& appLaunchCondition)
227 {
228         unique_ptr<IMapEnumerator> pMapEnum(conditionList.GetMapEnumeratorN());
229         Integer* pKey = null;
230         _AppLaunchCondition* pAppLaunchCondition = null;
231         result r = E_SYSTEM;
232
233         SysTryReturnResult(NID_SYS, pMapEnum != null, E_SYSTEM, "Reserved condition list is empty");
234
235         while(pMapEnum->MoveNext() == E_SUCCESS)
236         {
237                 pKey = static_cast<Integer *>(pMapEnum->GetKey());
238                 pAppLaunchCondition = static_cast<_AppLaunchCondition *>(pMapEnum->GetValue());
239
240                 if(appLaunchCondition.GetConditionString() == "")
241                 {
242                         if(appLaunchCondition.GetAppId() == pAppLaunchCondition->GetAppId())
243                         {
244                                 alarm_cancel(pKey->ToInt());
245                                 conditionList.Remove(*pKey);
246                                 delete pKey;
247                                 r = E_SUCCESS;
248                         }
249                 }
250                 else
251                 {
252                         if(appLaunchCondition.GetAppId() == pAppLaunchCondition->GetAppId()
253                                 && appLaunchCondition.GetConditionString() == pAppLaunchCondition->GetConditionString())
254                         {
255                                 alarm_cancel(pKey->ToInt());
256                                 conditionList.Remove(*pKey);
257                                 delete pKey;
258                                 r = E_SUCCESS;
259                         }
260                 }
261
262         }
263         return r;
264 }
265
266 _AppLaunchCondition*
267 _AlarmConditionHandler::GetAppLaunchCondition(int alarmId)
268 {
269         SysLog(NID_SYS, "Try to find condition");
270         unique_ptr<IMapEnumerator> pMapEnum(conditionList.GetMapEnumeratorN());
271         Integer* pKey = null;
272         _AppLaunchCondition* pAppLaunchCondition = null;
273         _AppLaunchCondition* pReservedCondition = null;
274
275         if(pMapEnum == null)
276         {
277                 SysLog(NID_SYS, "Reserved condition list is empty");
278                 return null;
279         }
280         
281         while(pMapEnum->MoveNext() == E_SUCCESS)
282         {
283                 pKey = static_cast<Integer *>(pMapEnum->GetKey());
284                 pAppLaunchCondition = static_cast<_AppLaunchCondition *>(pMapEnum->GetValue());
285                 if(pKey->ToInt() == alarmId)
286                 {
287                         pReservedCondition = pAppLaunchCondition;
288                         break;
289                 }
290         }
291         return pReservedCondition;
292 }
293
294 result
295 _AlarmConditionHandler::Launch(const Tizen::App::_AppLaunchCondition& condition)
296 {
297         return Fire(condition);
298 }
299
300 //////////////////////////////////////////////////////////////
301 //      All plugins must provide both a creation and a destruction function
302 /////////////////////////////////////////////////////////////
303 extern "C"
304 {
305 _OSP_EXPORT_ _AppLaunchConditionHandlerBase*
306 CreatePlugin(void)
307 {
308         return _AlarmConditionHandler::GetInstance();
309 }
310
311 _OSP_EXPORT_ void
312 DestroyPlugin(_AppLaunchConditionHandlerBase* p)
313 {
314          _AlarmConditionHandler::ReleaseInstance();
315 }
316
317 _OSP_EXPORT_ void
318 OnAlarmForLaunch(int alarmId)
319 {
320         SysLog(NID_SYS, "Alarm request %d", alarmId);
321         _AppLaunchCondition* pAppLaunchCondition = null;
322         _AlarmConditionHandler* pAlarmConditionHandler = _AlarmConditionHandler::GetInstance();
323         pAppLaunchCondition = pAlarmConditionHandler->GetAppLaunchCondition(alarmId);
324                 if(pAppLaunchCondition != null)
325         {
326                 SysLog(NID_SYS, "Launch Request");
327                 pAlarmConditionHandler->Launch(*pAppLaunchCondition);
328         }
329         _AlarmConditionHandler::ReleaseInstance();
330 }
331
332 }//extern "C"