2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
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
9 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 * @file FLoc_LocationProviderImpl.cpp
20 * @brief This is the implementation file for the %_LocationProviderImpl class.
22 * This implementation file contains the definitions of the %_LocationProviderImpl class methods.
25 #include <unique_ptr.h>
26 #include <FApp_AppManagerImpl.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_SettingInfoImpl.h>
43 #include "FLoc_LocationImpl.h"
44 #include "FLoc_LocationManager.h"
45 #include "FLoc_LocationMonitor.h"
46 #include "FLoc_LocationProviderImpl.h"
47 #include "FLoc_MathUtils.h"
48 #include "FLoc_Types.h"
50 using namespace Tizen::App;
51 using namespace Tizen::Base;
52 using namespace Tizen::Base::Collection;
53 using namespace Tizen::Base::Runtime;
54 using namespace Tizen::Base::Utility;
55 using namespace Tizen::System;
58 namespace Tizen { namespace Locations
61 _LocationProviderImpl::_LocationProviderImpl(void)
62 : Tizen::Base::Runtime::_Event()
63 , __firstLocationUpdate(true)
64 , __regionMonitoringActive(false)
65 , __awakeEnabled(false)
67 , __locationUpdateType(_LOCATION_UPDATE_TYPE_NONE)
68 , __locationUpdateStatus(LOC_SVC_STATUS_IDLE)
69 , __regionMonitorStatus(LOC_SVC_STATUS_IDLE)
70 , __lastLocationAccuracy(LOC_ACCURACY_INVALID)
73 , __distanceThreshold(0.0)
74 , __pLocationListener(null)
75 , __pLocationManager(null)
76 , __pLastLocation(null)
81 _LocationProviderImpl::~_LocationProviderImpl(void)
83 UiApp* pAppInstance = Tizen::App::UiApp::GetInstance();
86 _AppManagerImpl* pAppManager = _AppManagerImpl::GetInstance();
89 pAppManager->RemoveActiveAppEventListener(*this);
93 StopLocationUpdates();
94 RemoveAllMonitoringRegions();
98 _LocationProviderImpl::Construct(const LocationCriteria& criteria, ILocationProviderListener& listener)
100 result r = E_SUCCESS;
101 _LocationManager* pLocationManager = null;
103 pLocationManager = _LocationManager::GetInstance();
104 SysTryReturn(NID_LOC, pLocationManager != null, GetLastResult(), GetLastResult(), "[%s] Failed to get the location manager instance.", GetErrorMessage(GetLastResult()));
106 std::unique_ptr< Tizen::Base::Collection::ArrayList, AllElementsDeleter > pRegionList(new (std::nothrow) ArrayList());
107 SysTryReturn(NID_LOC, pRegionList != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
109 r = pRegionList->Construct();
110 SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Failed to construct the list. Propagating.", GetErrorMessage(r));
112 UiApp* pAppInstance = Tizen::App::UiApp::GetInstance();
113 if (pAppInstance != null)
115 _AppManagerImpl* pAppManager = _AppManagerImpl::GetInstance();
116 SysTryReturn(NID_LOC, pAppManager, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] System error occured.");
118 r = pAppManager->AddActiveAppEventListener(*this);
119 SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Error occured during adding the event listener to app manager. Propagating.", GetErrorMessage(r));
122 std::unique_ptr< Tizen::Locations::Location > pLocation(_LocationImpl::GetLocationInstanceN());
123 SysTryReturn(NID_LOC, pLocation != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
125 _Event::Initialize();
126 _Event::AddListener(*this);
128 __pRegionList = std::move(pRegionList);
129 __pLastLocation = std::move(pLocation);
130 __criteria = criteria;
131 __pLocationListener = &listener;
132 __pLocationManager = pLocationManager;
134 SysLog(NID_LOC, "Location provider constructed with the accuracy (%x).", criteria.GetAccuracy());
140 _LocationProviderImpl::StartLocationUpdatesByInterval(int interval)
142 bool userConsent = GetUserPrivilege();
143 SysTryReturn(NID_LOC, userConsent, E_USER_NOT_CONSENTED, E_USER_NOT_CONSENTED, "[E_USER_NOT_CONSENTED] The user has disabled the required settings.");
145 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);
147 if (__locationUpdateType == _LOCATION_UPDATE_TYPE_INTERVAL && __updateInterval == interval)
151 else if (__locationUpdateType == _LOCATION_UPDATE_TYPE_DISTANCE || __locationUpdateType == _LOCATION_UPDATE_TYPE_INTERVAL)
153 __pLocationManager->StopLocationUpdates(__reqId);
154 __locationUpdateStatus = LOC_SVC_STATUS_IDLE;
157 const double INVALID_DISTANCE_THRESHOLD = 0.0;
158 return StartLocationUpdates(_LOCATION_UPDATE_TYPE_INTERVAL, interval, INVALID_DISTANCE_THRESHOLD);
162 _LocationProviderImpl::StartLocationUpdatesByDistance(double distance)
164 bool userConsent = GetUserPrivilege();
165 SysTryReturn(NID_LOC, userConsent, E_USER_NOT_CONSENTED, E_USER_NOT_CONSENTED, "[E_USER_NOT_CONSENTED] The user has disabled the required settings.");
167 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);
169 SysTryReturn(NID_LOC, Double::IsNaN(distance) == false, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The distance is NaN.");
171 if (__locationUpdateType == _LOCATION_UPDATE_TYPE_DISTANCE && (Double::Compare(__distanceThreshold, distance) == 0))
175 else if (__locationUpdateType == _LOCATION_UPDATE_TYPE_DISTANCE || __locationUpdateType == _LOCATION_UPDATE_TYPE_INTERVAL)
177 __pLocationManager->StopLocationUpdates(__reqId);
178 __locationUpdateStatus = LOC_SVC_STATUS_IDLE;
181 const int INVALID_INTERVAL = 0;
182 return StartLocationUpdates(_LOCATION_UPDATE_TYPE_DISTANCE, INVALID_INTERVAL, distance);
186 _LocationProviderImpl::StopLocationUpdates(void)
188 SysLog(NID_LOC, "Stopping the location updates for the request ID (%ld)", __reqId);
190 SysTryReturn(NID_LOC, __locationUpdateType != _LOCATION_UPDATE_TYPE_NONE, E_INVALID_OPERATION, E_INVALID_OPERATION, "[E_INVALID_OPERATION] Location update has not been requested.");
192 result r = __pLocationManager->StopLocationUpdates(__reqId);
194 ResetLocationUpdates();
200 _LocationProviderImpl::KeepLocationUpdateAwake(bool enable)
202 if (__awakeEnabled == enable)
206 __awakeEnabled = enable;
208 UiApp* appInstance = Tizen::App::UiApp::GetInstance();
209 if (appInstance == null) // This is service APP. So should be handled now.
211 SysLog(NID_LOC, "Handling the request awake mode(%d) for the service application.", enable);
214 if (__locationUpdateType != _LOCATION_UPDATE_TYPE_NONE && __locationUpdateStatus == LOC_SVC_STATUS_PAUSED)
216 SysLog(NID_LOC, "Requesting to start the location updates as the update type is (%x)", __locationUpdateType);
217 __locationUpdateStatus = LOC_SVC_STATUS_NOT_FIXED;
218 __pLocationManager->StartLocationUpdates(__criteria.GetAccuracy(), __updateInterval, this, __reqId);
220 NotifyServiceStatus(_LOC_PRV_EVENT_SEND_LOC_SVC_CB, __locationUpdateStatus);
225 if (__locationUpdateType != _LOCATION_UPDATE_TYPE_NONE && (__locationUpdateStatus == LOC_SVC_STATUS_RUNNING || __locationUpdateStatus == LOC_SVC_STATUS_NOT_FIXED))
227 SysLog(NID_LOC, "Requesting to stop the location updates as the update type is (%x)", __locationUpdateType);
228 __locationUpdateStatus = LOC_SVC_STATUS_PAUSED;
229 __pLocationManager->StopLocationUpdates(__reqId);
231 NotifyServiceStatus(_LOC_PRV_EVENT_SEND_LOC_SVC_CB, __locationUpdateStatus);
238 _LocationProviderImpl::AddMonitoringRegion(const Coordinates& regionCenter, double radius, RegionId& regionId)
240 bool userConsent = GetUserPrivilege();
241 SysTryReturn(NID_LOC, userConsent, E_USER_NOT_CONSENTED, E_USER_NOT_CONSENTED, "[E_USER_NOT_CONSENTED] The user has disabled the required settings.");
243 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.");
245 SysTryReturn(NID_LOC, (!Double::IsNaN(radius) && !Double::IsNaN(regionCenter.GetLatitude()) && !Double::IsNaN(regionCenter.GetLongitude())),
246 E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] One of the value is NaN.");
248 SysLog(NID_LOC, "Requested to add the monitoring region with center (Latitude: %lf, Longitude %lf) and radius (%lf).", regionCenter.GetLatitude(), regionCenter.GetLongitude(), radius);
250 const int DEAULT_REGION_MONITOR_INTERVAL = 5;
251 static int nextRegionId = 0;
252 result r = E_SUCCESS;
254 std::unique_ptr< _RegionInfo > pRegionInfo(new (std::nothrow) _RegionInfo(regionCenter, radius, nextRegionId));
255 SysTryReturn(NID_LOC, pRegionInfo != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
257 r = __pRegionList->Add(*pRegionInfo.get());
258 SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Failed to add the Region info into the list. Propogated.", GetErrorMessage(r));
260 pRegionInfo.release();
261 regionId = nextRegionId;
264 if (__regionMonitoringActive == true)
269 r = __pLocationManager->StartLocationUpdates(__criteria.GetAccuracy(), DEAULT_REGION_MONITOR_INTERVAL, this, __regionReqId);
270 SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Failed to start the location updates. Propogating.", GetErrorMessage(r));
272 __regionMonitoringActive = true;
273 __regionMonitorStatus = LOC_SVC_STATUS_NOT_FIXED;
274 NotifyServiceStatus(_LOC_PRV_EVENT_SEND_MONITOR_SVC_CB, __regionMonitorStatus);
280 _LocationProviderImpl::RemoveMonitoringRegion(RegionId regionId)
282 int count = __pRegionList->GetCount();
283 result r = E_SUCCESS;
284 bool isIdValid = false;
286 SysLog(NID_LOC, "Total regions currently monitored is (%d).", count);
288 for (int i = 0; i < count; i++)
290 _RegionInfo* pRegionInfo = static_cast< _RegionInfo* >(__pRegionList->GetAt(i));
291 if (regionId == pRegionInfo->GetRegionId())
293 __pRegionList->RemoveAt(i, true);
299 SysTryReturn(NID_LOC, isIdValid == true, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The region ID is invalid.");
301 if (__pRegionList->GetCount() == 0)
303 __regionMonitoringActive = false;
304 __regionMonitorStatus = LOC_SVC_STATUS_IDLE;
305 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.
307 __lastLocationAccuracy = LOC_ACCURACY_INVALID;
309 r = __pLocationManager->StopLocationUpdates(__regionReqId);
310 SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] All regions are removed but failed to stop the location updates. Propagating.", GetErrorMessage(r));
317 _LocationProviderImpl::RemoveAllMonitoringRegions(void)
319 result r = E_SUCCESS;
321 __pRegionList->RemoveAll(true);
323 if (__regionMonitoringActive == true)
325 __regionMonitoringActive = false;
326 __regionMonitorStatus = LOC_SVC_STATUS_IDLE;
327 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.
329 __lastLocationAccuracy = LOC_ACCURACY_INVALID;
331 r = __pLocationManager->StopLocationUpdates(__regionReqId);
332 SysTryReturnVoidResult(NID_LOC, r == E_SUCCESS, r, "[%s] All regions are removed but failed to stop the location updates. Ignored.", GetErrorMessage(r));
338 LocationServiceStatus
339 _LocationProviderImpl::GetLocationUpdateStatus(void) const
341 return __locationUpdateStatus;
344 LocationServiceStatus
345 _LocationProviderImpl::GetRegionMonitoringStatus(void) const
347 return __regionMonitorStatus;
351 _LocationProviderImpl::GetCurrentAccuracy(void) const
353 return __lastLocationAccuracy;
357 _LocationProviderImpl::GetLocation(const LocationCriteria& criteria)
359 Location retLocation(_LocationImpl::GetLocationInstance());
361 bool userConsent = GetUserPrivilege();
362 SysTryReturn(NID_LOC, userConsent, retLocation, E_USER_NOT_CONSENTED, "[E_USER_NOT_CONSENTED] The user has disabled the required settings.");
364 Location* pLocation = null;
365 const int MAX_TIMEOUT = 30;
366 result r = E_SUCCESS;
367 _LocationManager* pLocationManager = null;
369 SysLog(NID_LOC, "Requesting for single location with criteria (%x).", criteria.GetAccuracy());
371 std::unique_ptr< _LocationMonitor > pLocMonitor(new (std::nothrow) _LocationMonitor());
372 SysTryCatch(NID_LOC, pLocMonitor, , E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
374 r = pLocMonitor->Construct(MAX_TIMEOUT, criteria.GetAccuracy());
375 SysTryCatch(NID_LOC, r == E_SUCCESS, , r, "[%s] Failed to construct the Location Monitor.", GetErrorMessage(r));
377 pLocationManager = _LocationManager::GetInstance();
378 SysTryCatch(NID_LOC, pLocationManager, , r, "[%s] Failed to get the location manager instance.", GetErrorMessage(r));
380 r = pLocationManager->RegisterLocationMonitor(pLocMonitor.get());
381 SysTryCatch(NID_LOC, r == E_SUCCESS, , r, "[%s] Failed to register the location monitor.", GetErrorMessage(r));
383 r = pLocMonitor->Wait();
387 pLocation = pLocMonitor->GetLocationN();
392 retLocation = *pLocation;
396 SetLastResult(E_LOCATION_UNAVAILABLE);
408 _LocationProviderImpl::GetLastKnownLocation(void)
410 Location retLocation(_LocationImpl::GetLocationInstance());
412 bool userConsent = GetUserPrivilege();
413 SysTryReturn(NID_LOC, userConsent, retLocation, E_USER_NOT_CONSENTED, "[E_USER_NOT_CONSENTED] The user has disabled the required settings.");
415 _LocationManager* pLocationManager = _LocationManager::GetInstance();
416 SysTryReturn(NID_LOC, pLocationManager, retLocation, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
418 retLocation = pLocationManager->GetLastKnownLocation();
420 if (!retLocation.IsValid())
422 SetLastResult(E_LOCATION_UNAVAILABLE);
435 _LocationProviderImpl::OnLocationUpdated(RequestId reqId, const Tizen::Locations::Location& location)
437 SysLog(NID_LOC, "Location is updated from Location Manager for the request ID (%ld).", reqId);
439 std::unique_ptr< Location > pLocation(new (std::nothrow) Location(location));
440 SysTryReturnVoidResult(NID_LOC, pLocation, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
442 std::unique_ptr< _LocProviderEventArg > pLocProviderEventArg(new (std::nothrow) _LocProviderEventArg());
443 SysTryReturnVoidResult(NID_LOC, pLocProviderEventArg, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
445 pLocProviderEventArg->SetEventType(_LOC_PRV_EVENT_SEND_LOC);
446 pLocProviderEventArg->SetLocation(pLocation.get());
447 pLocProviderEventArg->SetRequestId(reqId);
450 result r = _Event::FireAsync(*pLocProviderEventArg);
451 SysTryReturnVoidResult(NID_LOC, r == E_SUCCESS, r, "[%s] Failed to fire the event.", GetErrorMessage(r));
452 pLocProviderEventArg.release();
458 _LocationProviderImpl::OnLocationEventReceivedN(RequestId reqId, Tizen::Locations::Location& location)
460 SysLog(NID_LOC, "Location Event received.");
462 LocationAccuracy currentAccuracy = LOC_ACCURACY_INVALID;
463 long long lastLocationTime = 0;
465 Location* pLocation = &location;
466 _LocationImpl* pLocationImpl = _LocationImpl::GetInstance(*pLocation);
469 lastLocationTime = _LocationImpl::GetInstance(*__pLastLocation.get())->GetTimestampInMs();
472 long long timeDifference = abs(pLocationImpl->GetTimestampInMs() - lastLocationTime);
473 SysLog(NID_LOC, "Time difference between last location timestamp (%lld) and current location timestamp (%lld) is (%lld).", lastLocationTime, pLocationImpl->GetTimestampInMs(), timeDifference);
474 if (timeDifference > 0)
477 currentAccuracy = __pLocationManager->GetAccuracyLevel(pLocation->GetHorizontalAccuracy());
480 if (currentAccuracy != __lastLocationAccuracy)
482 SysLog(NID_LOC, "Notify the accuracy change.");
483 __lastLocationAccuracy = currentAccuracy;
484 __pLocationListener->OnAccuracyChanged(currentAccuracy);
487 if (reqId == __reqId)
489 HandleLocationUpdate(location, isNew);
491 else if (reqId == __regionReqId)
493 HandleRegionMonitoring(location, isNew);
500 _LocationProviderImpl::OnLocationUpdateStatusChanged(Tizen::Locations::LocationServiceStatus locSvcStatus)
502 __pLocationListener->OnLocationUpdateStatusChanged(locSvcStatus);
506 _LocationProviderImpl::OnRegionMonitoringStatusChanged(Tizen::Locations::LocationServiceStatus locSvcStatus)
508 __pLocationListener->OnRegionMonitoringStatusChanged(locSvcStatus);
512 _LocationProviderImpl::OnActiveAppChanged(const Tizen::App::AppId& appId)
514 Tizen::App::App* pApp = Tizen::App::App::GetInstance();
515 Tizen::App::AppId currentAppId = pApp->GetAppId();
517 SysLog(NID_LOC, "Active App ID is (%ls) and the current app Id is (%ls)", appId.GetPointer(), currentAppId.GetPointer());
519 if (currentAppId == appId)
521 SysLog(NID_LOC, "Application is active.");
523 if (__locationUpdateStatus == LOC_SVC_STATUS_PAUSED)
525 SysLog(NID_LOC, "Start the location updates as the location update status is PAUSED.");
526 __pLocationManager->StartLocationUpdates(__criteria.GetAccuracy(), __updateInterval, this, __reqId);
527 __locationUpdateStatus = LOC_SVC_STATUS_NOT_FIXED;
528 __pLocationListener->OnLocationUpdateStatusChanged(__locationUpdateStatus);
533 SysLog(NID_LOC, "Application is not active.");
534 if (__awakeEnabled == false && (__locationUpdateStatus == LOC_SVC_STATUS_RUNNING || __locationUpdateStatus == LOC_SVC_STATUS_NOT_FIXED))
536 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);
537 __pLocationManager->StopLocationUpdates(__reqId);
538 __locationUpdateStatus = LOC_SVC_STATUS_PAUSED;
539 __pLocationListener->OnLocationUpdateStatusChanged(__locationUpdateStatus);
545 _LocationProviderImpl::StartLocationUpdates(LocationUpdateType updateType, int interval, double distance)
547 result r = E_SUCCESS;
548 const int CHECKING_INTERVAL = 10;
550 if (updateType == _LOCATION_UPDATE_TYPE_INTERVAL)
552 __updateInterval = interval;
554 else if (updateType == _LOCATION_UPDATE_TYPE_DISTANCE)
556 __updateInterval = CHECKING_INTERVAL;
557 __distanceThreshold = distance;
560 __locationUpdateType = updateType;
562 if (__awakeEnabled == true)
564 r = __pLocationManager->StartLocationUpdates(__criteria.GetAccuracy(), __updateInterval, this, __reqId);
565 SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Failed to start the Native location updates.", GetErrorMessage(r));
566 __locationUpdateStatus = LOC_SVC_STATUS_NOT_FIXED;
570 UiApp* pAppInstance = Tizen::App::UiApp::GetInstance();
571 if (pAppInstance == null)
573 __locationUpdateStatus = LOC_SVC_STATUS_PAUSED;
577 AppUiState appUiState = pAppInstance->GetAppUiState();
578 if (appUiState == APP_UI_STATE_FOREGROUND || appUiState == APP_UI_STATE_PARTIAL_BACKGROUND)
580 r = __pLocationManager->StartLocationUpdates(__criteria.GetAccuracy(), __updateInterval, this, __reqId);
581 SysTryCatch(NID_LOC, r == E_SUCCESS, , r, "[%s] Failed to start the location updates. Propagating.", GetErrorMessage(r));
582 __locationUpdateStatus = LOC_SVC_STATUS_NOT_FIXED;
586 __locationUpdateStatus = LOC_SVC_STATUS_PAUSED;
591 SysLog(NID_LOC, "Update type is (%x). The request Id is (%ld) and the update status is (%x).", __locationUpdateType, __reqId, __locationUpdateStatus);
592 NotifyServiceStatus(_LOC_PRV_EVENT_SEND_LOC_SVC_CB, __locationUpdateStatus);
597 __locationUpdateType = _LOCATION_UPDATE_TYPE_NONE;
602 _LocationProviderImpl::CheckDistanceThreshold(const Location& oldPosition, const Location& newPosition)
604 double displacement = 0.0;
605 const Coordinates coordOld = oldPosition.GetCoordinates();
606 const Coordinates coordNew = newPosition.GetCoordinates();
608 if (__firstLocationUpdate)
610 SysLog(NID_LOC, "First location update. So send true.");
611 __firstLocationUpdate = false;
615 displacement = coordOld.GetDistanceTo(coordNew);
616 SysLog(NID_LOC, "Displacement is (%lf)", displacement);
617 return ((displacement > __distanceThreshold) ? true : false);
621 _LocationProviderImpl::ResetLocationUpdates(void)
623 __firstLocationUpdate = true;
625 __lastLocationAccuracy = LOC_ACCURACY_INVALID;
626 __locationUpdateType = _LOCATION_UPDATE_TYPE_NONE;
627 __locationUpdateStatus = LOC_SVC_STATUS_IDLE;
628 __updateInterval = 0;
629 __distanceThreshold = 0.0;
633 _LocationProviderImpl::FireImpl(Tizen::Base::Runtime::IEventListener& listener, const Tizen::Base::Runtime::IEventArg& arg)
635 _ILocProviderEventListener* pLocProviderEventListener = dynamic_cast< _ILocProviderEventListener* >(&listener);
636 SysTryReturnVoidResult(NID_LOC, pLocProviderEventListener, E_SYSTEM, "[E_INVALID_ARG] The listener is null.");
638 IEventArg* pArg = const_cast< IEventArg* >(&arg);
639 _LocProviderEventArg* pEventArg = dynamic_cast< _LocProviderEventArg* >(pArg);
640 SysTryReturnVoidResult(NID_LOC, pEventArg, E_SYSTEM, "[E_INVALID_ARG] Event argument is null.");
642 _LocProviderEventType eventType = pEventArg->GetEventType();
645 case _LOC_PRV_EVENT_SEND_LOC:
646 pLocProviderEventListener->OnLocationEventReceivedN(pEventArg->GetRequestId(), *pEventArg->GetLocationN());
649 case _LOC_PRV_EVENT_SEND_LOC_SVC_CB:
650 pLocProviderEventListener->OnLocationUpdateStatusChanged(pEventArg->GetLocServiceStatus());
653 case _LOC_PRV_EVENT_SEND_MONITOR_SVC_CB:
654 pLocProviderEventListener->OnRegionMonitoringStatusChanged(pEventArg->GetLocServiceStatus());
660 _LocationProviderImpl::HandleLocationUpdate(Tizen::Locations::Location& location, bool isNew)
662 LocationServiceStatus newLocationUpdateStatus = __locationUpdateStatus;
666 if (__locationUpdateType != _LOCATION_UPDATE_TYPE_NONE && __locationUpdateStatus != LOC_SVC_STATUS_PAUSED)
668 newLocationUpdateStatus = LOC_SVC_STATUS_RUNNING;
671 else if (_LocationImpl::GetInstance(location)->IsDenied())
673 SysLog(NID_LOC, "User consent not available.");
674 if (__locationUpdateType != _LOCATION_UPDATE_TYPE_NONE && __locationUpdateStatus != LOC_SVC_STATUS_PAUSED)
676 newLocationUpdateStatus = LOC_SVC_STATUS_DENIED;
681 SysLog(NID_LOC, "Invalid Location Update.");
682 if (__locationUpdateType != _LOCATION_UPDATE_TYPE_NONE && __locationUpdateStatus != LOC_SVC_STATUS_PAUSED)
684 newLocationUpdateStatus = LOC_SVC_STATUS_NOT_FIXED;
688 if (newLocationUpdateStatus != __locationUpdateStatus)
690 SysLog(NID_LOC, "Location Update Satus changed to (%x). Notify the status.", newLocationUpdateStatus);
691 __locationUpdateStatus = newLocationUpdateStatus;
692 __pLocationListener->OnLocationUpdateStatusChanged(__locationUpdateStatus);
695 if (newLocationUpdateStatus == LOC_SVC_STATUS_RUNNING)
697 if (__locationUpdateType == _LOCATION_UPDATE_TYPE_DISTANCE)
699 if (CheckDistanceThreshold(*__pLastLocation.get(), location) == true)
701 SysLog(NID_LOC, "Location displacement exceeds the distance threshold (%lf). Notify the location.", __distanceThreshold);
702 __pLocationListener->OnLocationUpdated(location);
703 *__pLastLocation.get() = location;
706 else if (__locationUpdateType == _LOCATION_UPDATE_TYPE_INTERVAL)
708 SysLog(NID_LOC, "Location time interval expired. Notify the location.");
709 __pLocationListener->OnLocationUpdated(location);
710 *__pLastLocation.get() = location;
716 _LocationProviderImpl::HandleRegionMonitoring(Tizen::Locations::Location& location, bool isNew)
718 LocationServiceStatus newRegionMonitorStatus = __regionMonitorStatus;
722 newRegionMonitorStatus = LOC_SVC_STATUS_RUNNING;
724 else if (_LocationImpl::GetInstance(location)->IsDenied())
726 newRegionMonitorStatus = LOC_SVC_STATUS_DENIED;
730 newRegionMonitorStatus = LOC_SVC_STATUS_NOT_FIXED;
733 if (newRegionMonitorStatus != __regionMonitorStatus)
735 SysLog(NID_LOC, "Region Monitoring Satus changed to (%x). Notify the status.", newRegionMonitorStatus);
736 __regionMonitorStatus = newRegionMonitorStatus;
737 __pLocationListener->OnRegionMonitoringStatusChanged(__regionMonitorStatus);
740 if (newRegionMonitorStatus == LOC_SVC_STATUS_RUNNING)
742 NotifyRegionCrossedStatus(location);
743 *__pLastLocation.get() = location;
748 _LocationProviderImpl::NotifyRegionCrossedStatus(const Tizen::Locations::Location& location)
750 int count = __pRegionList->GetCount();
752 SysLog(NID_LOC, "Number of regions currently monitored is (%d)", count);
754 for (int i = 0; i < count; i++)
756 _RegionInfo* pRegionInfo = static_cast< _RegionInfo* >(__pRegionList->GetAt(i));
760 Coordinates regionCoordinate = pRegionInfo->GetCoordinate();
761 _RegionState currentState = REGION_STATE_UNKNOWN;
762 _RegionState previousState = pRegionInfo->GetPreviousValidState();
763 bool notifyStateChange = false;
765 currentState = GetRegionCurrentState(*pRegionInfo, location);
766 SysLog(NID_LOC, "Current Region state is (%d) and Previous Region state is (%d)", currentState, previousState);
768 if (currentState != REGION_STATE_UNKNOWN && previousState != currentState)
770 notifyStateChange = true;
771 pRegionInfo->SetValidPreviousState(currentState);
774 if ((pRegionInfo->GetRegionState() == REGION_STATE_INSIDE || pRegionInfo->GetRegionState() == REGION_STATE_UNKNOWN) && currentState == REGION_STATE_OUTSIDE)
776 if (notifyStateChange)
778 SysLog(NID_LOC, "Notify the boundary crossed event as previous valid region state is INSIDE and current state is OUTSIDE.");
779 __pLocationListener->OnRegionLeft(pRegionInfo->GetRegionId());
782 else if ((pRegionInfo->GetRegionState() == REGION_STATE_OUTSIDE || pRegionInfo->GetRegionState() == REGION_STATE_UNKNOWN) && currentState == REGION_STATE_INSIDE)
784 if (notifyStateChange)
786 SysLog(NID_LOC, "Notify the boundary crossed event as previous valid region state is OUTSIDE and current state is INSIDE.");
787 __pLocationListener->OnRegionEntered(pRegionInfo->GetRegionId());
790 pRegionInfo->SetRegionState(currentState);
796 _LocationProviderImpl::GetRegionCurrentState(const _RegionInfo& region, const Location& location)
798 TryReturn(location.GetHorizontalAccuracy() >= 0.0, REGION_STATE_UNKNOWN, "Location received with invalid accuracy");
800 SysLog(NID_LOC, "[RegionID %d] Region Information is (Center latitude: %lf, Center longitude: %lf, Region radius:%lf", region.GetRegionId(), region.GetCoordinate().GetLatitude(),
801 region.GetCoordinate().GetLongitude(), region.GetRadius());
802 SysLog(NID_LOC, "[RegionID %d] Location Information is (Latitude: %lf, Longitude: %lf, Horizontal accuracy:%lf", region.GetRegionId(), location.GetCoordinates().GetLatitude(),
803 location.GetCoordinates().GetLongitude(), location.GetHorizontalAccuracy());
805 _RegionState regionState = REGION_STATE_UNKNOWN;
807 double distanceBtwCenters = region.GetCoordinate().GetDistanceTo(location.GetCoordinates());
808 double regionRadius = region.GetRadius();
809 double locationRadius = location.GetHorizontalAccuracy();
811 SysLog(NID_LOC, "[RegionID %d] The distance between centers is (%lf)", region.GetRegionId(), distanceBtwCenters);
813 if (distanceBtwCenters >= (regionRadius + locationRadius))
815 regionState = REGION_STATE_OUTSIDE;
817 else if (distanceBtwCenters < regionRadius && Double::Compare(locationRadius, 0.0) == 0)
819 SysLog(NID_LOC, "[RegionID %d] Location Radius is 0 and distance < regionRadius", region.GetRegionId());
820 regionState = REGION_STATE_INSIDE;
824 double radiusThreshold = (1 / Math::Sqrt(2)) * locationRadius;
826 if (regionRadius < radiusThreshold)
828 SysLog(NID_LOC, "[RegionID %d] Region circle is less than 50 percent area of the location circle.", region.GetRegionId());
829 regionState = (distanceBtwCenters >= locationRadius) ? REGION_STATE_OUTSIDE : REGION_STATE_UNKNOWN;
835 double overlapRegion = _MathUtils::CalculateOverlapRegion(region, location);
836 double upperThreshold = 0;
837 double lowerThreshold = 0;
838 double occupancy = 0;
840 SysLog(NID_LOC, "[RegionID %d] OverlapRegion is (%lf)", region.GetRegionId(), overlapRegion);
842 if (regionRadius >= locationRadius)
844 // Calculate occupancy % with the location circle
845 SysLog(NID_LOC, "[RegionID %d] Region radius is bigger.", region.GetRegionId());
846 occupancy = (overlapRegion / (Math::GetPi() * locationRadius * locationRadius)) * 100;
851 else if (regionRadius >= radiusThreshold)
853 SysLog(NID_LOC, "[RegionID %d] The ratio of Region radius to location radius is between 0.707 and 1.", region.GetRegionId());
854 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)
856 SysLog(NID_LOC, "[RegionID %d] Threshold value is %lf.", region.GetRegionId(), thresholdValue);
858 occupancy = (overlapRegion / (Math::GetPi() * locationRadius * locationRadius)) * 100;
860 upperThreshold = 50 + thresholdValue;
861 lowerThreshold = 50 - thresholdValue;
864 // Decide the state with as per the inner and outer thresholds
865 SysLog(NID_LOC, "[RegionID %d] Occupancy is (%lf), Upper threshold is (%lf) and lower threshold is (%lf).", region.GetRegionId(), occupancy, upperThreshold, lowerThreshold);
866 regionState = (occupancy >= upperThreshold) ? REGION_STATE_INSIDE : ((occupancy <= lowerThreshold) ? REGION_STATE_OUTSIDE : REGION_STATE_UNKNOWN);
870 SysLog(NID_LOC, "[RegionID %d] Returning region state as (%d).", region.GetRegionId(), regionState);
875 _LocationProviderImpl::NotifyServiceStatus(_LocProviderEventType eventType, LocationServiceStatus svcStatus)
877 std::unique_ptr< _LocProviderEventArg > pLocProviderEventArg(new (std::nothrow) _LocProviderEventArg());
878 if (pLocProviderEventArg)
880 pLocProviderEventArg->SetEventType(eventType);
881 pLocProviderEventArg->SetLocServiceStatus(svcStatus);
883 result r = _Event::FireAsync(*pLocProviderEventArg.get());
884 SysTryReturnVoidResult(NID_LOC, r == E_SUCCESS, r, "[%s] Failed to fire the event.", GetErrorMessage(r));
886 pLocProviderEventArg.release();
893 _LocationProviderImpl::GetUserPrivilege(void)
895 _LocationManager* pLocMgr = _LocationManager::GetInstance();
896 SysTryReturn(NID_LOC, pLocMgr, false, E_SYSTEM, "[E_SYSTEM] Failed to get the location manager instance.");
898 bool appSettingEnabled = pLocMgr->IsAppEnabled();
899 if (appSettingEnabled == false)
904 bool hasPrivilege = false;
905 result gps = E_SUCCESS;
906 result wps = E_SUCCESS;
908 bool gpsEnabled = true;
909 bool wpsEnabled = true;
911 gps = _SettingInfoImpl::GetValue(L"http://tizen.org/setting/location.gps", gpsEnabled);
912 wps = _SettingInfoImpl::GetValue(L"http://tizen.org/setting/location.wps", wpsEnabled);
914 hasPrivilege = gpsEnabled | wpsEnabled;
916 if (gps != E_SUCCESS || wps != E_SUCCESS || hasPrivilege == false)