merge with master
[framework/osp/locations.git] / src / FLoc_LocationProviderImpl.cpp
index 02a1229..bccc8a3 100644 (file)
@@ -39,7 +39,9 @@
 #include <FLocTypes.h>
 #include <FSysPowerManager.h>
 #include <FSysSystemTime.h>
+#include <FSys_AlarmImpl.h>
 #include <FSys_SettingInfoImpl.h>
+#include "FLoc_Config.h"
 #include "FLoc_LocationImpl.h"
 #include "FLoc_LocationManager.h"
 #include "FLoc_LocationMonitor.h"
@@ -60,21 +62,9 @@ namespace Tizen { namespace Locations
 
 _LocationProviderImpl::_LocationProviderImpl(void)
        : Tizen::Base::Runtime::_Event()
-       , __firstLocationUpdate(true)
-       , __regionMonitoringActive(false)
-       , __awakeEnabled(false)
-       , __updateInterval(0)
-       , __locationUpdateType(_LOCATION_UPDATE_TYPE_NONE)
-       , __locationUpdateStatus(LOC_SVC_STATUS_IDLE)
-       , __regionMonitorStatus(LOC_SVC_STATUS_IDLE)
        , __lastLocationAccuracy(LOC_ACCURACY_INVALID)
-       , __reqId(-1)
-       , __regionReqId(-1)
-       , __distanceThreshold(0.0)
        , __pLocationListener(null)
        , __pLocationManager(null)
-       , __pLastLocation(null)
-       , __pRegionList(null)
 {
 }
 
@@ -109,6 +99,18 @@ _LocationProviderImpl::Construct(const LocationCriteria& criteria, ILocationProv
        r = pRegionList->Construct();
        SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Failed to construct the list. Propagating.", GetErrorMessage(r));
 
+       std::unique_ptr< Tizen::Base::Runtime::Timer> pTimer (new (std::nothrow) Timer());
+       SysTryReturn(NID_LOC, pTimer != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+
+       r = pTimer->Construct(*this);
+       SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Failed to construct the timer. Propagating.", GetErrorMessage(r));
+
+       std::unique_ptr< Tizen::System::Alarm> pAlarm (new (std::nothrow) Alarm());
+       SysTryReturn(NID_LOC, pAlarm != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+
+       r = pAlarm->Construct(*this);
+       SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Failed to construct the alarm. Propagating.", GetErrorMessage(r));
+
        UiApp* pAppInstance = Tizen::App::UiApp::GetInstance();
        if (pAppInstance != null)
        {
@@ -119,14 +121,21 @@ _LocationProviderImpl::Construct(const LocationCriteria& criteria, ILocationProv
                SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Error occured during adding the event listener to app manager. Propagating.", GetErrorMessage(r));
        }
 
-       std::unique_ptr< Tizen::Locations::Location > pLocation(_LocationImpl::GetLocationInstanceN());
-       SysTryReturn(NID_LOC, pLocation != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+       std::unique_ptr< Tizen::Locations::Location > pLastLocation(_LocationImpl::GetLocationInstanceN());
+       SysTryReturn(NID_LOC, pLastLocation != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+
+       std::unique_ptr<Tizen::Locations::Location> pLastRegionLocation (_LocationImpl::GetLocationInstanceN());
+       SysTryReturn(NID_LOC, pLastRegionLocation != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
 
        _Event::Initialize();
        _Event::AddListener(*this);
 
-       __pRegionList = std::move(pRegionList);
-       __pLastLocation = std::move(pLocation);
+       __regionMonitor.pRegionList = std::move(pRegionList);
+       __regionMonitor.pTimer = std::move(pTimer);
+       __regionMonitor.pAlarm = std::move(pAlarm);
+       __regionMonitor.pLocation = std::move(pLastRegionLocation);
+       __locationUpdater.pLocation = std::move(pLastLocation);
+       
        __criteria = criteria;
        __pLocationListener = &listener;
        __pLocationManager = pLocationManager;
@@ -144,15 +153,10 @@ _LocationProviderImpl::StartLocationUpdatesByInterval(int interval)
 
        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);
 
-       if (__locationUpdateType == _LOCATION_UPDATE_TYPE_INTERVAL && __updateInterval == interval)
+       if (__locationUpdater.type == _LOCATION_UPDATE_TYPE_INTERVAL && __locationUpdater.updateInterval == interval)
        {
                return E_SUCCESS;
        }
-       else if (__locationUpdateType == _LOCATION_UPDATE_TYPE_DISTANCE || __locationUpdateType == _LOCATION_UPDATE_TYPE_INTERVAL)
-       {
-               __pLocationManager->StopLocationUpdates(__reqId);
-               __locationUpdateStatus = LOC_SVC_STATUS_IDLE;
-       }
 
        const double INVALID_DISTANCE_THRESHOLD = 0.0;
        return StartLocationUpdates(_LOCATION_UPDATE_TYPE_INTERVAL, interval, INVALID_DISTANCE_THRESHOLD);
@@ -168,15 +172,10 @@ _LocationProviderImpl::StartLocationUpdatesByDistance(double distance)
 
        SysTryReturn(NID_LOC, Double::IsNaN(distance) == false, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The distance is NaN.");
 
-       if (__locationUpdateType == _LOCATION_UPDATE_TYPE_DISTANCE && (Double::Compare(__distanceThreshold, distance) == 0))
+       if (__locationUpdater.type == _LOCATION_UPDATE_TYPE_DISTANCE && (Double::Compare(__locationUpdater.distanceThreshold, distance) == 0))
        {
                return E_SUCCESS;
        }
-       else if (__locationUpdateType == _LOCATION_UPDATE_TYPE_DISTANCE || __locationUpdateType == _LOCATION_UPDATE_TYPE_INTERVAL)
-       {
-               __pLocationManager->StopLocationUpdates(__reqId);
-               __locationUpdateStatus = LOC_SVC_STATUS_IDLE;
-       }
 
        const int INVALID_INTERVAL = 0;
        return StartLocationUpdates(_LOCATION_UPDATE_TYPE_DISTANCE, INVALID_INTERVAL, distance);
@@ -185,11 +184,11 @@ _LocationProviderImpl::StartLocationUpdatesByDistance(double distance)
 result
 _LocationProviderImpl::StopLocationUpdates(void)
 {
-       SysLog(NID_LOC, "Stopping the location updates for the request ID (%ld)", __reqId);
+       SysLog(NID_LOC, "Stopping the location updates for the request ID (%ld)", __locationUpdater.reqId);
 
-       SysTryReturn(NID_LOC, __locationUpdateType != _LOCATION_UPDATE_TYPE_NONE, E_INVALID_OPERATION, E_INVALID_OPERATION, "[E_INVALID_OPERATION] Location update has not been requested.");
+       SysTryReturn(NID_LOC, __locationUpdater.type != _LOCATION_UPDATE_TYPE_NONE, E_INVALID_OPERATION, E_INVALID_OPERATION, "[E_INVALID_OPERATION] Location update has not been requested.");
 
-       result r = __pLocationManager->StopLocationUpdates(__reqId);
+       result r = __pLocationManager->StopLocationUpdates(__locationUpdater.reqId);
 
        ResetLocationUpdates();
 
@@ -199,11 +198,11 @@ _LocationProviderImpl::StopLocationUpdates(void)
 void
 _LocationProviderImpl::KeepLocationUpdateAwake(bool enable)
 {
-       if (__awakeEnabled == enable)
+       if (__locationUpdater.awakeEnabled == enable)
        {
                return;
        }
-       __awakeEnabled = enable;
+       __locationUpdater.awakeEnabled = enable;
 
        UiApp* appInstance = Tizen::App::UiApp::GetInstance();
        if (appInstance == null)        // This is service APP. So should be handled now.
@@ -211,24 +210,24 @@ _LocationProviderImpl::KeepLocationUpdateAwake(bool enable)
                SysLog(NID_LOC, "Handling the request awake mode(%d) for the service application.", enable);
                if (enable == true)
                {
-                       if (__locationUpdateType != _LOCATION_UPDATE_TYPE_NONE && __locationUpdateStatus == LOC_SVC_STATUS_PAUSED)
+                       if (__locationUpdater.type != _LOCATION_UPDATE_TYPE_NONE && __locationUpdater.status == LOC_SVC_STATUS_PAUSED)
                        {
-                               SysLog(NID_LOC, "Requesting to start the location updates as the update type is (%x)", __locationUpdateType);
-                               __locationUpdateStatus = LOC_SVC_STATUS_NOT_FIXED;
-                               __pLocationManager->StartLocationUpdates(__criteria.GetAccuracy(), __updateInterval, this, __reqId);
+                               SysLog(NID_LOC, "Requesting to start the location updates as the update type is (%x)", __locationUpdater.type);
+                               __locationUpdater.status = LOC_SVC_STATUS_NOT_FIXED;
+                               __pLocationManager->StartLocationUpdates(__criteria.GetAccuracy(), __locationUpdater.updateInterval, this, __locationUpdater.reqId);
 
-                               NotifyServiceStatus(_LOC_PRV_EVENT_SEND_LOC_SVC_CB, __locationUpdateStatus);
+                               NotifyServiceStatus(_LOC_PRV_EVENT_SEND_LOC_SVC_CB, __locationUpdater.status);
                        }
                }
                else
                {
-                       if (__locationUpdateType != _LOCATION_UPDATE_TYPE_NONE && (__locationUpdateStatus == LOC_SVC_STATUS_RUNNING || __locationUpdateStatus == LOC_SVC_STATUS_NOT_FIXED))
+                       if (__locationUpdater.type != _LOCATION_UPDATE_TYPE_NONE && (__locationUpdater.status == LOC_SVC_STATUS_RUNNING || __locationUpdater.status == LOC_SVC_STATUS_NOT_FIXED))
                        {
-                               SysLog(NID_LOC, "Requesting to stop the location updates as the update type is (%x)", __locationUpdateType);
-                               __locationUpdateStatus = LOC_SVC_STATUS_PAUSED;
-                               __pLocationManager->StopLocationUpdates(__reqId);
+                               SysLog(NID_LOC, "Requesting to stop the location updates as the update type is (%x)", __locationUpdater.type);
+                               __locationUpdater.status = LOC_SVC_STATUS_PAUSED;
+                               __pLocationManager->StopLocationUpdates(__locationUpdater.reqId);
 
-                               NotifyServiceStatus(_LOC_PRV_EVENT_SEND_LOC_SVC_CB, __locationUpdateStatus);
+                               NotifyServiceStatus(_LOC_PRV_EVENT_SEND_LOC_SVC_CB, __locationUpdater.status);
                        }
                }
        }
@@ -247,50 +246,51 @@ _LocationProviderImpl::AddMonitoringRegion(const Coordinates& regionCenter, doub
 
        SysLog(NID_LOC, "Requested to add the monitoring region with center (Latitude: %lf, Longitude %lf) and radius (%lf).", regionCenter.GetLatitude(), regionCenter.GetLongitude(), radius);
 
-       const int DEAULT_REGION_MONITOR_INTERVAL = 5;
        static int nextRegionId = 0;
        result r = E_SUCCESS;
 
        std::unique_ptr< _RegionInfo > pRegionInfo(new (std::nothrow) _RegionInfo(regionCenter, radius, nextRegionId));
        SysTryReturn(NID_LOC, pRegionInfo != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
 
-       r = __pRegionList->Add(*pRegionInfo.get());
+       r = __regionMonitor.pRegionList->Add(*pRegionInfo.get());
        SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Failed to add the Region info into the list. Propogated.", GetErrorMessage(r));
 
        pRegionInfo.release();
        regionId = nextRegionId;
        nextRegionId++;
 
-       if (__regionMonitoringActive == true)
+       if (__regionMonitor.status != LOC_SVC_STATUS_IDLE)
        {
                return E_SUCCESS;
        }
 
-       r = __pLocationManager->StartLocationUpdates(__criteria.GetAccuracy(), DEAULT_REGION_MONITOR_INTERVAL, this, __regionReqId);
-       SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Failed to start the location updates. Propogating.", GetErrorMessage(r));
+       r = ActivateRegionMonitoring();
+       SysTryCatch(NID_LOC, r == E_SUCCESS, , r, "[%s] Failed to start the region monitoring. Propogating.", GetErrorMessage(r));
 
-       __regionMonitoringActive = true;
-       __regionMonitorStatus = LOC_SVC_STATUS_NOT_FIXED;
-       NotifyServiceStatus(_LOC_PRV_EVENT_SEND_MONITOR_SVC_CB, __regionMonitorStatus);
+       __regionMonitor.status = LOC_SVC_STATUS_NOT_FIXED;
+       NotifyServiceStatus(_LOC_PRV_EVENT_SEND_MONITOR_SVC_CB, __regionMonitor.status);
 
        return E_SUCCESS;
+
+CATCH:
+       __regionMonitor.pRegionList->RemoveAt(0);
+       return r;
 }
 
 result
 _LocationProviderImpl::RemoveMonitoringRegion(RegionId regionId)
 {
-       int count = __pRegionList->GetCount();
-       result r = E_SUCCESS;
+       int count = __regionMonitor.pRegionList->GetCount();
        bool isIdValid = false;
 
        SysLog(NID_LOC, "Total regions currently monitored is (%d).", count);
 
        for (int i = 0; i < count; i++)
        {
-               _RegionInfo* pRegionInfo = static_cast< _RegionInfo* >(__pRegionList->GetAt(i));
+               _RegionInfo* pRegionInfo = static_cast< _RegionInfo* >(__regionMonitor.pRegionList->GetAt(i));
                if (regionId == pRegionInfo->GetRegionId())
                {
-                       __pRegionList->RemoveAt(i, true);
+                       __regionMonitor.pRegionList->RemoveAt(i, true);
                        isIdValid = true;
                        break;
                }
@@ -298,16 +298,14 @@ _LocationProviderImpl::RemoveMonitoringRegion(RegionId regionId)
 
        SysTryReturn(NID_LOC, isIdValid == true, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The region ID is invalid.");
 
-       if (__pRegionList->GetCount() == 0)
+       if (__regionMonitor.pRegionList->GetCount() == 0)
        {
-               __regionMonitoringActive = false;
-               __regionMonitorStatus = LOC_SVC_STATUS_IDLE;
-               if (__locationUpdateStatus == LOC_SVC_STATUS_IDLE)  // As we are using the same variable for both region monitoring and location updates, this set is required here.
+               __regionMonitor.status = LOC_SVC_STATUS_IDLE;
+               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.
                {
                        __lastLocationAccuracy = LOC_ACCURACY_INVALID;
                }
-               r = __pLocationManager->StopLocationUpdates(__regionReqId);
-               SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] All regions are removed but failed to stop the location updates. Propagating.", GetErrorMessage(r));
+               StopRegionMonitoring();
        }
 
        return E_SUCCESS;
@@ -316,20 +314,16 @@ _LocationProviderImpl::RemoveMonitoringRegion(RegionId regionId)
 void
 _LocationProviderImpl::RemoveAllMonitoringRegions(void)
 {
-       result r = E_SUCCESS;
+       __regionMonitor.pRegionList->RemoveAll(true);
 
-       __pRegionList->RemoveAll(true);
-
-       if (__regionMonitoringActive == true)
+       if (__regionMonitor.status != LOC_SVC_STATUS_IDLE)
        {
-               __regionMonitoringActive = false;
-               __regionMonitorStatus = LOC_SVC_STATUS_IDLE;
-               if (__locationUpdateStatus == LOC_SVC_STATUS_IDLE)  // As we are using the same variable for both region monitoring and location updates, this set is required here.
+               __regionMonitor.status = LOC_SVC_STATUS_IDLE;
+               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.
                {
                        __lastLocationAccuracy = LOC_ACCURACY_INVALID;
                }
-               r = __pLocationManager->StopLocationUpdates(__regionReqId);
-               SysTryReturnVoidResult(NID_LOC, r == E_SUCCESS, r, "[%s] All regions are removed but failed to stop the location updates. Ignored.", GetErrorMessage(r));
+               StopRegionMonitoring();
        }
 
        return;
@@ -338,13 +332,13 @@ _LocationProviderImpl::RemoveAllMonitoringRegions(void)
 LocationServiceStatus
 _LocationProviderImpl::GetLocationUpdateStatus(void) const
 {
-       return __locationUpdateStatus;
+       return __locationUpdater.status;
 }
 
 LocationServiceStatus
 _LocationProviderImpl::GetRegionMonitoringStatus(void) const
 {
-       return __regionMonitorStatus;
+       return __regionMonitor.status;
 }
 
 LocationAccuracy
@@ -464,12 +458,19 @@ _LocationProviderImpl::OnLocationEventReceivedN(RequestId reqId, Tizen::Location
 
        Location* pLocation = &location;
        _LocationImpl* pLocationImpl = _LocationImpl::GetInstance(*pLocation);
-       if (__pLastLocation)
+
+       if (reqId == __locationUpdater.reqId)
        {
-               lastLocationTime = _LocationImpl::GetInstance(*__pLastLocation.get())->GetTimestampInMs();
+               SysLog(NID_LOC, "The location is updated for Location request.");
+               lastLocationTime = _LocationImpl::GetInstance(*__locationUpdater.pLocation.get())->GetTimestampInMs();
+       }
+       else if (reqId == __regionMonitor.reqId)
+       {
+               SysLog(NID_LOC, "The location is updated for Region monitoring.");
+               lastLocationTime = _LocationImpl::GetInstance(*__regionMonitor.pLocation.get())->GetTimestampInMs();
        }
 
-       long long timeDifference = abs(pLocationImpl->GetTimestampInMs() - lastLocationTime);
+       long long timeDifference = pLocationImpl->GetTimestampInMs() - lastLocationTime;
        SysLog(NID_LOC, "Time difference between last location timestamp (%lld) and current location timestamp (%lld) is (%lld).", lastLocationTime, pLocationImpl->GetTimestampInMs(), timeDifference);
        if (timeDifference > 0)
        {
@@ -484,13 +485,31 @@ _LocationProviderImpl::OnLocationEventReceivedN(RequestId reqId, Tizen::Location
                __pLocationListener->OnAccuracyChanged(currentAccuracy);
        }
 
-       if (reqId == __reqId)
+       if (reqId == __locationUpdater.reqId)
        {
                HandleLocationUpdate(location, isNew);
        }
-       else if (reqId == __regionReqId)
+       else if (reqId == __regionMonitor.reqId)
        {
-               HandleRegionMonitoring(location, isNew);
+               if (isNew)      // Copy the location only if it is new.
+               {
+                       *__regionMonitor.pLocation = location;
+               }
+
+               if (currentAccuracy != LOC_ACCURACY_INVALID && currentAccuracy <= __criteria.GetAccuracy())
+               {
+                       SysLog(NID_LOC, "Location criteria (accuracy: %ld) is met for handling region monitoring.", currentAccuracy);
+                       result r = __regionMonitor.pTimer->Cancel();
+                       SysTryLog(NID_LOC, r == E_SUCCESS, "Failed to cancel the timer.");
+
+                       r = __pLocationManager->StopLocationUpdates(__regionMonitor.reqId);
+                       SysTryLog(NID_LOC, r == E_SUCCESS, "Failed to stop the location updates.");
+                       HandleRegionMonitoring(location, isNew);
+               }
+               else
+               {
+                       SysLog(NID_LOC, "Location criteria (accuracy: %ld) is not met for handling region monitoring.", currentAccuracy);
+               }
        }
 
        delete pLocation;
@@ -520,81 +539,111 @@ _LocationProviderImpl::OnActiveAppChanged(const Tizen::App::AppId& appId)
        {
                SysLog(NID_LOC, "Application is active.");
 
-               if (__locationUpdateStatus == LOC_SVC_STATUS_PAUSED)
+               if (__locationUpdater.status == LOC_SVC_STATUS_PAUSED)
                {
                        SysLog(NID_LOC, "Start the location updates as the location update status is PAUSED.");
-                       __pLocationManager->StartLocationUpdates(__criteria.GetAccuracy(), __updateInterval, this, __reqId);
-                       __locationUpdateStatus = LOC_SVC_STATUS_NOT_FIXED;
-                       __pLocationListener->OnLocationUpdateStatusChanged(__locationUpdateStatus);
+                       __pLocationManager->StartLocationUpdates(__criteria.GetAccuracy(), __locationUpdater.updateInterval, this, __locationUpdater.reqId);
+                       __locationUpdater.status = LOC_SVC_STATUS_NOT_FIXED;
+                       __pLocationListener->OnLocationUpdateStatusChanged(__locationUpdater.status);
                }
        }
        else
        {
                SysLog(NID_LOC, "Application is not active.");
-               if (__awakeEnabled == false && (__locationUpdateStatus == LOC_SVC_STATUS_RUNNING || __locationUpdateStatus == LOC_SVC_STATUS_NOT_FIXED))
+               
+               if (__locationUpdater.awakeEnabled == false && (__locationUpdater.status == LOC_SVC_STATUS_RUNNING || __locationUpdater.status == LOC_SVC_STATUS_NOT_FIXED))
                {
-                       SysLog(NID_LOC, "Stop the location updates as application is not active with awake mode as (%d) and location update state as (%x).", __awakeEnabled, __locationUpdateStatus);
-                       __pLocationManager->StopLocationUpdates(__reqId);
-                       __locationUpdateStatus = LOC_SVC_STATUS_PAUSED;
-                       __pLocationListener->OnLocationUpdateStatusChanged(__locationUpdateStatus);
+                       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);
+                       __pLocationManager->StopLocationUpdates(__locationUpdater.reqId);
+                       __locationUpdater.status = LOC_SVC_STATUS_PAUSED;
+                       __pLocationListener->OnLocationUpdateStatusChanged(__locationUpdater.status);
                }
        }
 }
 
+void
+_LocationProviderImpl::OnAlarmExpired(Alarm& alarm)
+{
+       SysLog(NID_LOC, "Region Monitor Alarm expired.");
+       
+       result r = ActivateRegionMonitoring();
+       SysTryReturnVoidResult(NID_LOC, r == E_SUCCESS, r, "[%s] Failed to start the region monitoring. Propogating.", GetErrorMessage(r));
+}
+
+void
+_LocationProviderImpl::OnTimerExpired(Timer& timer)
+{
+       SysLog(NID_LOC, "Region Monitor timer expired due to unavailability of location information.");
+       __pLocationManager->StopLocationUpdates(__regionMonitor.reqId);
+       HandleRegionMonitoring(*__regionMonitor.pLocation, __regionMonitor.pLocation->IsValid());
+}
+
 result
 _LocationProviderImpl::StartLocationUpdates(LocationUpdateType updateType, int interval, double distance)
 {
        result r = E_SUCCESS;
-       const int CHECKING_INTERVAL = 10;
+       bool startUpdate = true;
 
        if (updateType == _LOCATION_UPDATE_TYPE_INTERVAL)
        {
-               __updateInterval = interval;
+               __locationUpdater.updateInterval = interval;
        }
        else if (updateType == _LOCATION_UPDATE_TYPE_DISTANCE)
        {
-               __updateInterval = CHECKING_INTERVAL;
-               __distanceThreshold = distance;
+               __locationUpdater.updateInterval = DEFAULT_DISTANCE_CHECKING_INTERVAL;
+               __locationUpdater.distanceThreshold = distance;
        }
 
-       __locationUpdateType = updateType;
-
-       if (__awakeEnabled == true)
-       {
-               r = __pLocationManager->StartLocationUpdates(__criteria.GetAccuracy(), __updateInterval, this, __reqId);
-               SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Failed to start the Native location updates.", GetErrorMessage(r));
-               __locationUpdateStatus = LOC_SVC_STATUS_NOT_FIXED;
-       }
-       else
+       if  (!__locationUpdater.awakeEnabled)
        {
                UiApp* pAppInstance = Tizen::App::UiApp::GetInstance();
                if (pAppInstance == null)
                {
-                       __locationUpdateStatus = LOC_SVC_STATUS_PAUSED;
+                       startUpdate = false;
                }
-               else
+               else 
                {
                        AppUiState appUiState = pAppInstance->GetAppUiState();
-                       if (appUiState == APP_UI_STATE_FOREGROUND || appUiState == APP_UI_STATE_PARTIAL_BACKGROUND)
-                       {
-                               r = __pLocationManager->StartLocationUpdates(__criteria.GetAccuracy(), __updateInterval, this, __reqId);
-                               SysTryCatch(NID_LOC, r == E_SUCCESS, , r, "[%s] Failed to start the location updates. Propagating.", GetErrorMessage(r));
-                               __locationUpdateStatus = LOC_SVC_STATUS_NOT_FIXED;
-                       }
-                       else
+               
+                       if (appUiState == APP_UI_STATE_BACKGROUND)
                        {
-                               __locationUpdateStatus = LOC_SVC_STATUS_PAUSED;
+                               SysLog(NID_LOC, "App is background.");
+                               startUpdate = false;
                        }
                }
        }
 
-       SysLog(NID_LOC, "Update type is (%x). The request Id is (%ld) and the update status is (%x).", __locationUpdateType, __reqId, __locationUpdateStatus);
-       NotifyServiceStatus(_LOC_PRV_EVENT_SEND_LOC_SVC_CB, __locationUpdateStatus);
+       if (startUpdate)
+       {
+               if (__locationUpdater.type != _LOCATION_UPDATE_TYPE_NONE)
+               {
+                       SysLog(NID_LOC, "Update session already running. Updating the interval to %d seconds", __locationUpdater.updateInterval);
+                       r = __pLocationManager->ChangeUpdateInterval(__locationUpdater.reqId, __locationUpdater.updateInterval);
+                       SysTryCatch(NID_LOC, r == E_SUCCESS, , r, "[%s] Failed to update the request interval. Propagating.", GetErrorMessage(r));
+                       __locationUpdater.type = updateType;
+                       return E_SUCCESS;
+               }
+               else
+               {
+                       r = __pLocationManager->StartLocationUpdates(__criteria.GetAccuracy(), __locationUpdater.updateInterval, this, __locationUpdater.reqId);
+                       SysTryCatch(NID_LOC, r == E_SUCCESS, , r, "[%s] Failed to start the Native location updates. Propagating.", GetErrorMessage(r));
+                       __locationUpdater.status = LOC_SVC_STATUS_NOT_FIXED;
+               }       
+       }
+       else
+       {
+               __locationUpdater.status = LOC_SVC_STATUS_PAUSED;       
+       }
+
+       __locationUpdater.type = updateType;
+
+       SysLog(NID_LOC, "Update type is (%x). The request Id is (%ld) and the update status is (%x).", __locationUpdater.type, __locationUpdater.reqId, __locationUpdater.status);
+       NotifyServiceStatus(_LOC_PRV_EVENT_SEND_LOC_SVC_CB, __locationUpdater.status);
 
        return E_SUCCESS;
 
 CATCH:
-       __locationUpdateType = _LOCATION_UPDATE_TYPE_NONE;
+       __locationUpdater.type = _LOCATION_UPDATE_TYPE_NONE;
        return r;
 }
 
@@ -605,28 +654,28 @@ _LocationProviderImpl::CheckDistanceThreshold(const Location& oldPosition, const
        const Coordinates coordOld = oldPosition.GetCoordinates();
        const Coordinates coordNew = newPosition.GetCoordinates();
 
-       if (__firstLocationUpdate)
+       if (__locationUpdater.firstLocationUpdate)
        {
                SysLog(NID_LOC, "First location update. So send true.");
-               __firstLocationUpdate = false;
+               __locationUpdater.firstLocationUpdate = false;
                return true;
        }
 
        displacement = coordOld.GetDistanceTo(coordNew);
        SysLog(NID_LOC, "Displacement is (%lf)", displacement);
-       return ((displacement > __distanceThreshold) ? true : false);
+       return ((displacement > __locationUpdater.distanceThreshold) ? true : false);
 }
 
 void
 _LocationProviderImpl::ResetLocationUpdates(void)
 {
-       __firstLocationUpdate = true;
-       __reqId = -1;
+       __locationUpdater.firstLocationUpdate = true;
+       __locationUpdater.reqId = -1;
        __lastLocationAccuracy = LOC_ACCURACY_INVALID;
-       __locationUpdateType = _LOCATION_UPDATE_TYPE_NONE;
-       __locationUpdateStatus = LOC_SVC_STATUS_IDLE;
-       __updateInterval = 0;
-       __distanceThreshold = 0.0;
+       __locationUpdater.type = _LOCATION_UPDATE_TYPE_NONE;
+       __locationUpdater.status = LOC_SVC_STATUS_IDLE;
+       __locationUpdater.updateInterval = 0;
+       __locationUpdater.distanceThreshold = 0.0;
 }
 
 void
@@ -659,11 +708,11 @@ _LocationProviderImpl::FireImpl(Tizen::Base::Runtime::IEventListener& listener,
 void
 _LocationProviderImpl::HandleLocationUpdate(Tizen::Locations::Location& location, bool isNew)
 {
-       LocationServiceStatus newLocationUpdateStatus = __locationUpdateStatus;
+       LocationServiceStatus newLocationUpdateStatus = __locationUpdater.status;
 
        if (isNew)
        {
-               if (__locationUpdateType != _LOCATION_UPDATE_TYPE_NONE && __locationUpdateStatus != LOC_SVC_STATUS_PAUSED)
+               if (__locationUpdater.type != _LOCATION_UPDATE_TYPE_NONE && __locationUpdater.status != LOC_SVC_STATUS_PAUSED)
                {
                        newLocationUpdateStatus = LOC_SVC_STATUS_RUNNING;
                }
@@ -671,7 +720,7 @@ _LocationProviderImpl::HandleLocationUpdate(Tizen::Locations::Location& location
        else if (_LocationImpl::GetInstance(location)->IsDenied())
        {
                SysLog(NID_LOC, "User consent not available.");
-               if (__locationUpdateType != _LOCATION_UPDATE_TYPE_NONE && __locationUpdateStatus != LOC_SVC_STATUS_PAUSED)
+               if (__locationUpdater.type != _LOCATION_UPDATE_TYPE_NONE && __locationUpdater.status != LOC_SVC_STATUS_PAUSED)
                {
                        newLocationUpdateStatus = LOC_SVC_STATUS_DENIED;
                }
@@ -679,35 +728,35 @@ _LocationProviderImpl::HandleLocationUpdate(Tizen::Locations::Location& location
        else
        {
                SysLog(NID_LOC, "Invalid Location Update.");
-               if (__locationUpdateType != _LOCATION_UPDATE_TYPE_NONE && __locationUpdateStatus != LOC_SVC_STATUS_PAUSED)
+               if (__locationUpdater.type != _LOCATION_UPDATE_TYPE_NONE && __locationUpdater.status != LOC_SVC_STATUS_PAUSED)
                {
                        newLocationUpdateStatus = LOC_SVC_STATUS_NOT_FIXED;
                }
        }
 
-       if (newLocationUpdateStatus != __locationUpdateStatus)
+       if (newLocationUpdateStatus != __locationUpdater.status)
        {
                SysLog(NID_LOC, "Location Update Satus changed to (%x). Notify the status.", newLocationUpdateStatus);
-               __locationUpdateStatus = newLocationUpdateStatus;
-               __pLocationListener->OnLocationUpdateStatusChanged(__locationUpdateStatus);
+               __locationUpdater.status = newLocationUpdateStatus;
+               __pLocationListener->OnLocationUpdateStatusChanged(__locationUpdater.status);
        }
 
        if (newLocationUpdateStatus == LOC_SVC_STATUS_RUNNING)
        {
-               if (__locationUpdateType == _LOCATION_UPDATE_TYPE_DISTANCE)
+               if (__locationUpdater.type == _LOCATION_UPDATE_TYPE_DISTANCE)
                {
-                       if (CheckDistanceThreshold(*__pLastLocation.get(), location) == true)
+                       if (CheckDistanceThreshold(*__locationUpdater.pLocation.get(), location) == true)
                        {
-                               SysLog(NID_LOC, "Location displacement exceeds the distance threshold (%lf). Notify the location.", __distanceThreshold);
+                               SysLog(NID_LOC, "Location displacement exceeds the distance threshold (%lf). Notify the location.", __locationUpdater.distanceThreshold);
                                __pLocationListener->OnLocationUpdated(location);
-                               *__pLastLocation.get() = location;
+                               *__locationUpdater.pLocation.get() = location;
                        }
                }
-               else if (__locationUpdateType == _LOCATION_UPDATE_TYPE_INTERVAL)
+               else if (__locationUpdater.type == _LOCATION_UPDATE_TYPE_INTERVAL)
                {
                        SysLog(NID_LOC, "Location time interval expired. Notify the location.");
                        __pLocationListener->OnLocationUpdated(location);
-                       *__pLastLocation.get() = location;
+                       *__locationUpdater.pLocation.get() = location;
                }
        }
 }
@@ -715,7 +764,7 @@ _LocationProviderImpl::HandleLocationUpdate(Tizen::Locations::Location& location
 void
 _LocationProviderImpl::HandleRegionMonitoring(Tizen::Locations::Location& location, bool isNew)
 {
-       LocationServiceStatus newRegionMonitorStatus = __regionMonitorStatus;
+       LocationServiceStatus newRegionMonitorStatus = __regionMonitor.status;
 
        if (isNew)
        {
@@ -730,30 +779,31 @@ _LocationProviderImpl::HandleRegionMonitoring(Tizen::Locations::Location& locati
                newRegionMonitorStatus = LOC_SVC_STATUS_NOT_FIXED;
        }
 
-       if (newRegionMonitorStatus != __regionMonitorStatus)
+       if (newRegionMonitorStatus != __regionMonitor.status)
        {
                SysLog(NID_LOC, "Region Monitoring Satus changed to (%x). Notify the status.", newRegionMonitorStatus);
-               __regionMonitorStatus = newRegionMonitorStatus;
-               __pLocationListener->OnRegionMonitoringStatusChanged(__regionMonitorStatus);
+               __regionMonitor.status = newRegionMonitorStatus;
+               __pLocationListener->OnRegionMonitoringStatusChanged(__regionMonitor.status);
        }
 
        if (newRegionMonitorStatus == LOC_SVC_STATUS_RUNNING)
        {
                NotifyRegionCrossedStatus(location);
-               *__pLastLocation.get() = location;
        }
+
+       SetNextRegionMonitoringTime();
 }
 
 void
 _LocationProviderImpl::NotifyRegionCrossedStatus(const Tizen::Locations::Location& location)
 {
-       int count = __pRegionList->GetCount();
+       int count = __regionMonitor.pRegionList->GetCount();
 
        SysLog(NID_LOC, "Number of regions currently monitored is (%d)", count);
 
        for (int i = 0; i < count; i++)
        {
-               _RegionInfo* pRegionInfo = static_cast< _RegionInfo* >(__pRegionList->GetAt(i));
+               _RegionInfo* pRegionInfo = static_cast< _RegionInfo* >(__regionMonitor.pRegionList->GetAt(i));
 
                if (pRegionInfo)
                {
@@ -920,4 +970,66 @@ _LocationProviderImpl::GetUserPrivilege(void)
 
        return true;
 }
+
+result
+_LocationProviderImpl::ActivateRegionMonitoring(void)
+{
+       long long currentTime;
+       SystemTime::GetTicks(currentTime);
+
+       SysLog(NID_LOC, "Current system time is %lld", currentTime);
+       
+       _LocationImpl::GetInstance(*__regionMonitor.pLocation)->SetValidity(false);
+       _LocationImpl::GetInstance(*__regionMonitor.pLocation)->SetTimestamp(currentTime);
+       
+       result r = __regionMonitor.pTimer->Start(DEFAULT_WAITING_TIME_FOR_FIXING_LOCATION * 1000);
+       SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Failed to start the timer. Propogating.", GetErrorMessage(r));
+
+       r = __pLocationManager->StartLocationUpdates(__criteria.GetAccuracy(), MIN_LOCATION_UPDATE_INTERVAL, this, __regionMonitor.reqId);
+       SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Failed to start the location updates. Propogating.", GetErrorMessage(r));
+
+       SysLog(NID_LOC, "Timer & Location updates are started.");
+       return E_SUCCESS;
+}
+
+void
+_LocationProviderImpl::StopRegionMonitoring(void)
+{
+       result r = _AlarmImpl::GetInstance(__regionMonitor.pAlarm.get())->Cancel();
+       SysTryReturnVoidResult(NID_LOC, r == E_SUCCESS, r, "[%s] Failed to stop the alarm. Ignored.", GetErrorMessage(r));
+
+       r = __regionMonitor.pTimer->Cancel();
+       SysTryReturnVoidResult(NID_LOC, r == E_SUCCESS, r, "[%s] Failed to stop the timer. Ignored.", GetErrorMessage(r));
+
+       r = __pLocationManager->StopLocationUpdates(__regionMonitor.reqId);
+       SysTryReturnVoidResult(NID_LOC, r == E_SUCCESS, r, "[%s] All regions are removed but failed to stop the location updates. Ignored.", GetErrorMessage(r));
+}
+
+void
+_LocationProviderImpl::SetNextRegionMonitoringTime(void)
+{
+       DateTime alarmDateTime;
+       long long alarmTime = DEFAULT_REGION_MONITORING_CYCLE_INTERVAL;
+       SystemTime::GetCurrentTime(TIME_MODE_WALL, alarmDateTime);
+
+       SysLog(NID_LOC, "Current System Time is %ls", alarmDateTime.ToString().GetPointer());
+
+       if (__regionMonitor.pLocation->IsValid())
+       {
+               const int bufferTime = 5;   //Buffer of 5 seconds for determining the alarmTime;
+               double minDistance = _MathUtils::GetShortestDistance(*__regionMonitor.pLocation, *__regionMonitor.pRegionList);
+               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.
+
+               if (newAlarmTime > alarmTime)
+               {
+                       alarmTime = newAlarmTime;
+               }
+       }
+
+       alarmDateTime.AddSeconds(alarmTime);
+       result r = _AlarmImpl::GetInstance(__regionMonitor.pAlarm.get())->Set(alarmDateTime, 0, null);  
+       SysTryLog(NID_LOC, r == E_SUCCESS, "Failed to set the alarm for next cycle.");
+       
+       SysLog(NID_LOC, "Next alarm expires after %ld seconds.", alarmTime);
+}
 }}