merge with master
[framework/osp/locations.git] / src / FLoc_LocationProviderImpl.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        FLoc_LocationProviderImpl.cpp
20  * @brief       This is the implementation file for the %_LocationProviderImpl class.
21  *
22  * This implementation file contains the definitions of the %_LocationProviderImpl class methods.
23  */
24
25 #include <unique_ptr.h>
26 #include <FApp_AppManagerImpl.h>
27 #include <FAppApp.h>
28 #include <FAppTypes.h>
29 #include <FAppUiApp.h>
30 #include <FBaseColArrayList.h>
31 #include <FBaseDouble.h>
32 #include <FBaseRtEvent.h>
33 #include <FBaseRtTimer.h>
34 #include <FBaseSysLog.h>
35 #include <FLocLocationCriteria.h>
36 #include <FLocCoordinates.h>
37 #include <FLocILocationProviderListener.h>
38 #include <FLocLocation.h>
39 #include <FLocTypes.h>
40 #include <FSysPowerManager.h>
41 #include <FSysSystemTime.h>
42 #include <FSys_AlarmImpl.h>
43 #include <FSys_SettingInfoImpl.h>
44 #include "FLoc_Config.h"
45 #include "FLoc_LocationImpl.h"
46 #include "FLoc_LocationManager.h"
47 #include "FLoc_LocationMonitor.h"
48 #include "FLoc_LocationProviderImpl.h"
49 #include "FLoc_MathUtils.h"
50 #include "FLoc_Types.h"
51
52 using namespace Tizen::App;
53 using namespace Tizen::Base;
54 using namespace Tizen::Base::Collection;
55 using namespace Tizen::Base::Runtime;
56 using namespace Tizen::Base::Utility;
57 using namespace Tizen::System;
58 using namespace std;
59
60 namespace Tizen { namespace Locations
61 {
62
63 _LocationProviderImpl::_LocationProviderImpl(void)
64         : Tizen::Base::Runtime::_Event()
65         , __lastLocationAccuracy(LOC_ACCURACY_INVALID)
66         , __pLocationListener(null)
67         , __pLocationManager(null)
68 {
69 }
70
71 _LocationProviderImpl::~_LocationProviderImpl(void)
72 {
73         UiApp* pAppInstance = Tizen::App::UiApp::GetInstance();
74         if (pAppInstance)
75         {
76                 _AppManagerImpl* pAppManager = _AppManagerImpl::GetInstance();
77                 if (pAppManager)
78                 {
79                         pAppManager->RemoveActiveAppEventListener(*this);
80                 }
81         }
82
83         StopLocationUpdates();
84         RemoveAllMonitoringRegions();
85 }
86
87 result
88 _LocationProviderImpl::Construct(const LocationCriteria& criteria, ILocationProviderListener& listener)
89 {
90         result r = E_SUCCESS;
91         _LocationManager* pLocationManager = null;
92
93         pLocationManager = _LocationManager::GetInstance();
94         SysTryReturn(NID_LOC, pLocationManager != null, GetLastResult(), GetLastResult(), "[%s] Failed to get the location manager instance.", GetErrorMessage(GetLastResult()));
95
96         std::unique_ptr< Tizen::Base::Collection::ArrayList, AllElementsDeleter > pRegionList(new (std::nothrow) ArrayList());
97         SysTryReturn(NID_LOC, pRegionList != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
98
99         r = pRegionList->Construct();
100         SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Failed to construct the list. Propagating.", GetErrorMessage(r));
101
102         std::unique_ptr< Tizen::Base::Runtime::Timer> pTimer (new (std::nothrow) Timer());
103         SysTryReturn(NID_LOC, pTimer != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
104
105         r = pTimer->Construct(*this);
106         SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Failed to construct the timer. Propagating.", GetErrorMessage(r));
107
108         std::unique_ptr< Tizen::System::Alarm> pAlarm (new (std::nothrow) Alarm());
109         SysTryReturn(NID_LOC, pAlarm != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
110
111         r = pAlarm->Construct(*this);
112         SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Failed to construct the alarm. Propagating.", GetErrorMessage(r));
113
114         UiApp* pAppInstance = Tizen::App::UiApp::GetInstance();
115         if (pAppInstance != null)
116         {
117                 _AppManagerImpl* pAppManager = _AppManagerImpl::GetInstance();
118                 SysTryReturn(NID_LOC, pAppManager, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] System error occured.");
119
120                 r = pAppManager->AddActiveAppEventListener(*this);
121                 SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Error occured during adding the event listener to app manager. Propagating.", GetErrorMessage(r));
122         }
123
124         std::unique_ptr< Tizen::Locations::Location > pLastLocation(_LocationImpl::GetLocationInstanceN());
125         SysTryReturn(NID_LOC, pLastLocation != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
126
127         std::unique_ptr<Tizen::Locations::Location> pLastRegionLocation (_LocationImpl::GetLocationInstanceN());
128         SysTryReturn(NID_LOC, pLastRegionLocation != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
129
130         _Event::Initialize();
131         _Event::AddListener(*this);
132
133         __regionMonitor.pRegionList = std::move(pRegionList);
134         __regionMonitor.pTimer = std::move(pTimer);
135         __regionMonitor.pAlarm = std::move(pAlarm);
136         __regionMonitor.pLocation = std::move(pLastRegionLocation);
137         __locationUpdater.pLocation = std::move(pLastLocation);
138         
139         __criteria = criteria;
140         __pLocationListener = &listener;
141         __pLocationManager = pLocationManager;
142
143         SysLog(NID_LOC, "Location provider constructed with the accuracy (%x).", criteria.GetAccuracy());
144
145         return E_SUCCESS;
146 }
147
148 result
149 _LocationProviderImpl::StartLocationUpdatesByInterval(int interval)
150 {
151         bool userConsent = GetUserPrivilege();
152         SysTryReturn(NID_LOC, userConsent, E_USER_NOT_CONSENTED, E_USER_NOT_CONSENTED, "[E_USER_NOT_CONSENTED] The user has disabled the required settings.");
153
154         SysTryReturn(NID_LOC, interval >= 1, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The interval(%d) should be greater than or equal to 1", interval);
155
156         if (__locationUpdater.type == _LOCATION_UPDATE_TYPE_INTERVAL && __locationUpdater.updateInterval == interval)
157         {
158                 return E_SUCCESS;
159         }
160
161         const double INVALID_DISTANCE_THRESHOLD = 0.0;
162         return StartLocationUpdates(_LOCATION_UPDATE_TYPE_INTERVAL, interval, INVALID_DISTANCE_THRESHOLD);
163 }
164
165 result
166 _LocationProviderImpl::StartLocationUpdatesByDistance(double distance)
167 {
168         bool userConsent = GetUserPrivilege();
169         SysTryReturn(NID_LOC, userConsent, E_USER_NOT_CONSENTED, E_USER_NOT_CONSENTED, "[E_USER_NOT_CONSENTED] The user has disabled the required settings.");
170
171         SysTryReturn(NID_LOC, distance > 0.0, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The distance(%lf) should be greater than 0.0", distance);
172
173         SysTryReturn(NID_LOC, Double::IsNaN(distance) == false, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The distance is NaN.");
174
175         if (__locationUpdater.type == _LOCATION_UPDATE_TYPE_DISTANCE && (Double::Compare(__locationUpdater.distanceThreshold, distance) == 0))
176         {
177                 return E_SUCCESS;
178         }
179
180         const int INVALID_INTERVAL = 0;
181         return StartLocationUpdates(_LOCATION_UPDATE_TYPE_DISTANCE, INVALID_INTERVAL, distance);
182 }
183
184 result
185 _LocationProviderImpl::StopLocationUpdates(void)
186 {
187         SysLog(NID_LOC, "Stopping the location updates for the request ID (%ld)", __locationUpdater.reqId);
188
189         SysTryReturn(NID_LOC, __locationUpdater.type != _LOCATION_UPDATE_TYPE_NONE, E_INVALID_OPERATION, E_INVALID_OPERATION, "[E_INVALID_OPERATION] Location update has not been requested.");
190
191         result r = __pLocationManager->StopLocationUpdates(__locationUpdater.reqId);
192
193         ResetLocationUpdates();
194
195         return r;
196 }
197
198 void
199 _LocationProviderImpl::KeepLocationUpdateAwake(bool enable)
200 {
201         if (__locationUpdater.awakeEnabled == enable)
202         {
203                 return;
204         }
205         __locationUpdater.awakeEnabled = enable;
206
207         UiApp* appInstance = Tizen::App::UiApp::GetInstance();
208         if (appInstance == null)        // This is service APP. So should be handled now.
209         {
210                 SysLog(NID_LOC, "Handling the request awake mode(%d) for the service application.", enable);
211                 if (enable == true)
212                 {
213                         if (__locationUpdater.type != _LOCATION_UPDATE_TYPE_NONE && __locationUpdater.status == LOC_SVC_STATUS_PAUSED)
214                         {
215                                 SysLog(NID_LOC, "Requesting to start the location updates as the update type is (%x)", __locationUpdater.type);
216                                 __locationUpdater.status = LOC_SVC_STATUS_NOT_FIXED;
217                                 __pLocationManager->StartLocationUpdates(__criteria.GetAccuracy(), __locationUpdater.updateInterval, this, __locationUpdater.reqId);
218
219                                 NotifyServiceStatus(_LOC_PRV_EVENT_SEND_LOC_SVC_CB, __locationUpdater.status);
220                         }
221                 }
222                 else
223                 {
224                         if (__locationUpdater.type != _LOCATION_UPDATE_TYPE_NONE && (__locationUpdater.status == LOC_SVC_STATUS_RUNNING || __locationUpdater.status == LOC_SVC_STATUS_NOT_FIXED))
225                         {
226                                 SysLog(NID_LOC, "Requesting to stop the location updates as the update type is (%x)", __locationUpdater.type);
227                                 __locationUpdater.status = LOC_SVC_STATUS_PAUSED;
228                                 __pLocationManager->StopLocationUpdates(__locationUpdater.reqId);
229
230                                 NotifyServiceStatus(_LOC_PRV_EVENT_SEND_LOC_SVC_CB, __locationUpdater.status);
231                         }
232                 }
233         }
234 }
235
236 result
237 _LocationProviderImpl::AddMonitoringRegion(const Coordinates& regionCenter, double radius, RegionId& regionId)
238 {
239         bool userConsent = GetUserPrivilege();
240         SysTryReturn(NID_LOC, userConsent, E_USER_NOT_CONSENTED, E_USER_NOT_CONSENTED, "[E_USER_NOT_CONSENTED] The user has disabled the required settings.");
241
242         SysTryReturn(NID_LOC, radius >= 50.0 && radius <= 100000.00, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The radius is not within the specified limits.");
243
244         SysTryReturn(NID_LOC, (!Double::IsNaN(radius) && !Double::IsNaN(regionCenter.GetLatitude()) && !Double::IsNaN(regionCenter.GetLongitude())),
245                                  E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] One of the value is NaN.");
246
247         SysLog(NID_LOC, "Requested to add the monitoring region with center (Latitude: %lf, Longitude %lf) and radius (%lf).", regionCenter.GetLatitude(), regionCenter.GetLongitude(), radius);
248
249         static int nextRegionId = 0;
250         result r = E_SUCCESS;
251
252         std::unique_ptr< _RegionInfo > pRegionInfo(new (std::nothrow) _RegionInfo(regionCenter, radius, nextRegionId));
253         SysTryReturn(NID_LOC, pRegionInfo != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
254
255         r = __regionMonitor.pRegionList->Add(*pRegionInfo.get());
256         SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Failed to add the Region info into the list. Propogated.", GetErrorMessage(r));
257
258         pRegionInfo.release();
259         regionId = nextRegionId;
260         nextRegionId++;
261
262         if (__regionMonitor.status != LOC_SVC_STATUS_IDLE)
263         {
264                 return E_SUCCESS;
265         }
266
267         r = ActivateRegionMonitoring();
268         SysTryCatch(NID_LOC, r == E_SUCCESS, , r, "[%s] Failed to start the region monitoring. Propogating.", GetErrorMessage(r));
269
270         __regionMonitor.status = LOC_SVC_STATUS_NOT_FIXED;
271         NotifyServiceStatus(_LOC_PRV_EVENT_SEND_MONITOR_SVC_CB, __regionMonitor.status);
272
273         return E_SUCCESS;
274
275 CATCH:
276         __regionMonitor.pRegionList->RemoveAt(0);
277         return r;
278 }
279
280 result
281 _LocationProviderImpl::RemoveMonitoringRegion(RegionId regionId)
282 {
283         int count = __regionMonitor.pRegionList->GetCount();
284         bool isIdValid = false;
285
286         SysLog(NID_LOC, "Total regions currently monitored is (%d).", count);
287
288         for (int i = 0; i < count; i++)
289         {
290                 _RegionInfo* pRegionInfo = static_cast< _RegionInfo* >(__regionMonitor.pRegionList->GetAt(i));
291                 if (regionId == pRegionInfo->GetRegionId())
292                 {
293                         __regionMonitor.pRegionList->RemoveAt(i, true);
294                         isIdValid = true;
295                         break;
296                 }
297         }
298
299         SysTryReturn(NID_LOC, isIdValid == true, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The region ID is invalid.");
300
301         if (__regionMonitor.pRegionList->GetCount() == 0)
302         {
303                 __regionMonitor.status = LOC_SVC_STATUS_IDLE;
304                 if (__locationUpdater.status == LOC_SVC_STATUS_IDLE)  // As we are using the same variable for both region monitoring and location updates, this set is required here.
305                 {
306                         __lastLocationAccuracy = LOC_ACCURACY_INVALID;
307                 }
308                 StopRegionMonitoring();
309         }
310
311         return E_SUCCESS;
312 }
313
314 void
315 _LocationProviderImpl::RemoveAllMonitoringRegions(void)
316 {
317         __regionMonitor.pRegionList->RemoveAll(true);
318
319         if (__regionMonitor.status != LOC_SVC_STATUS_IDLE)
320         {
321                 __regionMonitor.status = LOC_SVC_STATUS_IDLE;
322                 if (__locationUpdater.status == LOC_SVC_STATUS_IDLE)  // As we are using the same variable for both region monitoring and location updates, this set is required here.
323                 {
324                         __lastLocationAccuracy = LOC_ACCURACY_INVALID;
325                 }
326                 StopRegionMonitoring();
327         }
328
329         return;
330 }
331
332 LocationServiceStatus
333 _LocationProviderImpl::GetLocationUpdateStatus(void) const
334 {
335         return __locationUpdater.status;
336 }
337
338 LocationServiceStatus
339 _LocationProviderImpl::GetRegionMonitoringStatus(void) const
340 {
341         return __regionMonitor.status;
342 }
343
344 LocationAccuracy
345 _LocationProviderImpl::GetCurrentAccuracy(void) const
346 {
347         return __lastLocationAccuracy;
348 }
349
350 Location
351 _LocationProviderImpl::GetLocation(const LocationCriteria& criteria)
352 {
353         Location retLocation(_LocationImpl::GetLocationInstance());
354
355         bool userConsent = GetUserPrivilege();
356         SysTryReturn(NID_LOC, userConsent, retLocation, E_USER_NOT_CONSENTED, "[E_USER_NOT_CONSENTED] The user has disabled the required settings.");
357
358         Location* pLocation = null;
359         const int MAX_TIMEOUT = 30;
360         result r = E_SUCCESS;
361         _LocationManager* pLocationManager = null;
362
363         SysLog(NID_LOC, "Requesting for single location with criteria (%x).", criteria.GetAccuracy());
364
365         std::unique_ptr< _LocationMonitor > pLocMonitor(new (std::nothrow) _LocationMonitor());
366         SysTryCatch(NID_LOC, pLocMonitor, , E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
367
368         r = pLocMonitor->Construct(MAX_TIMEOUT, criteria.GetAccuracy());
369         SysTryCatch(NID_LOC, r == E_SUCCESS, , r, "[%s] Failed to construct the Location Monitor.", GetErrorMessage(r));
370
371         pLocationManager = _LocationManager::GetInstance();
372         SysTryCatch(NID_LOC, pLocationManager, , r, "[%s] Failed to get the location manager instance.", GetErrorMessage(r));
373
374         r = pLocationManager->RegisterLocationMonitor(pLocMonitor.get());
375         SysTryCatch(NID_LOC, r == E_SUCCESS, , r, "[%s] Failed to register the location monitor.", GetErrorMessage(r));
376
377         r = pLocMonitor->Wait();
378
379         if (!IsFailed(r))
380         {
381                 pLocation = pLocMonitor->GetLocationN();
382         }
383
384         if (pLocation)
385         {
386                 retLocation = *pLocation;
387         }
388         else
389         {
390                 SetLastResult(E_LOCATION_UNAVAILABLE);
391         }
392
393         delete pLocation;
394
395         return retLocation;
396
397 CATCH:
398         return retLocation;
399 }
400
401 Location
402 _LocationProviderImpl::GetLastKnownLocation(void)
403 {
404         Location retLocation(_LocationImpl::GetLocationInstance());
405
406         bool userConsent = GetUserPrivilege();
407         SysTryReturn(NID_LOC, userConsent, retLocation, E_USER_NOT_CONSENTED, "[E_USER_NOT_CONSENTED] The user has disabled the required settings.");
408
409         _LocationManager* pLocationManager = _LocationManager::GetInstance();
410         SysTryReturn(NID_LOC, pLocationManager, retLocation, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
411
412         retLocation = pLocationManager->GetLastKnownLocation();
413
414         if (!retLocation.IsValid())
415         {
416                 SetLastResult(E_LOCATION_UNAVAILABLE);
417         }
418         else
419         {
420                 ClearLastResult();
421         }
422
423         return retLocation;
424 }
425
426 // Private members
427
428 void
429 _LocationProviderImpl::OnLocationUpdated(RequestId reqId, const Tizen::Locations::Location& location)
430 {
431         SysLog(NID_LOC, "Location is updated from Location Manager for the request ID (%ld).", reqId);
432
433         std::unique_ptr< Location > pLocation(new (std::nothrow) Location(location));
434         SysTryReturnVoidResult(NID_LOC, pLocation, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
435
436         std::unique_ptr< _LocProviderEventArg > pLocProviderEventArg(new (std::nothrow) _LocProviderEventArg());
437         SysTryReturnVoidResult(NID_LOC, pLocProviderEventArg, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
438
439         pLocProviderEventArg->SetEventType(_LOC_PRV_EVENT_SEND_LOC);
440         pLocProviderEventArg->SetLocation(pLocation.get());
441         pLocProviderEventArg->SetRequestId(reqId);
442         pLocation.release();
443
444         result r = _Event::FireAsync(*pLocProviderEventArg);
445         SysTryReturnVoidResult(NID_LOC, r == E_SUCCESS, r, "[%s] Failed to fire the event.", GetErrorMessage(r));
446         pLocProviderEventArg.release();
447
448         return;
449 }
450
451 void
452 _LocationProviderImpl::OnLocationEventReceivedN(RequestId reqId, Tizen::Locations::Location& location)
453 {
454         SysLog(NID_LOC, "Location Event received.");
455         bool isNew = false;
456         LocationAccuracy currentAccuracy = LOC_ACCURACY_INVALID;
457         long long lastLocationTime = 0;
458
459         Location* pLocation = &location;
460         _LocationImpl* pLocationImpl = _LocationImpl::GetInstance(*pLocation);
461
462         if (reqId == __locationUpdater.reqId)
463         {
464                 SysLog(NID_LOC, "The location is updated for Location request.");
465                 lastLocationTime = _LocationImpl::GetInstance(*__locationUpdater.pLocation.get())->GetTimestampInMs();
466         }
467         else if (reqId == __regionMonitor.reqId)
468         {
469                 SysLog(NID_LOC, "The location is updated for Region monitoring.");
470                 lastLocationTime = _LocationImpl::GetInstance(*__regionMonitor.pLocation.get())->GetTimestampInMs();
471         }
472
473         long long timeDifference = pLocationImpl->GetTimestampInMs() - lastLocationTime;
474         SysLog(NID_LOC, "Time difference between last location timestamp (%lld) and current location timestamp (%lld) is (%lld).", lastLocationTime, pLocationImpl->GetTimestampInMs(), timeDifference);
475         if (timeDifference > 0)
476         {
477                 isNew = true;
478                 currentAccuracy = __pLocationManager->GetAccuracyLevel(pLocation->GetHorizontalAccuracy());
479         }
480
481         if (currentAccuracy != __lastLocationAccuracy)
482         {
483                 SysLog(NID_LOC, "Notify the accuracy change.");
484                 __lastLocationAccuracy = currentAccuracy;
485                 __pLocationListener->OnAccuracyChanged(currentAccuracy);
486         }
487
488         if (reqId == __locationUpdater.reqId)
489         {
490                 HandleLocationUpdate(location, isNew);
491         }
492         else if (reqId == __regionMonitor.reqId)
493         {
494                 if (isNew)      // Copy the location only if it is new.
495                 {
496                         *__regionMonitor.pLocation = location;
497                 }
498
499                 if (currentAccuracy != LOC_ACCURACY_INVALID && currentAccuracy <= __criteria.GetAccuracy())
500                 {
501                         SysLog(NID_LOC, "Location criteria (accuracy: %ld) is met for handling region monitoring.", currentAccuracy);
502                         result r = __regionMonitor.pTimer->Cancel();
503                         SysTryLog(NID_LOC, r == E_SUCCESS, "Failed to cancel the timer.");
504
505                         r = __pLocationManager->StopLocationUpdates(__regionMonitor.reqId);
506                         SysTryLog(NID_LOC, r == E_SUCCESS, "Failed to stop the location updates.");
507                         HandleRegionMonitoring(location, isNew);
508                 }
509                 else
510                 {
511                         SysLog(NID_LOC, "Location criteria (accuracy: %ld) is not met for handling region monitoring.", currentAccuracy);
512                 }
513         }
514
515         delete pLocation;
516 }
517
518 void
519 _LocationProviderImpl::OnLocationUpdateStatusChanged(Tizen::Locations::LocationServiceStatus locSvcStatus)
520 {
521         __pLocationListener->OnLocationUpdateStatusChanged(locSvcStatus);
522 }
523
524 void
525 _LocationProviderImpl::OnRegionMonitoringStatusChanged(Tizen::Locations::LocationServiceStatus locSvcStatus)
526 {
527         __pLocationListener->OnRegionMonitoringStatusChanged(locSvcStatus);
528 }
529
530 void
531 _LocationProviderImpl::OnActiveAppChanged(const Tizen::App::AppId& appId)
532 {
533         Tizen::App::App* pApp = Tizen::App::App::GetInstance();
534         Tizen::App::AppId currentAppId = pApp->GetAppId();
535
536         SysLog(NID_LOC, "Active App ID is (%ls) and the current app Id is (%ls)", appId.GetPointer(), currentAppId.GetPointer());
537
538         if (currentAppId == appId)
539         {
540                 SysLog(NID_LOC, "Application is active.");
541
542                 if (__locationUpdater.status == LOC_SVC_STATUS_PAUSED)
543                 {
544                         SysLog(NID_LOC, "Start the location updates as the location update status is PAUSED.");
545                         __pLocationManager->StartLocationUpdates(__criteria.GetAccuracy(), __locationUpdater.updateInterval, this, __locationUpdater.reqId);
546                         __locationUpdater.status = LOC_SVC_STATUS_NOT_FIXED;
547                         __pLocationListener->OnLocationUpdateStatusChanged(__locationUpdater.status);
548                 }
549         }
550         else
551         {
552                 SysLog(NID_LOC, "Application is not active.");
553                 
554                 if (__locationUpdater.awakeEnabled == false && (__locationUpdater.status == LOC_SVC_STATUS_RUNNING || __locationUpdater.status == LOC_SVC_STATUS_NOT_FIXED))
555                 {
556                         SysLog(NID_LOC, "Stop the location updates as application is not active with awake mode as (%d) and location update state as (%x).", __locationUpdater.awakeEnabled, __locationUpdater.status);
557                         __pLocationManager->StopLocationUpdates(__locationUpdater.reqId);
558                         __locationUpdater.status = LOC_SVC_STATUS_PAUSED;
559                         __pLocationListener->OnLocationUpdateStatusChanged(__locationUpdater.status);
560                 }
561         }
562 }
563
564 void
565 _LocationProviderImpl::OnAlarmExpired(Alarm& alarm)
566 {
567         SysLog(NID_LOC, "Region Monitor Alarm expired.");
568         
569         result r = ActivateRegionMonitoring();
570         SysTryReturnVoidResult(NID_LOC, r == E_SUCCESS, r, "[%s] Failed to start the region monitoring. Propogating.", GetErrorMessage(r));
571 }
572
573 void
574 _LocationProviderImpl::OnTimerExpired(Timer& timer)
575 {
576         SysLog(NID_LOC, "Region Monitor timer expired due to unavailability of location information.");
577         __pLocationManager->StopLocationUpdates(__regionMonitor.reqId);
578         HandleRegionMonitoring(*__regionMonitor.pLocation, __regionMonitor.pLocation->IsValid());
579 }
580
581 result
582 _LocationProviderImpl::StartLocationUpdates(LocationUpdateType updateType, int interval, double distance)
583 {
584         result r = E_SUCCESS;
585         bool startUpdate = true;
586
587         if (updateType == _LOCATION_UPDATE_TYPE_INTERVAL)
588         {
589                 __locationUpdater.updateInterval = interval;
590         }
591         else if (updateType == _LOCATION_UPDATE_TYPE_DISTANCE)
592         {
593                 __locationUpdater.updateInterval = DEFAULT_DISTANCE_CHECKING_INTERVAL;
594                 __locationUpdater.distanceThreshold = distance;
595         }
596
597         if  (!__locationUpdater.awakeEnabled)
598         {
599                 UiApp* pAppInstance = Tizen::App::UiApp::GetInstance();
600                 if (pAppInstance == null)
601                 {
602                         startUpdate = false;
603                 }
604                 else 
605                 {
606                         AppUiState appUiState = pAppInstance->GetAppUiState();
607                 
608                         if (appUiState == APP_UI_STATE_BACKGROUND)
609                         {
610                                 SysLog(NID_LOC, "App is background.");
611                                 startUpdate = false;
612                         }
613                 }
614         }
615
616         if (startUpdate)
617         {
618                 if (__locationUpdater.type != _LOCATION_UPDATE_TYPE_NONE)
619                 {
620                         SysLog(NID_LOC, "Update session already running. Updating the interval to %d seconds", __locationUpdater.updateInterval);
621                         r = __pLocationManager->ChangeUpdateInterval(__locationUpdater.reqId, __locationUpdater.updateInterval);
622                         SysTryCatch(NID_LOC, r == E_SUCCESS, , r, "[%s] Failed to update the request interval. Propagating.", GetErrorMessage(r));
623                         __locationUpdater.type = updateType;
624                         return E_SUCCESS;
625                 }
626                 else
627                 {
628                         r = __pLocationManager->StartLocationUpdates(__criteria.GetAccuracy(), __locationUpdater.updateInterval, this, __locationUpdater.reqId);
629                         SysTryCatch(NID_LOC, r == E_SUCCESS, , r, "[%s] Failed to start the Native location updates. Propagating.", GetErrorMessage(r));
630                         __locationUpdater.status = LOC_SVC_STATUS_NOT_FIXED;
631                 }       
632         }
633         else
634         {
635                 __locationUpdater.status = LOC_SVC_STATUS_PAUSED;       
636         }
637
638         __locationUpdater.type = updateType;
639
640         SysLog(NID_LOC, "Update type is (%x). The request Id is (%ld) and the update status is (%x).", __locationUpdater.type, __locationUpdater.reqId, __locationUpdater.status);
641         NotifyServiceStatus(_LOC_PRV_EVENT_SEND_LOC_SVC_CB, __locationUpdater.status);
642
643         return E_SUCCESS;
644
645 CATCH:
646         __locationUpdater.type = _LOCATION_UPDATE_TYPE_NONE;
647         return r;
648 }
649
650 bool
651 _LocationProviderImpl::CheckDistanceThreshold(const Location& oldPosition, const Location& newPosition)
652 {
653         double displacement = 0.0;
654         const Coordinates coordOld = oldPosition.GetCoordinates();
655         const Coordinates coordNew = newPosition.GetCoordinates();
656
657         if (__locationUpdater.firstLocationUpdate)
658         {
659                 SysLog(NID_LOC, "First location update. So send true.");
660                 __locationUpdater.firstLocationUpdate = false;
661                 return true;
662         }
663
664         displacement = coordOld.GetDistanceTo(coordNew);
665         SysLog(NID_LOC, "Displacement is (%lf)", displacement);
666         return ((displacement > __locationUpdater.distanceThreshold) ? true : false);
667 }
668
669 void
670 _LocationProviderImpl::ResetLocationUpdates(void)
671 {
672         __locationUpdater.firstLocationUpdate = true;
673         __locationUpdater.reqId = -1;
674         __lastLocationAccuracy = LOC_ACCURACY_INVALID;
675         __locationUpdater.type = _LOCATION_UPDATE_TYPE_NONE;
676         __locationUpdater.status = LOC_SVC_STATUS_IDLE;
677         __locationUpdater.updateInterval = 0;
678         __locationUpdater.distanceThreshold = 0.0;
679 }
680
681 void
682 _LocationProviderImpl::FireImpl(Tizen::Base::Runtime::IEventListener& listener, const Tizen::Base::Runtime::IEventArg& arg)
683 {
684         _ILocProviderEventListener* pLocProviderEventListener = dynamic_cast< _ILocProviderEventListener* >(&listener);
685         SysTryReturnVoidResult(NID_LOC, pLocProviderEventListener, E_SYSTEM, "[E_INVALID_ARG] The listener is null.");
686
687         IEventArg* pArg = const_cast< IEventArg* >(&arg);
688         _LocProviderEventArg* pEventArg = dynamic_cast< _LocProviderEventArg* >(pArg);
689         SysTryReturnVoidResult(NID_LOC, pEventArg, E_SYSTEM, "[E_INVALID_ARG] Event argument is null.");
690
691         _LocProviderEventType eventType = pEventArg->GetEventType();
692         switch (eventType)
693         {
694         case _LOC_PRV_EVENT_SEND_LOC:
695                 pLocProviderEventListener->OnLocationEventReceivedN(pEventArg->GetRequestId(), *pEventArg->GetLocationN());
696                 break;
697
698         case _LOC_PRV_EVENT_SEND_LOC_SVC_CB:
699                 pLocProviderEventListener->OnLocationUpdateStatusChanged(pEventArg->GetLocServiceStatus());
700                 break;
701
702         case _LOC_PRV_EVENT_SEND_MONITOR_SVC_CB:
703                 pLocProviderEventListener->OnRegionMonitoringStatusChanged(pEventArg->GetLocServiceStatus());
704                 break;
705         }
706 }
707
708 void
709 _LocationProviderImpl::HandleLocationUpdate(Tizen::Locations::Location& location, bool isNew)
710 {
711         LocationServiceStatus newLocationUpdateStatus = __locationUpdater.status;
712
713         if (isNew)
714         {
715                 if (__locationUpdater.type != _LOCATION_UPDATE_TYPE_NONE && __locationUpdater.status != LOC_SVC_STATUS_PAUSED)
716                 {
717                         newLocationUpdateStatus = LOC_SVC_STATUS_RUNNING;
718                 }
719         }
720         else if (_LocationImpl::GetInstance(location)->IsDenied())
721         {
722                 SysLog(NID_LOC, "User consent not available.");
723                 if (__locationUpdater.type != _LOCATION_UPDATE_TYPE_NONE && __locationUpdater.status != LOC_SVC_STATUS_PAUSED)
724                 {
725                         newLocationUpdateStatus = LOC_SVC_STATUS_DENIED;
726                 }
727         }
728         else
729         {
730                 SysLog(NID_LOC, "Invalid Location Update.");
731                 if (__locationUpdater.type != _LOCATION_UPDATE_TYPE_NONE && __locationUpdater.status != LOC_SVC_STATUS_PAUSED)
732                 {
733                         newLocationUpdateStatus = LOC_SVC_STATUS_NOT_FIXED;
734                 }
735         }
736
737         if (newLocationUpdateStatus != __locationUpdater.status)
738         {
739                 SysLog(NID_LOC, "Location Update Satus changed to (%x). Notify the status.", newLocationUpdateStatus);
740                 __locationUpdater.status = newLocationUpdateStatus;
741                 __pLocationListener->OnLocationUpdateStatusChanged(__locationUpdater.status);
742         }
743
744         if (newLocationUpdateStatus == LOC_SVC_STATUS_RUNNING)
745         {
746                 if (__locationUpdater.type == _LOCATION_UPDATE_TYPE_DISTANCE)
747                 {
748                         if (CheckDistanceThreshold(*__locationUpdater.pLocation.get(), location) == true)
749                         {
750                                 SysLog(NID_LOC, "Location displacement exceeds the distance threshold (%lf). Notify the location.", __locationUpdater.distanceThreshold);
751                                 __pLocationListener->OnLocationUpdated(location);
752                                 *__locationUpdater.pLocation.get() = location;
753                         }
754                 }
755                 else if (__locationUpdater.type == _LOCATION_UPDATE_TYPE_INTERVAL)
756                 {
757                         SysLog(NID_LOC, "Location time interval expired. Notify the location.");
758                         __pLocationListener->OnLocationUpdated(location);
759                         *__locationUpdater.pLocation.get() = location;
760                 }
761         }
762 }
763
764 void
765 _LocationProviderImpl::HandleRegionMonitoring(Tizen::Locations::Location& location, bool isNew)
766 {
767         LocationServiceStatus newRegionMonitorStatus = __regionMonitor.status;
768
769         if (isNew)
770         {
771                 newRegionMonitorStatus = LOC_SVC_STATUS_RUNNING;
772         }
773         else if (_LocationImpl::GetInstance(location)->IsDenied())
774         {
775                 newRegionMonitorStatus = LOC_SVC_STATUS_DENIED;
776         }
777         else
778         {
779                 newRegionMonitorStatus = LOC_SVC_STATUS_NOT_FIXED;
780         }
781
782         if (newRegionMonitorStatus != __regionMonitor.status)
783         {
784                 SysLog(NID_LOC, "Region Monitoring Satus changed to (%x). Notify the status.", newRegionMonitorStatus);
785                 __regionMonitor.status = newRegionMonitorStatus;
786                 __pLocationListener->OnRegionMonitoringStatusChanged(__regionMonitor.status);
787         }
788
789         if (newRegionMonitorStatus == LOC_SVC_STATUS_RUNNING)
790         {
791                 NotifyRegionCrossedStatus(location);
792         }
793
794         SetNextRegionMonitoringTime();
795 }
796
797 void
798 _LocationProviderImpl::NotifyRegionCrossedStatus(const Tizen::Locations::Location& location)
799 {
800         int count = __regionMonitor.pRegionList->GetCount();
801
802         SysLog(NID_LOC, "Number of regions currently monitored is (%d)", count);
803
804         for (int i = 0; i < count; i++)
805         {
806                 _RegionInfo* pRegionInfo = static_cast< _RegionInfo* >(__regionMonitor.pRegionList->GetAt(i));
807
808                 if (pRegionInfo)
809                 {
810                         Coordinates regionCoordinate = pRegionInfo->GetCoordinate();
811                         _RegionState currentState = REGION_STATE_UNKNOWN;
812                         _RegionState previousState = pRegionInfo->GetPreviousValidState();
813                         bool notifyStateChange = false;
814
815                         currentState = GetRegionCurrentState(*pRegionInfo, location);
816                         SysLog(NID_LOC, "Current Region state is (%d) and Previous Region state is (%d)", currentState, previousState);
817
818                         if (currentState != REGION_STATE_UNKNOWN && previousState != currentState)
819                         {
820                                 notifyStateChange = true;
821                                 pRegionInfo->SetValidPreviousState(currentState);
822                         }
823
824                         if ((pRegionInfo->GetRegionState() == REGION_STATE_INSIDE || pRegionInfo->GetRegionState() == REGION_STATE_UNKNOWN) && currentState == REGION_STATE_OUTSIDE)
825                         {
826                                 if (notifyStateChange)
827                                 {
828                                         SysLog(NID_LOC, "Notify the boundary crossed event as previous valid region state is INSIDE and current state is OUTSIDE.");
829                                         __pLocationListener->OnRegionLeft(pRegionInfo->GetRegionId());
830                                 }
831                         }
832                         else if ((pRegionInfo->GetRegionState() == REGION_STATE_OUTSIDE || pRegionInfo->GetRegionState() == REGION_STATE_UNKNOWN) && currentState == REGION_STATE_INSIDE)
833                         {
834                                 if (notifyStateChange)
835                                 {
836                                         SysLog(NID_LOC, "Notify the boundary crossed event as previous valid region state is OUTSIDE and current state is INSIDE.");
837                                         __pLocationListener->OnRegionEntered(pRegionInfo->GetRegionId());
838                                 }
839                         }
840                         pRegionInfo->SetRegionState(currentState);
841                 }
842         }
843 }
844
845 _RegionState
846 _LocationProviderImpl::GetRegionCurrentState(const _RegionInfo& region, const Location& location)
847 {
848         TryReturn(location.GetHorizontalAccuracy() >= 0.0, REGION_STATE_UNKNOWN, "Location received with invalid accuracy");
849
850         SysLog(NID_LOC, "[RegionID %d] Region Information is (Center latitude: %lf, Center longitude: %lf, Region radius:%lf", region.GetRegionId(), region.GetCoordinate().GetLatitude(),
851                    region.GetCoordinate().GetLongitude(), region.GetRadius());
852         SysLog(NID_LOC, "[RegionID %d] Location Information is (Latitude: %lf, Longitude: %lf, Horizontal accuracy:%lf", region.GetRegionId(), location.GetCoordinates().GetLatitude(),
853                    location.GetCoordinates().GetLongitude(), location.GetHorizontalAccuracy());
854
855         _RegionState regionState = REGION_STATE_UNKNOWN;
856
857         double distanceBtwCenters = region.GetCoordinate().GetDistanceTo(location.GetCoordinates());
858         double regionRadius = region.GetRadius();
859         double locationRadius = location.GetHorizontalAccuracy();
860
861         SysLog(NID_LOC, "[RegionID %d]  The distance between centers is (%lf)", region.GetRegionId(), distanceBtwCenters);
862
863         if (distanceBtwCenters >= (regionRadius + locationRadius))
864         {
865                 regionState = REGION_STATE_OUTSIDE;
866         }
867         else if (distanceBtwCenters < regionRadius && Double::Compare(locationRadius, 0.0) == 0)
868         {
869                 SysLog(NID_LOC, "[RegionID %d] Location Radius is 0 and distance < regionRadius", region.GetRegionId());
870                 regionState = REGION_STATE_INSIDE;
871         }
872         else
873         {
874                 double radiusThreshold = (1 / Math::Sqrt(2)) * locationRadius;
875
876                 if (regionRadius < radiusThreshold)
877                 {
878                         SysLog(NID_LOC, "[RegionID %d] Region circle is less than 50 percent area of the location circle.", region.GetRegionId());
879                         regionState = (distanceBtwCenters >= locationRadius) ? REGION_STATE_OUTSIDE : REGION_STATE_UNKNOWN;
880
881                         return regionState;
882                 }
883                 else
884                 {
885                         double overlapRegion = _MathUtils::CalculateOverlapRegion(region, location);
886                         double upperThreshold = 0;
887                         double lowerThreshold = 0;
888                         double occupancy = 0;
889
890                         SysLog(NID_LOC, "[RegionID %d] OverlapRegion is (%lf)", region.GetRegionId(), overlapRegion);
891
892                         if (regionRadius >= locationRadius)
893                         {
894                                 // Calculate occupancy % with the location circle
895                                 SysLog(NID_LOC, "[RegionID %d] Region radius is bigger.", region.GetRegionId());
896                                 occupancy = (overlapRegion / (Math::GetPi() * locationRadius * locationRadius)) * 100;
897
898                                 upperThreshold = 60;
899                                 lowerThreshold = 40;
900                         }
901                         else if (regionRadius >= radiusThreshold)
902                         {
903                                 SysLog(NID_LOC, "[RegionID %d] The ratio of Region radius to location radius is between 0.707 and 1.", region.GetRegionId());
904                                 double thresholdValue = -136.51 * (regionRadius / locationRadius) + 146.51; // This equation varies the threshold value from 10 (for R/r = 1) to 50 (for R/r = 0.707)
905
906                                 SysLog(NID_LOC, "[RegionID %d] Threshold value is %lf.", region.GetRegionId(), thresholdValue);
907
908                                 occupancy = (overlapRegion / (Math::GetPi() * locationRadius * locationRadius)) * 100;
909
910                                 upperThreshold = 50 + thresholdValue;
911                                 lowerThreshold = 50 - thresholdValue;
912                         }
913
914                         // Decide the state with as per the inner and outer thresholds
915                         SysLog(NID_LOC, "[RegionID %d] Occupancy is (%lf), Upper threshold is (%lf) and lower threshold is (%lf).", region.GetRegionId(), occupancy, upperThreshold, lowerThreshold);
916                         regionState = (occupancy >= upperThreshold) ? REGION_STATE_INSIDE : ((occupancy <= lowerThreshold) ? REGION_STATE_OUTSIDE : REGION_STATE_UNKNOWN);
917                 }
918         }
919
920         SysLog(NID_LOC, "[RegionID %d] Returning region state as (%d).", region.GetRegionId(), regionState);
921         return regionState;
922 }
923
924 void
925 _LocationProviderImpl::NotifyServiceStatus(_LocProviderEventType eventType, LocationServiceStatus svcStatus)
926 {
927         std::unique_ptr< _LocProviderEventArg > pLocProviderEventArg(new (std::nothrow) _LocProviderEventArg());
928         if (pLocProviderEventArg)
929         {
930                 pLocProviderEventArg->SetEventType(eventType);
931                 pLocProviderEventArg->SetLocServiceStatus(svcStatus);
932
933                 result r = _Event::FireAsync(*pLocProviderEventArg.get());
934                 SysTryReturnVoidResult(NID_LOC, r == E_SUCCESS, r, "[%s] Failed to fire the event.", GetErrorMessage(r));
935
936                 pLocProviderEventArg.release();
937         }
938
939         return;
940 }
941
942 bool
943 _LocationProviderImpl::GetUserPrivilege(void)
944 {
945         _LocationManager* pLocMgr = _LocationManager::GetInstance();
946         SysTryReturn(NID_LOC, pLocMgr, false, E_SYSTEM, "[E_SYSTEM] Failed to get the location manager instance.");
947
948         bool appSettingEnabled = pLocMgr->IsAppEnabled();
949         if (appSettingEnabled == false)
950         {
951                 return false;
952         }
953
954         bool hasPrivilege = false;
955         result gps = E_SUCCESS;
956         result wps = E_SUCCESS;
957
958         bool gpsEnabled = true;
959         bool wpsEnabled = true;
960
961         gps = _SettingInfoImpl::GetValue(L"http://tizen.org/setting/location.gps", gpsEnabled);
962         wps = _SettingInfoImpl::GetValue(L"http://tizen.org/setting/location.wps", wpsEnabled);
963
964         hasPrivilege = gpsEnabled | wpsEnabled;
965
966         if (gps != E_SUCCESS || wps != E_SUCCESS || hasPrivilege == false)
967         {
968                 return false;
969         }
970
971         return true;
972 }
973
974 result
975 _LocationProviderImpl::ActivateRegionMonitoring(void)
976 {
977         long long currentTime;
978         SystemTime::GetTicks(currentTime);
979
980         SysLog(NID_LOC, "Current system time is %lld", currentTime);
981         
982         _LocationImpl::GetInstance(*__regionMonitor.pLocation)->SetValidity(false);
983         _LocationImpl::GetInstance(*__regionMonitor.pLocation)->SetTimestamp(currentTime);
984         
985         result r = __regionMonitor.pTimer->Start(DEFAULT_WAITING_TIME_FOR_FIXING_LOCATION * 1000);
986         SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Failed to start the timer. Propogating.", GetErrorMessage(r));
987
988         r = __pLocationManager->StartLocationUpdates(__criteria.GetAccuracy(), MIN_LOCATION_UPDATE_INTERVAL, this, __regionMonitor.reqId);
989         SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Failed to start the location updates. Propogating.", GetErrorMessage(r));
990
991         SysLog(NID_LOC, "Timer & Location updates are started.");
992         return E_SUCCESS;
993 }
994
995 void
996 _LocationProviderImpl::StopRegionMonitoring(void)
997 {
998         result r = _AlarmImpl::GetInstance(__regionMonitor.pAlarm.get())->Cancel();
999         SysTryReturnVoidResult(NID_LOC, r == E_SUCCESS, r, "[%s] Failed to stop the alarm. Ignored.", GetErrorMessage(r));
1000
1001         r = __regionMonitor.pTimer->Cancel();
1002         SysTryReturnVoidResult(NID_LOC, r == E_SUCCESS, r, "[%s] Failed to stop the timer. Ignored.", GetErrorMessage(r));
1003
1004         r = __pLocationManager->StopLocationUpdates(__regionMonitor.reqId);
1005         SysTryReturnVoidResult(NID_LOC, r == E_SUCCESS, r, "[%s] All regions are removed but failed to stop the location updates. Ignored.", GetErrorMessage(r));
1006 }
1007
1008 void
1009 _LocationProviderImpl::SetNextRegionMonitoringTime(void)
1010 {
1011         DateTime alarmDateTime;
1012         long long alarmTime = DEFAULT_REGION_MONITORING_CYCLE_INTERVAL;
1013         SystemTime::GetCurrentTime(TIME_MODE_WALL, alarmDateTime);
1014
1015         SysLog(NID_LOC, "Current System Time is %ls", alarmDateTime.ToString().GetPointer());
1016
1017         if (__regionMonitor.pLocation->IsValid())
1018         {
1019                 const int bufferTime = 5;   //Buffer of 5 seconds for determining the alarmTime;
1020                 double minDistance = _MathUtils::GetShortestDistance(*__regionMonitor.pLocation, *__regionMonitor.pRegionList);
1021                 long long newAlarmTime = ((int) minDistance / DEFAULT_AVG_SPEED) - bufferTime;  //Calculate the alarm time based on the shortest distance between current location and nearest region boundary.
1022
1023                 if (newAlarmTime > alarmTime)
1024                 {
1025                         alarmTime = newAlarmTime;
1026                 }
1027         }
1028
1029         alarmDateTime.AddSeconds(alarmTime);
1030         result r = _AlarmImpl::GetInstance(__regionMonitor.pAlarm.get())->Set(alarmDateTime, 0, null);  
1031         SysTryLog(NID_LOC, r == E_SUCCESS, "Failed to set the alarm for next cycle.");
1032         
1033         SysLog(NID_LOC, "Next alarm expires after %ld seconds.", alarmTime);
1034 }
1035 }}