diff options
author | Nandan SR <nandan.sr@samsung.com> | 2013-06-07 12:34:17 +0900 |
---|---|---|
committer | Nandan SR <nandan.sr@samsung.com> | 2013-06-07 12:34:17 +0900 |
commit | d0af1bf8139af86c51cb7ab84b18e1448e8d0bf8 (patch) | |
tree | 9f956b4d39ebffd002ab80e4a5c936920c7c27d9 | |
parent | e2edf7ea7d25ec12d306f2d5362a7af6f1da743e (diff) | |
download | locations-d0af1bf8139af86c51cb7ab84b18e1448e8d0bf8.tar.gz locations-d0af1bf8139af86c51cb7ab84b18e1448e8d0bf8.tar.bz2 locations-d0af1bf8139af86c51cb7ab84b18e1448e8d0bf8.zip |
Implementation of new location manager.
Change-Id: I98a81dc40192362b688ea8b5e400c37feb50e5d7
Signed-off-by: Nandan SR <nandan.sr@samsung.com>
-rw-r--r-- | src/FLoc_Config.h | 1 | ||||
-rw-r--r-- | src/FLoc_ILocProviderEventListener.h | 2 | ||||
-rw-r--r-- | src/FLoc_ILocationManagerListener.h | 2 | ||||
-rw-r--r-- | src/FLoc_LocationManager.cpp | 1353 | ||||
-rw-r--r-- | src/FLoc_LocationManager.h | 188 | ||||
-rw-r--r-- | src/FLoc_LocationProviderImpl.cpp | 82 | ||||
-rw-r--r-- | src/FLoc_LocationProviderImpl.h | 4 | ||||
-rw-r--r-- | src/FLoc_SyncLocationRequestInfo.h | 1 |
8 files changed, 1186 insertions, 447 deletions
diff --git a/src/FLoc_Config.h b/src/FLoc_Config.h index 46c2b7e..00a5adb 100644 --- a/src/FLoc_Config.h +++ b/src/FLoc_Config.h @@ -35,6 +35,7 @@ const int DEFAULT_AVG_SPEED = 20; //Take average car speed as 72 km/hr = 20 m/s const int DEFAULT_REGION_MONITORING_CYCLE_INTERVAL = 5; const int DEFAULT_DISTANCE_CHECKING_INTERVAL = 10; const int DEFAULT_THRESHOLD_LOC_VALIDITY_TIME_OUT = 3; +const int MAX_TIMER_VALUE_DURING_WPS_POSITIONING = 640; }} // Tizen::Locations #endif //_FLOC_INTERNAL_CONFIG_H_ diff --git a/src/FLoc_ILocProviderEventListener.h b/src/FLoc_ILocProviderEventListener.h index b090936..e153b1f 100644 --- a/src/FLoc_ILocProviderEventListener.h +++ b/src/FLoc_ILocProviderEventListener.h @@ -80,7 +80,7 @@ public: /** * Called when the alarm expiry event is fired from the location provider impl class to break the context. @n * - * @since 2.0 + * @since 2.1.1 */ virtual void OnAlarmExpiredEventReceived(void) = 0; diff --git a/src/FLoc_ILocationManagerListener.h b/src/FLoc_ILocationManagerListener.h index 85f2256..bf5f2d7 100644 --- a/src/FLoc_ILocationManagerListener.h +++ b/src/FLoc_ILocationManagerListener.h @@ -62,7 +62,7 @@ public: /** * Called when the alarm requested by the location provider has expired. @n * - * @since 2.0 + * @since 2.1.1 */ virtual void OnAlarmExpired(void) = 0; }; //_ILocationManagerListener diff --git a/src/FLoc_LocationManager.cpp b/src/FLoc_LocationManager.cpp index cf95366..c85d4d1 100644 --- a/src/FLoc_LocationManager.cpp +++ b/src/FLoc_LocationManager.cpp @@ -34,9 +34,11 @@ #include <FBaseRtTimer.h> #include <FBaseRtMonitor.h> #include <FBaseSysLog.h> +#include <FBaseUtilMath.h> #include <FLocCoordinates.h> -#include <FSysSystemTime.h> +#include <FSysSettingInfo.h> #include <FSys_PowerManagerImpl.h> +#include <FSys_SettingInfoImpl.h> #include "FLoc_AlarmRequestInfo.h" #include "FLoc_Config.h" #include "FLoc_LocationImpl.h" @@ -45,27 +47,30 @@ #include "FLoc_LocationRequestInfo.h" #include "FLoc_SyncLocationRequestInfo.h" +using namespace std; using namespace Tizen::Base; using namespace Tizen::Base::Collection; using namespace Tizen::Base::Runtime; using namespace Tizen::Base::Utility; using namespace Tizen::System; -using namespace std; namespace Tizen { namespace Locations { + _LocationManager* _LocationManager::__pUniqueInstance = null; _LocationManager::_LocationManager(void) : Tizen::Base::Runtime::EventDrivenThread() - , __locMethodRequested(LOC_METHOD_REQUESTED_NONE) - , __locationMgrState(LOC_MGR_STATE_IDLE) + , __gpsEnabled(false) + , __wpsEnabled(false) , __minRequestedAccuracy(LOC_ACCURACY_INVALID) , __timerInterval(0) , __timerTicks(0) , __pLocRequestInfoList(null) , __pSyncLocRequestInfoList(null) - , __pLocUpdateTimer(null) + , __pAlarmRequestInfoList(null) + , __pLocCallbackTimer(null) + , __pLocCheckTimer(null) , __pInitMonitor(null) { } @@ -81,9 +86,8 @@ _LocationManager::StartLocationUpdates(LocationAccuracy accuracy, int interval, static RequestId nextLocRequestId = 1; const int ARRAY_LIST_CAPACITY = 1; - std::unique_ptr< Tizen::Base::Collection::ArrayList, Tizen::Base::Collection::AllElementsDeleter > pArgList(new (std::nothrow) ArrayList()); + std::unique_ptr< ArrayList, AllElementsDeleter > pArgList(new (std::nothrow) ArrayList()); SysTryReturn(NID_LOC, pArgList, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); - std::unique_ptr< _LocationRequestInfo > pLocRequestInfo(new (std::nothrow) _LocationRequestInfo(accuracy, interval, pListener, nextLocRequestId)); SysTryReturn(NID_LOC, pLocRequestInfo, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); @@ -91,18 +95,16 @@ _LocationManager::StartLocationUpdates(LocationAccuracy accuracy, int interval, SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Array Construct failed. Propogating.", GetErrorMessage(r)); r = pArgList->Add(*pLocRequestInfo); SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Arraylist addition of an object failed. Propogating", GetErrorMessage(r)); - pLocRequestInfo.release(); r = SendUserEvent(REQ_ID_START_LOC_UPDATES, pArgList.get()); SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Failed to send the user event. Propagating.", GetErrorMessage(r)); + pArgList.release(); reqId = nextLocRequestId; nextLocRequestId++; - - pArgList.release(); - SysLog(NID_LOC, "Request ID (%ld) is assigned for the location request with accuracy (%d) and interval (%d).", reqId, accuracy, interval); + return E_SUCCESS; } @@ -112,9 +114,8 @@ _LocationManager::StopLocationUpdates(RequestId reqId) SysLog(NID_LOC, "Location update stop requested for request ID (%d).", reqId); const int ARRAY_LIST_CAPACITY = 1; - std::unique_ptr< Tizen::Base::Collection::ArrayList, Tizen::Base::Collection::AllElementsDeleter > pArgList(new (std::nothrow) ArrayList()); + std::unique_ptr< ArrayList, AllElementsDeleter > pArgList(new (std::nothrow) ArrayList()); SysTryReturn(NID_LOC, pArgList, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); - std::unique_ptr< Integer > pReqId(new (std::nothrow) Integer(static_cast< int >(reqId))); SysTryReturn(NID_LOC, pReqId, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); @@ -122,13 +123,12 @@ _LocationManager::StopLocationUpdates(RequestId reqId) SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Array Construct failed. Propogating.", GetErrorMessage(r)); r = pArgList->Add(*pReqId); SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Arraylist addition of an object failed. Propogating.", GetErrorMessage(r)); - pReqId.release(); r = SendUserEvent(REQ_ID_STOP_LOC_UPDATES, pArgList.get()); SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Failed to send the user event. Propagating.", GetErrorMessage(r)); - pArgList.release(); + return E_SUCCESS; } @@ -138,7 +138,7 @@ _LocationManager::ChangeUpdateInterval(RequestId reqId, int interval) SysLog(NID_LOC, "Interval update requested for request ID (%d).", reqId); const int ARRAY_LIST_CAPACITY = 2; - std::unique_ptr< Tizen::Base::Collection::ArrayList, Tizen::Base::Collection::AllElementsDeleter > pArgList(new (std::nothrow) ArrayList()); + std::unique_ptr< ArrayList, AllElementsDeleter > pArgList(new (std::nothrow) ArrayList()); SysTryReturn(NID_LOC, pArgList, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); result r = pArgList->Construct(ARRAY_LIST_CAPACITY); SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Array Construct failed. Propogating.", GetErrorMessage(r)); @@ -148,7 +148,6 @@ _LocationManager::ChangeUpdateInterval(RequestId reqId, int interval) r = pArgList->Add(*pReqId); SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Arraylist addition of an object failed. Propogating.", GetErrorMessage(r)); - pReqId.release(); std::unique_ptr< Integer > pInterval(new (std::nothrow) Integer(interval)); @@ -156,13 +155,12 @@ _LocationManager::ChangeUpdateInterval(RequestId reqId, int interval) r = pArgList->Add(*pInterval); SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Arraylist addition of an object failed. Propogating.", GetErrorMessage(r)); - pInterval.release(); r = SendUserEvent(REQ_ID_UPDATE_INTERVAL, pArgList.get()); SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Failed to send the user event. Propagating.", GetErrorMessage(r)); - pArgList.release(); + return E_SUCCESS; } @@ -173,13 +171,13 @@ _LocationManager::RegisterLocationMonitor(_LocationMonitor* pLocationMonitor) const int ARRAY_LIST_CAPACITY = 1; Location location = GetLastKnownLocation(); - Tizen::Base::DateTime lastLocTime = location.GetTimestamp(); + DateTime lastLocTime = location.GetTimestamp(); result r = StartLocationUpdates(pLocationMonitor->GetAccuracy(), 1, null, reqId); SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Error to request location updates.", GetErrorMessage(r)); std::unique_ptr< _SyncLocationRequestInfo > pSyncLocationRequestInfo(new (std::nothrow) _SyncLocationRequestInfo(pLocationMonitor, reqId, lastLocTime)); - std::unique_ptr< Tizen::Base::Collection::ArrayList, Tizen::Base::Collection::AllElementsDeleter > pArgList(new (std::nothrow) ArrayList()); + std::unique_ptr< ArrayList, AllElementsDeleter > pArgList(new (std::nothrow) ArrayList()); SysTryCatch(NID_LOC, pSyncLocationRequestInfo != null && pArgList != null, , E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); @@ -192,8 +190,8 @@ _LocationManager::RegisterLocationMonitor(_LocationMonitor* pLocationMonitor) r = SendUserEvent(REQ_ID_SYNC_LOC_RETRIEVAL, pArgList.get()); SysTryCatch(NID_LOC, r == E_SUCCESS, , r, "[%s] Failed to send the user event. Propagating.", GetErrorMessage(r)); - pArgList.release(); + return E_SUCCESS; CATCH: @@ -206,9 +204,8 @@ _LocationManager::RequestStartAlarm(int interval, _ILocationManagerListener* pLi { const int ARRAY_LIST_CAPACITY = 1; - std::unique_ptr< Tizen::Base::Collection::ArrayList, Tizen::Base::Collection::AllElementsDeleter > pArgList(new (std::nothrow) ArrayList()); + std::unique_ptr< ArrayList, AllElementsDeleter > pArgList(new (std::nothrow) ArrayList()); SysTryReturn(NID_LOC, pArgList, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); - std::unique_ptr< _AlarmRequestInfo > pAlarmRequestInfo(new (std::nothrow) _AlarmRequestInfo(interval, pListener, reqId)); SysTryReturn(NID_LOC, pAlarmRequestInfo, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); @@ -216,15 +213,13 @@ _LocationManager::RequestStartAlarm(int interval, _ILocationManagerListener* pLi SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Array Construct failed. Propogating.", GetErrorMessage(r)); r = pArgList->Add(*pAlarmRequestInfo.get()); SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Arraylist addition of an object failed. Propogating", GetErrorMessage(r)); - pAlarmRequestInfo.release(); r = SendUserEvent(REQ_ID_START_ALARM, pArgList.get()); SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Failed to send the user event. Propagating.", GetErrorMessage(r)); - pArgList.release(); + SysLog(NID_LOC, "Successfully requested for alarm addition."); - SysLog(NID_LOC, "Success to add the alarm."); return E_SUCCESS; } @@ -234,9 +229,8 @@ _LocationManager::RequestStopAlarm(RequestId reqId) SysLog(NID_LOC, "Alarm stop requested for request ID (%d).", reqId); const int ARRAY_LIST_CAPACITY = 1; - std::unique_ptr< Tizen::Base::Collection::ArrayList, Tizen::Base::Collection::AllElementsDeleter > pArgList(new (std::nothrow) ArrayList()); + std::unique_ptr< ArrayList, AllElementsDeleter > pArgList(new (std::nothrow) ArrayList()); SysTryReturn(NID_LOC, pArgList, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); - std::unique_ptr< Integer > pReqId(new (std::nothrow) Integer(static_cast< int >(reqId))); SysTryReturn(NID_LOC, pReqId, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); @@ -244,13 +238,12 @@ _LocationManager::RequestStopAlarm(RequestId reqId) SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Array Construct failed. Propogating.", GetErrorMessage(r)); r = pArgList->Add(*pReqId); SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Arraylist addition of an object failed. Propogating.", GetErrorMessage(r)); - pReqId.release(); r = SendUserEvent(REQ_ID_STOP_ALARM, pArgList.get()); SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Failed to send the user event. Propagating.", GetErrorMessage(r)); - pArgList.release(); + return E_SUCCESS; } @@ -262,7 +255,7 @@ _LocationManager::GetLastKnownLocation(void) result r = synchronizer.Construct(); SysTryReturn(NID_LOC, r == E_SUCCESS, location, r, "[%s] Propogating.", GetErrorMessage(r)); - std::unique_ptr< Tizen::Base::Collection::ArrayList > pArgList(new (std::nothrow) ArrayList()); + std::unique_ptr< ArrayList > pArgList(new (std::nothrow) ArrayList()); SysTryReturn(NID_LOC, pArgList, location, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); r = pArgList->Construct(); SysTryReturn(NID_LOC, r == E_SUCCESS, location, r, "[%s] Propogating.", GetErrorMessage(r)); @@ -357,9 +350,15 @@ _LocationManager::AddToLocRequestInfoList(const _LocationRequestInfo* pLocReques result r = _PowerManagerImpl::PowerControl(1, 1); SysTryReturnVoidResult(NID_LOC, r == E_SUCCESS, r, "[%s] Failed to keep the CPU in awake state.", GetErrorMessage(r)); } - SysLog(NID_LOC, "Total count of request info is (%d).", __pLocRequestInfoList->GetCount()); - RestartLocationUpdates(); - RestartUpdateTimer(); + const int FIRST_REQUEST = 1; + int count = __pLocRequestInfoList->GetCount(); + SysLog(NID_LOC, "Total count of request info is (%d).", count); + if (count == FIRST_REQUEST) + { + InitiateLocationRequest(); + } + UpdateMinimunAccuracy(); + RestartCallbackTimer(); } void @@ -382,15 +381,14 @@ _LocationManager::RemoveFromLocRequestInfoList(RequestId reqId) { _PowerManagerImpl::PowerControl(1, 0); - __pLocUpdateTimer->Cancel(); - location_manager_stop(__gpsHandler.handle); - location_manager_stop(__wpsHandler.handle); Reset(); + location_manager_stop(__locMgrStatus.gpsHandler.handle); + location_manager_stop(__locMgrStatus.wpsHandler.handle); } else { - RestartLocationUpdates(); - RestartUpdateTimer(); + UpdateMinimunAccuracy(); + RestartCallbackTimer(); } } @@ -402,7 +400,6 @@ _LocationManager::AddToSyncLocationRequestInfoList(_SyncLocationRequestInfo& syn r = __pSyncLocRequestInfoList->Add(syncLocRequestInfo); SysTryCatch(NID_LOC, r == E_SUCCESS, , r, "[%s] Failed to add the sync request into the list.", GetErrorMessage(r)); - return; CATCH: @@ -422,16 +419,16 @@ void _LocationManager::AddToAlarmRequestInfoList(_AlarmRequestInfo& alarmRequestInfo) { alarm_id_t alarmId; + int res = alarmmgr_add_alarm_withcb(ALARM_TYPE_DEFAULT, alarmRequestInfo.GetInterval(), 0, AlarmExpiryCallback, this, &alarmId); SysTryReturnVoidResult(NID_LOC, res == ALARMMGR_RESULT_SUCCESS, E_SYSTEM, "Failed to add the alarm for next cycle."); - - SysLog(NID_LOC, "The alarm ID (%d) will be set to the request.", alarmId); alarmRequestInfo.SetAlarmId(alarmId); + SysLog(NID_LOC, "The alarm ID (%d) is set to the alarm request.", alarmId); std::unique_ptr< _AlarmRequestInfo > pNewAlarmRequestInfo(new (std::nothrow) _AlarmRequestInfo(alarmRequestInfo)); SysTryReturnVoidResult(NID_LOC, pNewAlarmRequestInfo, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); result r = __pAlarmRequestInfoList->Add(*pNewAlarmRequestInfo.get()); - SysTryReturnVoidResult(NID_LOC, r == E_SUCCESS, E_SYSTEM, "Failed to add the alarm request into list."); + SysTryReturnVoidResult(NID_LOC, r == E_SUCCESS, E_SYSTEM, "[E_SYSTEM] Failed to add the alarm request into list."); pNewAlarmRequestInfo.release(); return; @@ -442,7 +439,6 @@ _LocationManager::RemoveFromAlarmRequestInfoList(RequestId reqId) { int count = __pAlarmRequestInfoList->GetCount(); SysLog(NID_LOC, "Total count of Alarm Request pending is (%d).", count); - for (int i = 0; i < count; i++) { const _AlarmRequestInfo* pAlarmRequestInfo = static_cast< const _AlarmRequestInfo* >(__pAlarmRequestInfoList->GetAt(i)); @@ -455,82 +451,84 @@ _LocationManager::RemoveFromAlarmRequestInfoList(RequestId reqId) break; } } - return; } void -_LocationManager::RestartLocationUpdates(void) +_LocationManager::UpdateMinimunAccuracy(void) { int count = __pLocRequestInfoList->GetCount(); - int result = 0; - bool isAccuracyChanged = false; - for (int i = 0; i < count; i++) { const _LocationRequestInfo* pLocRequestInfo = static_cast< const _LocationRequestInfo* >(__pLocRequestInfoList->GetAt(i)); if (__minRequestedAccuracy > pLocRequestInfo->GetAccuracy() || __minRequestedAccuracy == LOC_ACCURACY_INVALID) { __minRequestedAccuracy = pLocRequestInfo->GetAccuracy(); - isAccuracyChanged = true; } } - if (!isAccuracyChanged) +} + +void +_LocationManager::InitiateLocationRequest(void) +{ + if (__locMgrStatus.locMgrState != LOC_MGR_STATE_IDLE) { + SysLog(NID_LOC, "Location manager already running."); return; } - SysLog(NID_LOC, "Location updates are restarted and new minimum requested Accuracy is (%d).", __minRequestedAccuracy); - switch (__locMethodRequested) - { - case LOC_METHOD_REQUESTED_NONE: - { - SysLog(NID_LOC, "None of the methods running. Start all"); + SysLog(NID_LOC, "None of the methods running. Start all"); + bool gpsEnabled = false; + bool wpsEnabled = false; + int resultGps = -1; + int resultWps = -1; + const int LOC_CHECK_TIMER_VALUE = 1000; - result = location_manager_start(__gpsHandler.handle); - SysTryLog(NID_LOC, result == 0, "Failed to start the location updates for GPS."); + result gps = _SettingInfoImpl::GetValue(L"http://tizen.org/setting/location.gps", gpsEnabled); + result wps = _SettingInfoImpl::GetValue(L"http://tizen.org/setting/location.wps", wpsEnabled); + __gpsEnabled = gpsEnabled; + __wpsEnabled = wpsEnabled; - result = location_manager_start(__wpsHandler.handle); - SysTryLog(NID_LOC, result == 0, "Failed to start the location updates for WPS."); + if (gps == E_SUCCESS && __gpsEnabled) + { + resultGps = location_manager_start(__locMgrStatus.gpsHandler.handle); + SysTryLog(NID_LOC, resultGps == 0, "Failed to start the core GPS location provider with result (%d).", resultGps); } - break; - - case LOC_METHOD_REQUESTED_GPS: + if (wps == E_SUCCESS && __wpsEnabled) { - SysLog(NID_LOC, "GPS Running. Start WPS."); - - result = location_manager_start(__wpsHandler.handle); - SysTryLog(NID_LOC, result == 0, "Failed to start the location updates for WPS."); + resultWps = location_manager_start(__locMgrStatus.wpsHandler.handle); + SysTryLog(NID_LOC, resultWps == 0, "Failed to start the core WPS location provider with result (%d).", resultWps); } - break; - case LOC_METHOD_REQUESTED_WPS: + if (resultGps == 0 && resultWps == 0) { - SysLog(NID_LOC, "WPS Running. Start GPS."); - - result = location_manager_start(__gpsHandler.handle); - SysTryLog(NID_LOC, result == 0, "Failed to start the location updates for GPS."); + __locMgrStatus.locMgrState = LOC_MGR_STATE_BOTH_GPS_WPS; } - break; - - case LOC_METHOD_REQUESTED_ALL: + else if (resultGps == 0 && resultWps != 0) { - SysLog(NID_LOC, "All the providers are already started."); + __locMgrStatus.locMgrState = LOC_MGR_STATE_GPS_ONLY; } - break; + else if (resultGps != 0 && resultWps == 0) + { + __locMgrStatus.locMgrState = LOC_MGR_STATE_WPS_ONLY; } - - __locationMgrState = LOC_MGR_STATE_FAST_SENSING; - __locMethodRequested = LOC_METHOD_REQUESTED_ALL; + else + { + SysLog(NID_LOC, "Failed to start both the location providers."); + __locMgrStatus.locMgrState = LOC_MGR_STATE_PASSIVE_IDLE; + return; + } + __locMgrStatus.locMgrSubState = LM_SS_NO_FIX; + __pLocCheckTimer->Start(LOC_CHECK_TIMER_VALUE); } void -_LocationManager::RestartUpdateTimer(void) +_LocationManager::RestartCallbackTimer(void) { int gcd = 1; int count = __pLocRequestInfoList->GetCount(); - __pLocUpdateTimer->Cancel(); + __pLocCallbackTimer->Cancel(); if (count > 0) { @@ -554,12 +552,9 @@ _LocationManager::RestartUpdateTimer(void) __timerInterval = gcd; __timerTicks = 0; - SysLog(NID_LOC, "Updated Timer interval is (%d).", __timerInterval); - result r = __pLocUpdateTimer->Start(__timerInterval * 1000); - if (IsFailed(r)) - { - SysLog(NID_LOC, "Failed to start the Location update timer."); - } + result r = __pLocCallbackTimer->Start(__timerInterval * 1000); + SysTryReturnVoidResult(NID_LOC, r == E_SUCCESS, r, "[%s] Failed to start the location callback timer.", GetErrorMessage(r)); + SysLog(NID_LOC, "The callback timer interval successfully updated to (%d).", __timerInterval); } void @@ -569,6 +564,7 @@ _LocationManager::HandleSyncRetrievalTimerExpiry(_SyncLocationRequestInfo& syncL DateTime timestamp = DateTime::GetMinValue(); const Location* pBestLoc = FindBestLocation(); + SysTryReturnVoidResult(NID_LOC, pBestLoc != null, E_INVALID_DATA, "[E_INVALID_DATA] Location not available."); SysLog(NID_LOC, "Location(timestamp: %ls, validity: %x, accuracy: %f) is retrieved.", pBestLoc->GetTimestamp().ToString().GetPointer(), pBestLoc->IsValid(), pBestLoc->GetHorizontalAccuracy()); if (pBestLoc->IsValid()) @@ -617,128 +613,11 @@ NOTIFY: RemoveSyncLocRetrievalRequest(syncLocRequestInfo); } -result -_LocationManager::SetLocationInformation(double latitude, double longitude, double altitude, time_t timestamp, location_method_e locMethod, Location* pLocation) -{ - SysSecureLog(NID_LOC, "Location Information is: Latitude (%lf), Longitude (%lf), Altitude (%lf), TimeStamp (%ld), Location method (%d)", latitude, longitude, altitude, timestamp, locMethod); - - int res = -1; - LocationAccuracy requiredAcc; - int rangeValue = 0; - - //Accuracy details. - location_accuracy_level_e accLevel = LOCATIONS_ACCURACY_NONE; - double horAcc = Tizen::Locations::NaN; - double verAcc = Tizen::Locations::NaN; - - //Velocity details. - double climb = Tizen::Locations::NaN; - double direction = Tizen::Locations::NaN; - double speed = Tizen::Locations::NaN; - time_t time_stamp = 0; - - RequestId requestId; - Location locationData = _LocationImpl::GetLocationInstance(); - _LocationImpl* pLocDataImpl = _LocationImpl::GetInstance(locationData); - - switch (locMethod) - { - case LOCATIONS_METHOD_GPS: - { - res = location_manager_get_accuracy(__gpsHandler.handle, &accLevel, &horAcc, &verAcc); - SysLog(NID_LOC, "Get Accuracy: Result (%d), Horizontal Acc (%lf), Vertical Acc (%lf)", res, horAcc, verAcc); - SysTryReturnResult(NID_LOC, res == 0, E_SYSTEM, "Invalid accuracy values from Native Location Provider."); - - res = location_manager_get_velocity(__gpsHandler.handle, &climb, &direction, &speed, &time_stamp); - SysLog(NID_LOC, "Get Velocity: Result (%d), Climb (%lf), Direction (%lf), Speed (%lf), Time stamp (%ld)", res, climb, direction, speed, time_stamp); - SysTryReturnResult(NID_LOC, res == 0, E_SYSTEM, "Invalid accuracy values from Native Location Provider."); - - pLocDataImpl->SetExtraInfo(L"location_method", L"gps"); - requestId = REQ_ID_SUSTAIN_GPS; - } - break; - - case LOCATIONS_METHOD_WPS: - { - res = location_manager_get_accuracy(__wpsHandler.handle, &accLevel, &horAcc, &verAcc); - SysLog(NID_LOC, "Get Accuracy: Result (%d), Horizontal Acc (%lf), Vertical Acc (%lf)", res, horAcc, verAcc); - SysTryReturnResult(NID_LOC, res == 0, E_SYSTEM, "Invalid accuracy values from Native Location Provider."); - - res = location_manager_get_velocity(__wpsHandler.handle, &climb, &direction, &speed, &time_stamp); - SysTryLog(NID_LOC, res == 0, "Get Velocity: Result (%d), Climb (%lf), Direction (%lf), Speed (%lf), Time stamp (%ld)", res, climb, direction, speed, time_stamp); - - pLocDataImpl->SetExtraInfo(L"location_method", L"network"); - requestId = REQ_ID_SUSTAIN_WPS; - } - break; - - default: - SysTryReturn(NID_LOC, false, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The location method is not valid"); - } - - Coordinates coordinates; - coordinates.Set(latitude, longitude, altitude); - pLocDataImpl->SetCoordinates(coordinates); - - horAcc = ConvertToNativeFormat(horAcc); - pLocDataImpl->SetHorizontalAccuracy(horAcc); - verAcc = ConvertToNativeFormat(verAcc); - pLocDataImpl->SetVerticalAccuracy(verAcc); - pLocDataImpl->SetTimestamp((long long) timestamp * 1000); - direction = ConvertToNativeFormat(direction); - pLocDataImpl->SetCourse(direction); - speed = ConvertToNativeFormat(speed); - pLocDataImpl->SetSpeed(speed); - pLocDataImpl->SetValidity(true); - *pLocation = locationData; - - requiredAcc = __minRequestedAccuracy; - switch (requiredAcc) - { - case LOC_ACCURACY_FINEST: - rangeValue = ACCURACY_FINEST; - break; - - case LOC_ACCURACY_TEN_METERS: - rangeValue = ACCURACY_TEN_MTRS; - break; - - case LOC_ACCURACY_HUNDRED_METERS: - rangeValue = ACCURACY_HUNDRED_MTRS; - break; - - case LOC_ACCURACY_ONE_KILOMETER: - rangeValue = ACCURACY_ONE_KILOMETER; - break; - - case LOC_ACCURACY_ANY: - rangeValue = ACCURACY_ANY; - break; - - case LOC_ACCURACY_INVALID: - // follow through - default: - SysAssertf(false, "The Accuracy value is not defined."); - } - - if (__locationMgrState == LOC_MGR_STATE_FAST_SENSING && (!Double::IsNaN(horAcc) && horAcc <= rangeValue)) - { - SysLog(NID_LOC, "State is LOC_MGR_STATE_FAST_SENSING and accuracy is within range. RequestId is (%d)", requestId); - __locationMgrState = LOC_MGR_STATE_FAST_SENSING_SETTLED; - SendUserEvent(requestId, null); - } - else - { - SysLog(NID_LOC, "State is LOC_MGR_STATE_FAST_SENSING_SETTLED and accuracy is out of range. Restart location updates."); - SendUserEvent(REQ_ID_RESTART_LOC_UPDATES, null); - } - return E_SUCCESS; -} - void _LocationManager::SendLocationCallbacks(void) { const Location* pBestLocation = FindBestLocation(); + SysTryReturnVoidResult(NID_LOC, pBestLocation != null, E_INVALID_DATA, "[E_INVALID_DATA] Location not available."); SysLog(NID_LOC, "Send location(validity: %x) through the callback.", pBestLocation->IsValid()); unique_ptr< Location > pLocation(new (std::nothrow) Location(*pBestLocation)); @@ -758,8 +637,11 @@ _LocationManager::SendLocationCallbacks(void) void _LocationManager::Reset(void) { - __locMethodRequested = LOC_METHOD_REQUESTED_NONE; - __locationMgrState = LOC_MGR_STATE_IDLE; + StopSubStateTimer(); + __pLocCallbackTimer->Cancel(); + __pLocCheckTimer->Cancel(); + __locMgrStatus.locMgrSubState = LM_SS_IDLE; + __locMgrStatus.locMgrState = LOC_MGR_STATE_IDLE; __minRequestedAccuracy = LOC_ACCURACY_INVALID; __timerInterval = 0; __timerTicks = 0; @@ -790,14 +672,14 @@ _LocationManager::GetLastKnownLocation(location_method_e nativeLocMethod) { case LOCATIONS_METHOD_GPS: { - nativeHandle = __gpsHandler.handle; + nativeHandle = __locMgrStatus.gpsHandler.handle; locationMethod = L"gps"; } break; case LOCATIONS_METHOD_WPS: { - nativeHandle = __wpsHandler.handle; + nativeHandle = __locMgrStatus.wpsHandler.handle; locationMethod = L"network"; } break; @@ -822,8 +704,6 @@ _LocationManager::GetLastKnownLocation(location_method_e nativeLocMethod) SysSecureLog(NID_LOC, "Last position(latitude: %lf, longitude: %lf, altitude: %lf, timestamp: %ld", latitude, longitude, altitude, timestampPosition); - altitude = ConvertToNativeFormatAltitude(altitude); - Coordinates coord; coord.Set(latitude, longitude, altitude); pLocationImpl->SetCoordinates(coord); @@ -836,8 +716,8 @@ _LocationManager::GetLastKnownLocation(location_method_e nativeLocMethod) { SysLog(NID_LOC, "Last accuracy(horAcc: %lf, vAcc: %lf, level: %x)", horAcc, verAcc, level); horAcc = ConvertToNativeFormat(horAcc); - pLocationImpl->SetHorizontalAccuracy(horAcc); verAcc = ConvertToNativeFormat(verAcc); + pLocationImpl->SetHorizontalAccuracy(horAcc); pLocationImpl->SetVerticalAccuracy(verAcc); } @@ -848,12 +728,10 @@ _LocationManager::GetLastKnownLocation(location_method_e nativeLocMethod) res = location_manager_get_last_velocity(nativeHandle, &climb, &direction, &speed, ×tampVelocity); if (res == 0) { - SysLog(NID_LOC, "Last velocity(climb: %lf, direction: %lf, speed: %lf, timestamp: %ld)", - climb, direction, speed, timestampVelocity); - + SysLog(NID_LOC, "Last velocity(climb: %lf, direction: %lf, speed: %lf, timestamp: %ld)", climb, direction, speed, timestampVelocity); direction = ConvertToNativeFormat(direction); - pLocationImpl->SetCourse(direction); speed = ConvertToNativeFormat(speed); + pLocationImpl->SetCourse(direction); pLocationImpl->SetSpeed(speed); } @@ -866,7 +744,7 @@ _LocationManager::GetLastKnownLocation(location_method_e nativeLocMethod) res = gps_status_get_last_satellite(nativeHandle, &satUsedCount, &satViewCount, ×tampSatellite); if (res == 0) { - long timeDiff = abs(timestampPosition - timestampSatellite); + long timeDiff = Math::Abs(timestampPosition - timestampSatellite); res = gps_status_foreach_last_satellites_in_view(nativeHandle, SatelliteInfoUpdated, &satInfo); SysLog(NID_LOC, "Last satellite(foreachResult: %d, inUse: %d, inView: %d, timestamp: %ld, timeDiff: %ld)", res, satUsedCount, satViewCount, timestampSatellite, timeDiff); @@ -918,7 +796,7 @@ _LocationManager::GetRecentLocationAvailable(void) } void -_LocationManager::UpdateLocRequestInfoList(RequestId reqId, int interval) +_LocationManager::UpdateLocRequestInterval(RequestId reqId, int interval) { int count = __pLocRequestInfoList->GetCount(); @@ -928,7 +806,7 @@ _LocationManager::UpdateLocRequestInfoList(RequestId reqId, int interval) if (reqId == pLocRequestInfo->GetRequestId()) { pLocRequestInfo->SetInterval(interval); - RestartUpdateTimer(); + RestartCallbackTimer(); break; } } @@ -937,89 +815,94 @@ _LocationManager::UpdateLocRequestInfoList(RequestId reqId, int interval) const Location* _LocationManager::FindBestLocation(void) { - switch (__locMethodRequested) + switch (__locMgrStatus.locMgrState) { - case LOC_METHOD_REQUESTED_GPS: + case LOC_MGR_STATE_GPS_ONLY: { SysLog(NID_LOC, "GPS location provider running."); - return __gpsHandler.pLocation.get(); + return __locMgrStatus.gpsHandler.pLocation.get(); } break; - case LOC_METHOD_REQUESTED_WPS: + case LOC_MGR_STATE_WPS_ONLY: { SysLog(NID_LOC, "WPS location provider running."); - return __wpsHandler.pLocation.get(); + return __locMgrStatus.wpsHandler.pLocation.get(); } break; - case LOC_METHOD_REQUESTED_ALL: + case LOC_MGR_STATE_PASSIVE_IDLE: //Give back the available location in case of Passive location because the location provider takes care of the location and send Denied. + // follow through + case LOC_MGR_STATE_BOTH_GPS_WPS: { SysLog(NID_LOC, "All the methods are running. Get the best location among all the providers."); long long gpsTimestamp = 0; long long wpsTimestamp = 0; - if (__gpsHandler.pLocation->IsValid()) + if (__locMgrStatus.gpsHandler.pLocation->IsValid()) { - gpsTimestamp = _LocationImpl::GetInstance(*__gpsHandler.pLocation)->GetTimestampInMs(); + gpsTimestamp = _LocationImpl::GetInstance(*__locMgrStatus.gpsHandler.pLocation)->GetTimestampInMs(); } - if (__wpsHandler.pLocation->IsValid()) + if (__locMgrStatus.wpsHandler.pLocation->IsValid()) { - wpsTimestamp = _LocationImpl::GetInstance(*__wpsHandler.pLocation)->GetTimestampInMs(); + wpsTimestamp = _LocationImpl::GetInstance(*__locMgrStatus.wpsHandler.pLocation)->GetTimestampInMs(); } SysLog(NID_LOC, "Compare timestamp(gps: %lld, wps: %lld) of different locations.", gpsTimestamp, wpsTimestamp); if (gpsTimestamp > wpsTimestamp) { SysLog(NID_LOC, "GPS time stamp is greater than WPS."); - return __gpsHandler.pLocation.get(); + return __locMgrStatus.gpsHandler.pLocation.get(); } else if (wpsTimestamp > gpsTimestamp) { SysLog(NID_LOC, "WPS time stamp is greater than GPS."); - return __wpsHandler.pLocation.get(); + return __locMgrStatus.wpsHandler.pLocation.get(); } else if (gpsTimestamp == wpsTimestamp) { - if (__gpsHandler.pLocation->GetHorizontalAccuracy() <= __wpsHandler.pLocation->GetHorizontalAccuracy()) + double gpsAccuracy = __locMgrStatus.gpsHandler.pLocation->GetHorizontalAccuracy(); + double wpsAccuracy = __locMgrStatus.wpsHandler.pLocation->GetHorizontalAccuracy(); + if ((gpsAccuracy <= wpsAccuracy) || Double::IsNaN(wpsAccuracy)) { SysLog(NID_LOC, "GPS time stamp is equal to WPS and GPS accuracy is better than WPS."); - return __gpsHandler.pLocation.get(); + return __locMgrStatus.gpsHandler.pLocation.get(); } else { - SysLog(NID_LOC, "WPS time stamp is equal to GPS but WPS accuracy is better than GPS."); - return __wpsHandler.pLocation.get(); + SysLog(NID_LOC, "WPS time stamp is equal to GPS and WPS accuracy is better than GPS."); + return __locMgrStatus.wpsHandler.pLocation.get(); } } } break; - case LOC_METHOD_REQUESTED_NONE: + case LOC_MGR_STATE_IDLE: // follow through default: SysLog(NID_LOC, "Location updates not running."); return null; } - SysLog(NID_LOC, "Returning null as none of the conditions are satsfied."); + SysLog(NID_LOC, "Returning null as none of the conditions are satisfied."); return null; } result _LocationManager::GetLocation(location_method_e nativeLocMethod) { - const int MAX_VALID_TIME_DIFFERENCE = 2000; - double altitude = Tizen::Locations::NaN; - double latitude = Tizen::Locations::NaN; - double longitude = Tizen::Locations::NaN; - time_t timestamp; + location_accuracy_level_e accuracy_level; int res = -1; - int satellitesInViewCount = 0; - int satellitesInUseCount = 0; - time_t timestampSatellite = 0; - String satInfo = L""; + time_t timestamp = 0; long long timeDiff = 0; + double altitude = NaN; + double latitude = NaN; + double longitude = NaN; + double climb = NaN; + double direction = NaN; + double speed = NaN; + double horizontal_acc = NaN; + double vertical_acc = NaN; location_manager_h nativeHandle = null; Location* pLocation = null; @@ -1027,15 +910,15 @@ _LocationManager::GetLocation(location_method_e nativeLocMethod) { case LOCATIONS_METHOD_GPS: { - nativeHandle = __gpsHandler.handle; - pLocation = __gpsHandler.pLocation.get(); + nativeHandle = __locMgrStatus.gpsHandler.handle; + pLocation = __locMgrStatus.gpsHandler.pLocation.get(); } break; case LOCATIONS_METHOD_WPS: { - nativeHandle = __wpsHandler.handle; - pLocation = __wpsHandler.pLocation.get(); + nativeHandle = __locMgrStatus.wpsHandler.handle; + pLocation = __locMgrStatus.wpsHandler.pLocation.get(); } break; @@ -1043,39 +926,698 @@ _LocationManager::GetLocation(location_method_e nativeLocMethod) break; } - res = location_manager_get_position(nativeHandle, &altitude, &latitude, &longitude, ×tamp); + res = location_manager_get_location(nativeHandle, &altitude, &latitude, &longitude, &climb, &direction, &speed, &accuracy_level, &horizontal_acc, &vertical_acc, ×tamp); SysTryReturnResult(NID_LOC, res == 0, E_SYSTEM, "Failed to obtain the natvie location information for the method (%x)", nativeLocMethod); + SysSecureLog(NID_LOC, "Location details: Lat(%lf), Long(%lf), Alt(%lf), Climb (%lf), Direction (%lf), Speed (%lf), Accuracy Level(%d), HAcc (%lf), VAcc (%lf), timestamp (%ld).", + latitude, longitude, altitude, climb, direction, speed, accuracy_level, horizontal_acc, vertical_acc, timestamp); if (res == 0) { - altitude = ConvertToNativeFormatAltitude(altitude); - result r = SetLocationInformation(latitude, longitude, altitude, timestamp, nativeLocMethod, pLocation); - if (r != E_SUCCESS) - { - SysLog(NID_LOC, "Failed to set the location information"); - } + Location locationData = _LocationImpl::GetLocationInstance(); + _LocationImpl* pLocDataImpl = _LocationImpl::GetInstance(locationData); + + horizontal_acc = ConvertToNativeFormat(horizontal_acc); + vertical_acc = ConvertToNativeFormat(vertical_acc); + Coordinates coordinates; + coordinates.Set(latitude, longitude, altitude); + pLocDataImpl->SetCoordinates(coordinates); + pLocDataImpl->SetHorizontalAccuracy(horizontal_acc); + pLocDataImpl->SetVerticalAccuracy(vertical_acc); + pLocDataImpl->SetTimestamp((long long) timestamp * 1000); + pLocDataImpl->SetCourse(direction); + pLocDataImpl->SetSpeed(speed); + pLocDataImpl->SetValidity(true); if (nativeLocMethod == LOCATIONS_METHOD_GPS) { - res = gps_status_get_satellite(__gpsHandler.handle, &satellitesInUseCount, &satellitesInViewCount, ×tampSatellite); + const int MAX_VALID_TIME_DIFFERENCE = 2000; + int satellitesInViewCount = 0; + int satellitesInUseCount = 0; + time_t timestampSatellite = 0; + String satInfo = L""; - timeDiff = abs(timestamp - timestampSatellite); + __locMgrStatus.gpsFailCount = 0; + pLocDataImpl->SetExtraInfo(L"location_method", L"gps"); + res = gps_status_get_satellite(nativeHandle, &satellitesInUseCount, &satellitesInViewCount, ×tampSatellite); + + timeDiff = Math::Abs(timestamp - timestampSatellite); timeDiff = timeDiff * 1000; SysLog(NID_LOC, "Result (%d), Satellites in Use (%d), Satellites in View (%d), Time stamp (%ld), Time Difference (Loc and Sat) (%ld)", res, satellitesInUseCount, satellitesInViewCount, timestampSatellite, timeDiff); if (res == 0 && timeDiff <= MAX_VALID_TIME_DIFFERENCE) { - res = gps_status_foreach_satellites_in_view(__gpsHandler.handle, SatelliteInfoUpdated, &satInfo); + res = gps_status_foreach_satellites_in_view(__locMgrStatus.gpsHandler.handle, SatelliteInfoUpdated, &satInfo); } satInfo.Trim(); SysLog(NID_LOC, "Result of get satellite is (%d) and satelliteInfo string representation is (%ls)", res, satInfo.GetPointer()); - _LocationImpl::GetInstance(*__gpsHandler.pLocation.get())->SetExtraInfo(L"satellite", satInfo); + pLocDataImpl->SetExtraInfo(L"satellite", satInfo); + } + else if (nativeLocMethod == LOCATIONS_METHOD_WPS) + { + pLocDataImpl->SetExtraInfo(L"location_method", L"network"); + } + *pLocation = locationData; + } + + return E_SUCCESS; +} + +void +_LocationManager::HandleBothGpsWpsState(void) +{ + bool isGpsAccMet = false; + bool isWpsAccMet = false; + bool isGpsTimeUpdated = false; + bool isWpsTimeUpdated = false; + + IsGpsLocationUpdated(isGpsTimeUpdated, isGpsAccMet); + IsWpsLocationUpdated(isWpsTimeUpdated, isWpsAccMet); + + if (isWpsAccMet) + { + StopSubStateTimer(); + SysLog(NID_LOC, "WPS accuracy is met during LOC_MGR_STATE_BOTH_GPS_WPS state."); + location_manager_stop(__locMgrStatus.gpsHandler.handle); + __locMgrStatus.locMgrState = LOC_MGR_STATE_WPS_ONLY; + __locMgrStatus.locMgrSubState = LM_SS_SETTLED; + } + else if (isGpsAccMet) + { + SysLog(NID_LOC, "GPS accuracy is met during LOC_MGR_STATE_BOTH_GPS_WPS state. Wait for 10 more seconds to give WPS a chance."); + + if (__locMgrStatus.locMgrSubState != LM_SS_BOTH_SETTLED_WAITING) + { + const int SUB_STATE_TIMER_VALUE = 10; + result r = RestartSubStateTimer(SUB_STATE_TIMER_VALUE); + if (!IsFailed(r)) + { + SysLog(NID_LOC, "Started a timer for 10 seconds to give WPS a chance in the state LOC_MGR_STATE_BOTH_GPS_WPS."); + __locMgrStatus.locMgrSubState = LM_SS_BOTH_SETTLED_WAITING; + } } } + else if (isWpsTimeUpdated || isGpsTimeUpdated) + { + SysLog(NID_LOC, "GPS accuracy and WPS accuracy not met during LOC_MGR_STATE_BOTH_GPS_WPS state. Wait for 20 seconds."); + + if (__locMgrStatus.locMgrSubState != LM_SS_BOTH_SENSING) + { + const int SUB_STATE_TIMER_VALUE = 20; + result r = RestartSubStateTimer(SUB_STATE_TIMER_VALUE); + if (!IsFailed(r)) + { + SysLog(NID_LOC, "Started a timer for 20 seconds as the accuracy is not met in state LOC_MGR_STATE_BOTH_GPS_WPS."); + __locMgrStatus.locMgrSubState = LM_SS_BOTH_SENSING; + } + } + } + else + { + SysLog(NID_LOC, "Position not obtained by either GPS or WPS."); + StopSubStateTimer(); + __locMgrStatus.locMgrSubState = LM_SS_NO_FIX; + } +} + +void +_LocationManager::HandleGpsOnlyState(void) +{ + bool isGpsAccMet = false; + bool isTimeUpdated = false; + double minAccRequested = ConvertLocationAccuracyToDouble(__minRequestedAccuracy); + + IsGpsLocationUpdated(isTimeUpdated, isGpsAccMet); + + if (!__wpsEnabled && isGpsAccMet) + { + StopSubStateTimer(); + __locMgrStatus.locMgrSubState = LM_SS_SETTLED; + return; + } + if (__wpsEnabled) + { + SysLog(NID_LOC, "WPS setting is enabled."); + if (isGpsAccMet) //Location available with requested accuracy. + { + if (minAccRequested > ConvertLocationAccuracyToDouble(LOC_ACCURACY_TEN_METERS)) + { + if (__locMgrStatus.locMgrSubState != LM_SS_GPS_ONLY_SETTLED) + { + const int SUB_STATE_TIMER_VALUE = 120; + result r = RestartSubStateTimer(SUB_STATE_TIMER_VALUE); + if (!IsFailed(r)) + { + SysLog(NID_LOC, "Started the sub state timer of 120 seconds in LOC_MGR_STATE_GPS_ONLY state."); + __locMgrStatus.locMgrSubState = LM_SS_GPS_ONLY_SETTLED; + } + } + } + else + { + __locMgrStatus.locMgrSubState = LM_SS_SETTLED; + } + } + else if (isTimeUpdated) //GPS Location available with less accuracy. + { + if (__locMgrStatus.locMgrSubState != LM_SS_GPS_ONLY_SENSING) + { + const int SUB_STATE_TIMER_VALUE = 40; + result r = RestartSubStateTimer(SUB_STATE_TIMER_VALUE); + if (!IsFailed(r)) + { + SysLog(NID_LOC, "Started the sub state timer of 40 seconds in LOC_MGR_STATE_GPS_ONLY state."); + __locMgrStatus.locMgrSubState = LM_SS_GPS_ONLY_SENSING; + } + } + } + else //Location not available + { + if (__locMgrStatus.locMgrSubState != LM_SS_GPS_ONLY_NO_FIX) + { + const int SUB_STATE_TIMER_VALUE = 10; + result r = RestartSubStateTimer(SUB_STATE_TIMER_VALUE); + if (!IsFailed(r)) + { + SysLog(NID_LOC, "Started the sub state timer of 10 seconds in LOC_MGR_STATE_GPS_ONLY state."); + __locMgrStatus.locMgrSubState = LM_SS_GPS_ONLY_NO_FIX; + } + } + } + } + else + { + StopSubStateTimer(); + + if (isTimeUpdated) + { + SysLog(NID_LOC, "GPS position available with less accuracy in LOC_MGR_STATE_GPS_ONLY state."); + __locMgrStatus.locMgrSubState = LM_SS_SENSING; + } + else + { + SysLog(NID_LOC, "GPS position not available in LOC_MGR_STATE_GPS_ONLY state."); + __locMgrStatus.locMgrSubState = LM_SS_NO_FIX; + } + } +} + +void +_LocationManager::HandleWpsOnlyState(void) +{ + bool isWpsAccMet = false; + bool isTimeUpdated = false; + double wpsAccuracy = __locMgrStatus.wpsHandler.pLocation->GetHorizontalAccuracy(); + + IsWpsLocationUpdated(isTimeUpdated, isWpsAccMet); + + if (isWpsAccMet) + { + StopSubStateTimer(); + __locMgrStatus.locMgrSubState = LM_SS_SETTLED; + return; + } + + if (__gpsEnabled) + { + SysLog(NID_LOC, "GPS is enabled."); + if (isTimeUpdated) // WPS location available with less accuracy + { + SysLog(NID_LOC, "WPS position available with less accuracy in LOC_MGR_STATE_WPS_ONLY state."); + if (__locMgrStatus.gpsFailCount == 0) + { + if (__minRequestedAccuracy > LOC_ACCURACY_TEN_METERS) + { + if (__locMgrStatus.locMgrSubState != LM_SS_WPS_ONLY_LESS_ACC_SENSING) + { + double currAccDiff = wpsAccuracy - ConvertLocationAccuracyToDouble(__minRequestedAccuracy); + int subStateTimerValue = 0; + + if (currAccDiff < 100) + { + subStateTimerValue = 15; + } + else + { + subStateTimerValue = 10; + } + result r = RestartSubStateTimer(subStateTimerValue * 1000); + if (!IsFailed(r)) + { + SysLog(NID_LOC, "Started the sub state timer for (%d) seconds in LOC_MGR_STATE_WPS_ONLY as WPS accuracy not met.", subStateTimerValue); + __locMgrStatus.locMgrSubState = LM_SS_WPS_ONLY_LESS_ACC_SENSING; + } + } + } + else if (__minRequestedAccuracy == LOC_ACCURACY_FINEST || __minRequestedAccuracy == LOC_ACCURACY_TEN_METERS) + { + if (__locMgrStatus.locMgrSubState != LM_SS_WPS_ONLY_FINE_ACC_SENSING) + { + const int SUB_STATE_TIMER_VALUE = 5; + result r = RestartSubStateTimer(SUB_STATE_TIMER_VALUE); + if (!IsFailed(r)) + { + SysLog(NID_LOC, "Started the sub state timer for 5 seconds in LOC_MGR_STATE_WPS_ONLY as WPS accuracy not met."); + __locMgrStatus.locMgrSubState = LM_SS_WPS_ONLY_FINE_ACC_SENSING; + } + } + } + } + else + { + if (__locMgrStatus.locMgrSubState != LM_SS_WPS_ONLY_SENSING) + { + SysLog(NID_LOC, "The number of GPS failures is (%d)", __locMgrStatus.gpsFailCount); + double timerVal = Math::Pow(2, (__locMgrStatus.gpsFailCount - 1)) * 10; + if (timerVal > MAX_TIMER_VALUE_DURING_WPS_POSITIONING) + { + timerVal = MAX_TIMER_VALUE_DURING_WPS_POSITIONING; + } + const int SUB_STATE_TIMER_VALUE = (int) timerVal; + result r = RestartSubStateTimer(SUB_STATE_TIMER_VALUE); + if (!IsFailed(r)) + { + SysLog(NID_LOC, "Started the sub state timer for (%d) seconds in LOC_MGR_STATE_WPS_ONLY mode when last GPS session has failed."); + __locMgrStatus.locMgrSubState = LM_SS_WPS_ONLY_SENSING; + } + } + } + } + else + { + if (__locMgrStatus.locMgrSubState != LM_SS_WPS_ONLY_NO_FIX) + { + const int SUB_STATE_TIMER_VALUE = 10; + SysLog(NID_LOC, "WPS position not available in LOC_MGR_STATE_WPS_ONLY state."); + result r = RestartSubStateTimer(SUB_STATE_TIMER_VALUE); + if (!IsFailed(r)) + { + SysLog(NID_LOC, "Started the sub state timer for 10 seconds in LOC_MGR_STATE_WPS_ONLY state when GPS is enabled and WPS no fix."); + __locMgrStatus.locMgrSubState = LM_SS_WPS_ONLY_NO_FIX; + } + } + } + } + else + { + StopSubStateTimer(); + if (isTimeUpdated) + { + SysLog(NID_LOC, "WPS position available with less accuracy in LOC_MGR_STATE_WPS_ONLY state."); + __locMgrStatus.locMgrSubState = LM_SS_SENSING; + } + else + { + SysLog(NID_LOC, "WPS position not available in LOC_MGR_STATE_WPS_ONLY state."); + __locMgrStatus.locMgrSubState = LM_SS_NO_FIX; + } + } +} + +void +_LocationManager::IsGpsLocationUpdated(bool& isTimeUpdated, bool& isAccMet) +{ + double minAccRequested = ConvertLocationAccuracyToDouble(__minRequestedAccuracy); + + if (__locMgrStatus.gpsHandler.pLocation->GetTimestamp() > __locMgrStatus.gpsHandler.oldTimeStamp) + { + double gpsAccuracy = __locMgrStatus.gpsHandler.pLocation->GetHorizontalAccuracy(); + isTimeUpdated = true; + if (!Double::IsNaN(gpsAccuracy) && gpsAccuracy <= minAccRequested) + { + isAccMet = true; + } + __locMgrStatus.gpsHandler.oldTimeStamp = __locMgrStatus.gpsHandler.pLocation->GetTimestamp(); + } +} + +void +_LocationManager::IsWpsLocationUpdated(bool& isTimeUpdated, bool& isAccMet) +{ + double minAccRequested = ConvertLocationAccuracyToDouble(__minRequestedAccuracy); + + if (__locMgrStatus.wpsHandler.pLocation->GetTimestamp() > __locMgrStatus.wpsHandler.oldTimeStamp) + { + double wpsAccuracy = __locMgrStatus.wpsHandler.pLocation->GetHorizontalAccuracy(); + isTimeUpdated = true; + if (!Double::IsNaN(wpsAccuracy) && wpsAccuracy <= minAccRequested) + { + isAccMet = true; + } + __locMgrStatus.wpsHandler.oldTimeStamp = __locMgrStatus.wpsHandler.pLocation->GetTimestamp(); + } +} + +double +_LocationManager::ConvertLocationAccuracyToDouble(LocationAccuracy locAcc) +{ + SysAssertf((locAcc > LOC_ACCURACY_INVALID && locAcc <= LOC_ACCURACY_ANY), "The accuracy value is not valid."); + + static int accArray[] = {NaN, ACCURACY_FINEST, ACCURACY_TEN_MTRS, ACCURACY_HUNDRED_MTRS, ACCURACY_ONE_KILOMETER, ACCURACY_ANY}; + + return accArray[locAcc]; +} + +result +_LocationManager::RestartSubStateTimer(int timeout) +{ + result r = E_SUCCESS; + + StopSubStateTimer(); + r = __locMgrStatus.pLocMgrSubStateTimer->Start(timeout * 1000); + SysTryReturnResult(NID_LOC, r == E_SUCCESS, r, "[%s] Failed to start the sub state timer with timer value (%d) seconds.", GetErrorMessage(r), timeout); + __locMgrStatus.isSubStateTimerStarted = true; + // Make a note of the GPS time stamp when sub state timer started. This is used to identify GPS fail case. + __locMgrStatus.gpsTimeAtSubstateTimerStart = __locMgrStatus.gpsHandler.pLocation->GetTimestamp(); return E_SUCCESS; } +void +_LocationManager::StopSubStateTimer(void) +{ + if (__locMgrStatus.isSubStateTimerStarted) + { + result r = __locMgrStatus.pLocMgrSubStateTimer->Cancel(); + SysTryLog(NID_LOC, r == E_SUCCESS, "[%s] Failed to stop the sub state timer.", GetErrorMessage(r)); + __locMgrStatus.isSubStateTimerStarted = false; + } +} + +void +_LocationManager::HandleSubStateTimerExpiry(void) +{ + SysLog(NID_LOC, "The substate timer expired for the State (%d) with sub state (%d).", __locMgrStatus.locMgrState, __locMgrStatus.locMgrSubState); + + switch (__locMgrStatus.locMgrState) + { + case LOC_MGR_STATE_BOTH_GPS_WPS: + { + switch (__locMgrStatus.locMgrSubState) + { + case LM_SS_BOTH_SENSING: + // follow through + case LM_SS_BOTH_SETTLED_WAITING: + { + enum nextState + { + SWITCH_STATE_NONE, + SWITCH_STATE_WPS_ONLY, + SWITCH_STATE_GPS_ONLY + }; + + nextState nxtState = SWITCH_STATE_NONE; + double gpsAccuracy = __locMgrStatus.gpsHandler.pLocation->GetHorizontalAccuracy(); + double wpsAccuracy = __locMgrStatus.wpsHandler.pLocation->GetHorizontalAccuracy(); + + long long wpsTimestamp = __locMgrStatus.wpsHandler.pLocation->GetTimestamp().GetTicks(); + long long gpsTimestamp = __locMgrStatus.gpsHandler.pLocation->GetTimestamp().GetTicks(); + + long long timeDiff = Math::Abs(wpsTimestamp - gpsTimestamp); + SysLog(NID_LOC, "Accuracy values are, GPS (%lf) and WPS (%lf). Time difference is (%lld).", gpsAccuracy, wpsAccuracy, timeDiff); + + if (timeDiff <= 1) + { + SysLog(NID_LOC, "Both GPS and WPS position available."); + if (!Double::IsNaN(wpsAccuracy) && wpsAccuracy <= gpsAccuracy) + { + SysLog(NID_LOC, "WPS accuracy is better than or equal to GPS."); + nxtState = SWITCH_STATE_WPS_ONLY; + } + else + { + SysLog(NID_LOC, "GPS accuracy is better than WPS."); + nxtState = SWITCH_STATE_GPS_ONLY; + } + } + else + { + SysLog(NID_LOC, "WPS and GPS timestamp is not similar."); + if (wpsTimestamp > gpsTimestamp) + { + SysLog(NID_LOC, "WPS timestamp is better than GPS."); + nxtState = SWITCH_STATE_WPS_ONLY; + } + else + { + SysLog(NID_LOC, "GPS timestamp is better than WPS."); + nxtState = SWITCH_STATE_GPS_ONLY; + } + } + + switch(nxtState) + { + case SWITCH_STATE_WPS_ONLY: + { + location_manager_stop(__locMgrStatus.gpsHandler.handle); + __locMgrStatus.locMgrState = LOC_MGR_STATE_WPS_ONLY; + __locMgrStatus.locMgrSubState = LM_SS_NO_FIX; + } + break; + + case SWITCH_STATE_GPS_ONLY: + { + location_manager_stop(__locMgrStatus.wpsHandler.handle); + __locMgrStatus.locMgrState = LOC_MGR_STATE_GPS_ONLY; + __locMgrStatus.locMgrSubState = LM_SS_NO_FIX; + } + break; + + case SWITCH_STATE_NONE: + // follow through + default: + SysAssertf(false, "This state cannot happen."); + break; + } + + if (__locMgrStatus.locMgrSubState == LM_SS_BOTH_SENSING) + { + long long diff = gpsTimestamp - __locMgrStatus.gpsTimeAtSubstateTimerStart.GetTicks(); + if (diff < 0) // Considered to be GPS fail. + { + __locMgrStatus.gpsFailCount++; + } + } + } + break; + + case LM_SS_IDLE: + // follow through + case LM_SS_SETTLED: + // follow through + case LM_SS_SENSING: + // follow through + case LM_SS_NO_FIX: + // follow through + case LM_SS_GPS_ONLY_SETTLED: + // follow through + case LM_SS_GPS_ONLY_SENSING: + // follow through + case LM_SS_GPS_ONLY_NO_FIX: + // follow through + case LM_SS_WPS_ONLY_LESS_ACC_SENSING: + // follow through + case LM_SS_WPS_ONLY_FINE_ACC_SENSING: + // follow through + case LM_SS_WPS_ONLY_SENSING: + // follow through + case LM_SS_WPS_ONLY_NO_FIX: + // follow through + default: + SysLog(NID_LOC, "The sub state timer expired in wrong location manager sub state."); + break; + } + } + break; + + case LOC_MGR_STATE_GPS_ONLY: + { + switch (__locMgrStatus.locMgrSubState) + { + case LM_SS_GPS_ONLY_SETTLED: + // follow through + case LM_SS_GPS_ONLY_SENSING: + // follow through + case LM_SS_GPS_ONLY_NO_FIX: + { + if (__wpsEnabled) + { + SysLog(NID_LOC, "WPS setting is enabled. Start WPS now."); + int res = location_manager_start(__locMgrStatus.wpsHandler.handle); + SysTryLog(NID_LOC, res == 0, "Failed to start the core WPS location manager. So continue with GPS only."); + if (res == 0) + { + __locMgrStatus.locMgrState = LOC_MGR_STATE_BOTH_GPS_WPS; + } + } + __locMgrStatus.locMgrSubState = LM_SS_NO_FIX; + } + break; + + case LM_SS_IDLE: + // follow through + case LM_SS_SETTLED: + // follow through + case LM_SS_SENSING: + // follow through + case LM_SS_NO_FIX: + // follow through + case LM_SS_BOTH_SENSING: + // follow through + case LM_SS_BOTH_SETTLED_WAITING: + // follow through + case LM_SS_WPS_ONLY_LESS_ACC_SENSING: + // follow through + case LM_SS_WPS_ONLY_FINE_ACC_SENSING: + // follow through + case LM_SS_WPS_ONLY_SENSING: + // follow through + case LM_SS_WPS_ONLY_NO_FIX: + // follow through + default: + SysLog(NID_LOC, "The sub state timer expired in wrong location manager sub state."); + break; + } + } + break; + + case LOC_MGR_STATE_WPS_ONLY: + { + switch (__locMgrStatus.locMgrSubState) + { + case LM_SS_WPS_ONLY_LESS_ACC_SENSING: + // follow through + case LM_SS_WPS_ONLY_FINE_ACC_SENSING: + // follow through + case LM_SS_WPS_ONLY_SENSING: + // follow through + case LM_SS_WPS_ONLY_NO_FIX: + { + if (__gpsEnabled) + { + SysLog(NID_LOC, "GPS setting is enabled and WPS could not fix the location with requested accuracy. Start GPS now."); + int res = location_manager_start(__locMgrStatus.gpsHandler.handle); + SysTryLog(NID_LOC, res == 0, "Failed to start the core GPS location provider. So continue with WPS only."); + if (res == 0) + { + __locMgrStatus.locMgrState = LOC_MGR_STATE_BOTH_GPS_WPS; + } + } + __locMgrStatus.locMgrSubState = LM_SS_NO_FIX; + } + break; + + case LM_SS_IDLE: + // follow through + case LM_SS_SETTLED: + // follow through + case LM_SS_SENSING: + // follow through + case LM_SS_NO_FIX: + // follow through + case LM_SS_BOTH_SENSING: + // follow through + case LM_SS_BOTH_SETTLED_WAITING: + // follow through + case LM_SS_GPS_ONLY_SETTLED: + // follow through + case LM_SS_GPS_ONLY_SENSING: + // follow through + case LM_SS_GPS_ONLY_NO_FIX: + // follow through + default: + SysLog(NID_LOC, "The sub state timer expired in wrong location manager sub state."); + break; + } + } + break; + + case LOC_MGR_STATE_IDLE: + // follow through + case LOC_MGR_STATE_PASSIVE_IDLE: + // follow through + default: + SysLog(NID_LOC, "The sub state timer expired in wrong location manager state."); + break; + } + + __locMgrStatus.isSubStateTimerStarted = false; +} + +void +_LocationManager::HandleLocationCheckTimerExpiry(void) +{ + SysLog(NID_LOC, "Location check timer expired."); + const int LOC_CHECK_TIMER_VALUE = 1000; + + switch (__locMgrStatus.locMgrState) + { + case LOC_MGR_STATE_BOTH_GPS_WPS: + { + if (__locMgrStatus.wpsHandler.serviceState == LOCATIONS_SERVICE_ENABLED) + { + result gpsRes = GetLocation(LOCATIONS_METHOD_WPS); + SysTryLog(NID_LOC, gpsRes == E_SUCCESS, "[E_SYSTEM] Failed to obtain the WPS location information."); + } + else + { + SysLog(NID_LOC, "WPS Location not available at the Native side."); + } + + if (__locMgrStatus.gpsHandler.serviceState == LOCATIONS_SERVICE_ENABLED) + { + result wpsRes = GetLocation(LOCATIONS_METHOD_GPS); + SysTryLog(NID_LOC, wpsRes == E_SUCCESS, "[E_SYSTEM] Failed to obtain the GPS location information."); + } + else + { + SysLog(NID_LOC, "GPS Location not available at the Native side."); + } + HandleBothGpsWpsState(); + } + break; + + case LOC_MGR_STATE_GPS_ONLY: + { + if (__locMgrStatus.gpsHandler.serviceState == LOCATIONS_SERVICE_ENABLED) + { + result res = GetLocation(LOCATIONS_METHOD_GPS); + SysTryLog(NID_LOC, res == E_SUCCESS, "[E_SYSTEM] Failed to obtain the GPS location information."); + } + else + { + SysLog(NID_LOC, "GPS Location not available at the Native side."); + } + HandleGpsOnlyState(); + } + break; + + case LOC_MGR_STATE_WPS_ONLY: + { + if (__locMgrStatus.wpsHandler.serviceState == LOCATIONS_SERVICE_ENABLED) + { + result res = GetLocation(LOCATIONS_METHOD_WPS); + SysTryLog(NID_LOC, res == E_SUCCESS, "[E_SYSTEM] Failed to obtain the WPS location information."); + } + else + { + SysLog(NID_LOC, "WPS Location not available at the Native side."); + } + HandleWpsOnlyState(); + } + break; + + case LOC_MGR_STATE_IDLE: + //follow through + case LOC_MGR_STATE_PASSIVE_IDLE: + //follow through + default: + SysLog(NID_LOC, "The timer expiry called in wrong location manager state."); + return; + } + + __pLocCheckTimer->Start(LOC_CHECK_TIMER_VALUE); +} + bool _LocationManager::OnStart(void) { @@ -1083,17 +1625,17 @@ _LocationManager::OnStart(void) int res = -1; - std::unique_ptr< Tizen::Base::Collection::ArrayList, AllElementsDeleter > pLocInfoRequestList(new (std::nothrow) ArrayList(SingleObjectDeleter)); + std::unique_ptr< ArrayList, AllElementsDeleter > pLocInfoRequestList(new (std::nothrow) ArrayList(SingleObjectDeleter)); SysTryReturn(NID_LOC, pLocInfoRequestList != null, false, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); result r = pLocInfoRequestList->Construct(); SysTryReturn(NID_LOC, r == E_SUCCESS, false, E_SYSTEM, "[E_SYSTEM] Failed to construct the Location Request list."); - std::unique_ptr< Tizen::Base::Collection::ArrayList, AllElementsDeleter > pSyncLocInfoRequestList(new (std::nothrow) ArrayList(SingleObjectDeleter)); + std::unique_ptr< ArrayList, AllElementsDeleter > pSyncLocInfoRequestList(new (std::nothrow) ArrayList(SingleObjectDeleter)); SysTryReturn(NID_LOC, pSyncLocInfoRequestList != null, false, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); r = pSyncLocInfoRequestList->Construct(); SysTryReturn(NID_LOC, r == E_SUCCESS, false, E_SYSTEM, "[E_SYSTEM] Failed to construct the Sync Location Request list."); - std::unique_ptr< Tizen::Base::Collection::ArrayList, AllElementsDeleter > pAlarmInfoRequestList(new (std::nothrow) ArrayList(SingleObjectDeleter)); + std::unique_ptr< ArrayList, AllElementsDeleter > pAlarmInfoRequestList(new (std::nothrow) ArrayList(SingleObjectDeleter)); SysTryReturn(NID_LOC, pAlarmInfoRequestList != null, false, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); r = pAlarmInfoRequestList->Construct(); SysTryReturn(NID_LOC, r == E_SUCCESS, false, E_SYSTEM, "[E_SYSTEM] Failed to construct the Sync Location Request list."); @@ -1103,26 +1645,37 @@ _LocationManager::OnStart(void) unique_ptr< Tizen::Locations::Location > pWpsLocation(_LocationImpl::GetLocationInstanceN()); SysTryReturn(NID_LOC, pWpsLocation != null, false, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); - std::unique_ptr< Tizen::Base::Runtime::Timer > pLocUpdateTimer(new (std::nothrow) Timer()); + std::unique_ptr< Timer > pLocUpdateTimer(new (std::nothrow) Timer()); r = pLocUpdateTimer->Construct(*this); - SysTryReturn(NID_LOC, r == E_SUCCESS, false, E_SYSTEM, "[E_SYSTEM] Failed to construct the location timer."); - - res = location_manager_create(LOCATIONS_METHOD_GPS, &__gpsHandler.handle); - SysTryReturn(NID_LOC, res == 0, false, E_SYSTEM, "[E_SYSTEM] Failed to create Native GPS Location provider."); - res = location_manager_set_service_state_changed_cb(__gpsHandler.handle, GpsServiceUpdateCallback, this); + SysTryReturn(NID_LOC, r == E_SUCCESS, false, E_SYSTEM, "[E_SYSTEM] Failed to construct the location update timer."); + std::unique_ptr< Timer > pLocCheckTimer(new (std::nothrow) Timer()); + r = pLocCheckTimer->Construct(*this); + SysTryReturn(NID_LOC, r == E_SUCCESS, false, E_SYSTEM, "[E_SYSTEM] Failed to construct the location chek timer."); + std::unique_ptr< Timer > pLocMgrSubstateTimer(new (std::nothrow) Timer()); + r = pLocMgrSubstateTimer->Construct(*this); + SysTryReturn(NID_LOC, r == E_SUCCESS, false, E_SYSTEM, "[E_SYSTEM] Failed to construct the location manager sub state timer."); + + r = SettingInfo::AddSettingEventListener(*this); + SysTryReturn(NID_LOC, r == E_SUCCESS, false, E_SYSTEM, "[E_SYSTEM] Failed to set the setting event listener."); + + res = location_manager_create(LOCATIONS_METHOD_GPS, &__locMgrStatus.gpsHandler.handle); + SysTryCatch(NID_LOC, res == 0, , E_SYSTEM, "[E_SYSTEM] Failed to create Native GPS Location provider."); + res = location_manager_set_service_state_changed_cb(__locMgrStatus.gpsHandler.handle, GpsServiceUpdateCallback, this); SysTryCatch(NID_LOC, res == 0, , E_SYSTEM, "[E_SYSTEM] Failed to register service callback for Native GPS Location provider."); - res = location_manager_create(LOCATIONS_METHOD_WPS, &__wpsHandler.handle); + res = location_manager_create(LOCATIONS_METHOD_WPS, &__locMgrStatus.wpsHandler.handle); SysTryCatch(NID_LOC, res == 0, , E_SYSTEM, "[E_SYSTEM] Failed to create Native WPS Location provider."); - res = location_manager_set_service_state_changed_cb(__wpsHandler.handle, WpsServiceUpdateCallback, this); + res = location_manager_set_service_state_changed_cb(__locMgrStatus.wpsHandler.handle, WpsServiceUpdateCallback, this); SysTryCatch(NID_LOC, res == 0, , E_SYSTEM, "[E_SYSTEM] Failed to register service callback for Native WPS Location provider."); __pLocRequestInfoList = std::move(pLocInfoRequestList); __pSyncLocRequestInfoList = std::move(pSyncLocInfoRequestList); __pAlarmRequestInfoList = std::move(pAlarmInfoRequestList); - __pLocUpdateTimer = std::move(pLocUpdateTimer); - __gpsHandler.pLocation = std::move(pGpsLocation); - __wpsHandler.pLocation = std::move(pWpsLocation); + __pLocCallbackTimer = std::move(pLocUpdateTimer); + __pLocCheckTimer = std::move(pLocCheckTimer); + __locMgrStatus.pLocMgrSubStateTimer = std::move(pLocMgrSubstateTimer); + __locMgrStatus.gpsHandler.pLocation = std::move(pGpsLocation); + __locMgrStatus.wpsHandler.pLocation = std::move(pWpsLocation); r = __pInitMonitor->Enter(); SysTryCatch(NID_LOC, r == E_SUCCESS, , r, "[%s] Failed to Enter Monitor. Propagating.", GetErrorMessage(r)); @@ -1135,15 +1688,17 @@ _LocationManager::OnStart(void) return true; CATCH: - if (__gpsHandler.handle) + if (__locMgrStatus.gpsHandler.handle) { - location_manager_destroy(__gpsHandler.handle); + location_manager_destroy(__locMgrStatus.gpsHandler.handle); } - if (__wpsHandler.handle) + if (__locMgrStatus.wpsHandler.handle) { - location_manager_destroy(__wpsHandler.handle); + location_manager_destroy(__locMgrStatus.wpsHandler.handle); } + SettingInfo::RemoveSettingEventListener(*this); + return false; } @@ -1153,14 +1708,15 @@ _LocationManager::OnStop(void) delete __pInitMonitor; __pInitMonitor = null; - if (__gpsHandler.handle) + if (__locMgrStatus.gpsHandler.handle) { - location_manager_destroy(__gpsHandler.handle); + location_manager_destroy(__locMgrStatus.gpsHandler.handle); } - if (__wpsHandler.handle) + if (__locMgrStatus.wpsHandler.handle) { - location_manager_destroy(__wpsHandler.handle); + location_manager_destroy(__locMgrStatus.wpsHandler.handle); } + SettingInfo::RemoveSettingEventListener(*this); } void @@ -1196,29 +1752,6 @@ _LocationManager::OnUserEventReceivedN(RequestId requestId, IList* pArgs) } break; - case REQ_ID_RESTART_LOC_UPDATES: - { - SysLog(NID_LOC, "REQ_ID_RESTART_LOC_UPDATES."); - RestartLocationUpdates(); - } - break; - - case REQ_ID_SUSTAIN_GPS: - { - SysLog(NID_LOC, "REQ_ID_SUSTAIN_GPS."); - location_manager_stop(__wpsHandler.handle); - __locMethodRequested = LOC_METHOD_REQUESTED_GPS; - } - break; - - case REQ_ID_SUSTAIN_WPS: - { - SysLog(NID_LOC, "REQ_ID_SUSTAIN_WPS."); - location_manager_stop(__gpsHandler.handle); - __locMethodRequested = LOC_METHOD_REQUESTED_WPS; - } - break; - case REQ_ID_SYNC_LOC_RETRIEVAL: { SysLog(NID_LOC, "REQ_ID_SYNC_LOC_RETRIEVAL."); @@ -1272,7 +1805,7 @@ _LocationManager::OnUserEventReceivedN(RequestId requestId, IList* pArgs) pInterval = static_cast< Integer* >(pArgs->GetAt(1)); SysTryCatch(NID_LOC, pInterval, , E_INVALID_ARG, "[E_INVALID_ARG] Invalid argument encountered. Ignored."); - UpdateLocRequestInfoList(static_cast< long >(pReqId->ToInt()), pInterval->ToInt()); + UpdateLocRequestInterval(static_cast< long >(pReqId->ToInt()), pInterval->ToInt()); } break; @@ -1320,87 +1853,180 @@ CATCH: void _LocationManager::OnTimerExpired(Tizen::Base::Runtime::Timer& timer) { - if (__pLocUpdateTimer->Equals(timer)) + if (__pLocCheckTimer->Equals(timer)) + { + HandleLocationCheckTimerExpiry(); + } + else if (__pLocCallbackTimer->Equals(timer)) { __timerTicks++; SysLog(NID_LOC, "LocationManager update timer expired. Timer Tick value is (%d).", __timerTicks); - result r = E_SUCCESS; - switch (__locMethodRequested) - { - case LOC_METHOD_REQUESTED_GPS: + __pLocCallbackTimer->Start(__timerInterval * 1000); + SendLocationCallbacks(); + } + else if (__locMgrStatus.pLocMgrSubStateTimer.get()->Equals(timer)) + { + SysLog(NID_LOC, "Substate timer expired."); + HandleSubStateTimerExpiry(); + } + else + { + int count = __pSyncLocRequestInfoList->GetCount(); + for (int i = 0; i < count; i++) { - r = GetLocation(LOCATIONS_METHOD_GPS); - SysTryLog(NID_LOC, r == E_SUCCESS, "[E_SYSTEM] Failed to obtain the GPS location information"); - if (IsFailed(r)) + _SyncLocationRequestInfo* pSyncLocRequestInfo = static_cast< _SyncLocationRequestInfo* >(__pSyncLocRequestInfoList->GetAt(i)); + if (pSyncLocRequestInfo != null && pSyncLocRequestInfo->Equals(timer)) { - SendUserEvent(REQ_ID_RESTART_LOC_UPDATES, null); + SysLog(NID_LOC, "Timer expired for the sync location request with request ID (%ld)", pSyncLocRequestInfo->GetRequestId()); + + HandleSyncRetrievalTimerExpiry(*pSyncLocRequestInfo); + break; } } - break; + } + return; +} - case LOC_METHOD_REQUESTED_WPS: +void +_LocationManager::OnSettingChanged(Tizen::Base::String& key) +{ + const String GPS_STRING(L"http://tizen.org/setting/location.gps"); + const String WPS_STRING(L"http://tizen.org/setting/location.wps"); + + SysLog(NID_LOC, "The setting value is changed for (%ls) setting.", key.GetPointer()); + + if (!((key.Equals(GPS_STRING, false)) || (key.Equals(WPS_STRING, false)))) + { + return; + } + + bool gpsEnabled = false; + bool wpsEnabled = false; + result gps = _SettingInfoImpl::GetValue(GPS_STRING, gpsEnabled); + SysTryReturnVoidResult(NID_LOC, gps == E_SUCCESS, gps, "[%s] Failed to get the setting value for GPS.", GetErrorMessage(gps)); + result wps = _SettingInfoImpl::GetValue(WPS_STRING, wpsEnabled); + SysTryReturnVoidResult(NID_LOC, wps == E_SUCCESS, wps, "[%s] Failed to get the setting value for WPS.", GetErrorMessage(wps)); + + SysLog(NID_LOC, "The current GPS setting value is (%d) and WPS setting value is (%d).", __gpsEnabled, __wpsEnabled); + SysLog(NID_LOC, "The changed GPS setting value is (%d) and WPS setting value is (%d).", gpsEnabled, wpsEnabled); + + switch (__locMgrStatus.locMgrState) + { + case LOC_MGR_STATE_PASSIVE_IDLE: + { + if (gpsEnabled && !wpsEnabled) { - r = GetLocation(LOCATIONS_METHOD_WPS); - SysTryLog(NID_LOC, r == E_SUCCESS, "[E_SYSTEM] Failed to obtain the WPS location information"); - if (IsFailed(r)) + SysLog(NID_LOC, "GPS setting enabled during the LOC_MGR_STATE_PASSIVE_IDLE."); + int res = location_manager_start(__locMgrStatus.gpsHandler.handle); + SysTryLog(NID_LOC, res == 0, "Failed to start the GPS location updates in Passive Idle mode."); + if (res == 0) { - SendUserEvent(REQ_ID_RESTART_LOC_UPDATES, null); + const int LOC_CHECK_TIMER_VALUE = 1; + __locMgrStatus.locMgrState = LOC_MGR_STATE_GPS_ONLY; + __locMgrStatus.locMgrSubState = LM_SS_NO_FIX; + __pLocCheckTimer->Start(LOC_CHECK_TIMER_VALUE * 1000); } } - break; - - case LOC_METHOD_REQUESTED_ALL: + else if (!gpsEnabled && wpsEnabled) { - if (__wpsHandler.serviceState == LOCATIONS_SERVICE_ENABLED) - { - r = GetLocation(LOCATIONS_METHOD_WPS); - SysTryLog(NID_LOC, r == E_SUCCESS, "[E_SYSTEM] Failed to obtain the WPS location information"); - } - else + SysLog(NID_LOC, "WPS setting enabled during the LOC_MGR_STATE_PASSIVE_IDLE."); + int res = location_manager_start(__locMgrStatus.wpsHandler.handle); + SysTryLog(NID_LOC, res == 0, "Failed to start the WPS location updates in Passive Idle mode."); + if (res == 0) { - SysLog(NID_LOC, "WPS Location not available at the Native side."); + const int LOC_CHECK_TIMER_VALUE = 1; + __locMgrStatus.locMgrState = LOC_MGR_STATE_WPS_ONLY; + __locMgrStatus.locMgrSubState = LM_SS_NO_FIX; + __pLocCheckTimer->Start(LOC_CHECK_TIMER_VALUE * 1000); } + } + } + break; + + case LOC_MGR_STATE_BOTH_GPS_WPS: + { + if (!gpsEnabled) + { + SysLog(NID_LOC, "GPS setting turned off during LOC_MGR_STATE_BOTH_GPS_WPS."); + location_manager_stop(__locMgrStatus.gpsHandler.handle); + __locMgrStatus.locMgrState = LOC_MGR_STATE_WPS_ONLY; + } + + if (!wpsEnabled) + { + SysLog(NID_LOC, "WPS setting turned off during LOC_MGR_STATE_BOTH_GPS_WPS."); + location_manager_stop(__locMgrStatus.wpsHandler.handle); + __locMgrStatus.locMgrState = LOC_MGR_STATE_GPS_ONLY; + } + } + break; - if (__gpsHandler.serviceState == LOCATIONS_SERVICE_ENABLED) + case LOC_MGR_STATE_GPS_ONLY: + { + if (!gpsEnabled) + { + int res = -1; + if (wpsEnabled) { - r = GetLocation(LOCATIONS_METHOD_GPS); - SysTryLog(NID_LOC, r == E_SUCCESS, "[E_SYSTEM] Failed to obtain the GPS location information"); + SysLog(NID_LOC, "The WPS setting is enabled. So starting WPS now."); + res = location_manager_start(__locMgrStatus.wpsHandler.handle); + SysTryLog(NID_LOC, res == 0, "Failed to start the location updates for WPS. Return value is (%d).", res); + if (res == 0) + { + __locMgrStatus.locMgrState = LOC_MGR_STATE_WPS_ONLY; + } } - else + if (!wpsEnabled || res != 0) { - SysLog(NID_LOC, "GPS Location not available at the Native side."); + __locMgrStatus.locMgrState = LOC_MGR_STATE_PASSIVE_IDLE; + StopSubStateTimer(); + __pLocCheckTimer->Cancel(); } - } - break; - case LOC_METHOD_REQUESTED_NONE: - // follow through - default: - SysLog(NID_LOC, "Timer expired when no location update is called."); - return; + SysLog(NID_LOC, "GPS setting turned off during LOC_MGR_STATE_GPS_ONLY."); + location_manager_stop(__locMgrStatus.gpsHandler.handle); } - - __pLocUpdateTimer->Start(__timerInterval * 1000); - SendLocationCallbacks(); } - else + break; + + case LOC_MGR_STATE_WPS_ONLY: { - int count = __pSyncLocRequestInfoList->GetCount(); - for (int i = 0; i < count; i++) + if (!wpsEnabled) { - _SyncLocationRequestInfo* pSyncLocRequestInfo = static_cast< _SyncLocationRequestInfo* >(__pSyncLocRequestInfoList->GetAt(i)); - if (pSyncLocRequestInfo != null && pSyncLocRequestInfo->Equals(timer)) + int res = -1; + if (gpsEnabled) { - SysLog(NID_LOC, "Timer expired for the sync location request with request ID (%ld)", pSyncLocRequestInfo->GetRequestId()); - - HandleSyncRetrievalTimerExpiry(*pSyncLocRequestInfo); - break; + SysLog(NID_LOC, "The GPS setting is enabled. So starting GPS now."); + res = location_manager_start(__locMgrStatus.gpsHandler.handle); + SysTryLog(NID_LOC, res == 0, "Failed to start the location updates for GPS. Return value is (%d).", res); + if (res == 0) + { + __locMgrStatus.locMgrState = LOC_MGR_STATE_GPS_ONLY; + } + } + if (!gpsEnabled || res != 0) + { + __locMgrStatus.locMgrState = LOC_MGR_STATE_PASSIVE_IDLE; + StopSubStateTimer(); + __pLocCheckTimer->Cancel(); } + + SysLog(NID_LOC, "WPS setting turned off during LOC_MGR_STATE_WPS_ONLY."); + location_manager_stop(__locMgrStatus.wpsHandler.handle); } } + break; - return; + case LOC_MGR_STATE_IDLE: + // follow through + default: + SysLog(NID_LOC, "GPS setting changed when there is no active location request. (%d),", __locMgrStatus.locMgrState); + break; + } + + __gpsEnabled = gpsEnabled; + __wpsEnabled = wpsEnabled; } bool @@ -1441,7 +2067,7 @@ _LocationManager::GpsServiceUpdateCallback(location_service_state_e state, void* } _LocationManager* pThis = static_cast< _LocationManager* >(user_data); - pThis->__gpsHandler.serviceState = state; + pThis->__locMgrStatus.gpsHandler.serviceState = state; } void @@ -1455,7 +2081,7 @@ _LocationManager::WpsServiceUpdateCallback(location_service_state_e state, void* } _LocationManager* pThis = static_cast< _LocationManager* >(user_data); - pThis->__wpsHandler.serviceState = state; + pThis->__locMgrStatus.wpsHandler.serviceState = state; } int @@ -1467,7 +2093,6 @@ _LocationManager::AlarmExpiryCallback(alarm_id_t alarm_id, void* user_param) SysLog(NID_LOC, "The user parameter is null. So cannot handle the callback."); return -1; } - _LocationManager* pThis = static_cast< _LocationManager* >(user_param); int count = pThis->__pAlarmRequestInfoList->GetCount(); diff --git a/src/FLoc_LocationManager.h b/src/FLoc_LocationManager.h index 4194035..04de9d6 100644 --- a/src/FLoc_LocationManager.h +++ b/src/FLoc_LocationManager.h @@ -29,14 +29,15 @@ #include <alarm.h> #include <location/locations.h> #include <FBaseColAllElementsDeleter.h> +#include <FBaseDateTime.h> #include <FBaseRtEventDrivenThread.h> #include <FLocLocation.h> +#include <FSysISettingEventListener.h> #include "FLoc_ILocationManagerListener.h" #include "FLoc_Types.h" namespace Tizen { namespace Locations { - class _AlarmRequestInfo; class _LocationMonitor; class _LocationRequestInfo; @@ -45,6 +46,7 @@ class _SyncLocationRequestInfo; class _LocationManager : public Tizen::Base::Runtime::EventDrivenThread , public Tizen::Base::Runtime::ITimerEventListener + , public Tizen::System::ISettingEventListener { public: // This method adds the location request into the list of requests and requests for location updates from core location provider. @@ -162,29 +164,29 @@ private: // void RemoveFromAlarmRequestInfoList(RequestId reqId); - // The method restarts both GPS and WPS native location providers. + // The method updates the minimum accuracy required. // - // @since 2.0 + // @since 2.2 // - void RestartLocationUpdates(void); + void UpdateMinimunAccuracy(void); - // The method restarts the update timer after calculating the GCD of the timeout values requested by each location provider. + // The method starts the core location provider when the location is requested during Location manager idle state. // - // @since 2.0 + // @since 2.2 // - void RestartUpdateTimer(void); + void InitiateLocationRequest(void); - // The method is called everytime the sync retrieval timer is expired. + // The method restarts the callback timer after calculating the GCD of the timeout values requested by each location provider. // - // @since 2.0 + // @since 2.2 // - void HandleSyncRetrievalTimerExpiry(_SyncLocationRequestInfo& syncLocRequestInfo); + void RestartCallbackTimer(void); - // The method is called everytime the Async update timer is expired to set the location information. + // The method is called everytime the sync retrieval timer is expired. // // @since 2.0 // - result SetLocationInformation(double latitude, double longitude, double altitude, time_t timestamp, location_method_e locMethod, Location* pLocation); + void HandleSyncRetrievalTimerExpiry(_SyncLocationRequestInfo& syncLocRequestInfo); // The method is called to send back the callbacks in case of async location updates. // @@ -226,7 +228,7 @@ private: // // @since 2.0 // - void UpdateLocRequestInfoList(RequestId reqId, int interval); + void UpdateLocRequestInterval(RequestId reqId, int interval); // This method gets the better location among the three location providers. // @@ -240,22 +242,73 @@ private: // result GetLocation(location_method_e nativeLocMethod); - // This method Covert error code for native error. + // This method handles the location information obtained from core location provider/s when the location manager state is LOC_MGR_STATE_BOTH_GPS_WPS. // - // @since 2.1 + // @since 2.2 // - inline double ConvertToNativeFormat(double value) - { - return value < 0.0 ? Tizen::Locations::NaN : value; - } + void HandleBothGpsWpsState(void); + + // This method handles the location information obtained from core GPS location provider when the location manager state is LOC_MGR_STATE_GPS_ONLY. + // + // @since 2.2 + // + void HandleGpsOnlyState(void); + + // This method handles the location information obtained from core WPS location provider when the location manager state is LOC_MGR_STATE_WPS_ONLY. + // + // @since 2.2 + // + void HandleWpsOnlyState(void); + + // This method checks the validity of location updated by GPS core provider is valid or not. + // + // @since 2.2 + // + void IsGpsLocationUpdated(bool& isTimeUpdated, bool& isAccMet); + + // This method checks the validity of location updated by WPS core provider is valid or not. + // + // @since 2.2 + // + void IsWpsLocationUpdated(bool& isTimeUpdated, bool& isAccMet); + + // This method converts the LocationAccuracy enum variable to corresponding double value. + // + // @since 2.2 + // + double ConvertLocationAccuracyToDouble(LocationAccuracy locAcc); + + // This method stops if timer is running and starts the sub state timer for the given interval. + // + // @since 2.2 + // + result RestartSubStateTimer(int timeout); + + // This method stops the sub state timer if it is running. + // + // @since 2.2 + // + void StopSubStateTimer(void); - // This method Covert error code for native altitude error. + // This method handles the expiry of the sub state. + // + // @since 2.2 + // + void HandleSubStateTimerExpiry(void); + + // This method handles the expiry of the location check timer. + // + // @since 2.2 + // + void HandleLocationCheckTimerExpiry(void); + + // This method Covert error code for native error. // // @since 2.1 // - inline double ConvertToNativeFormatAltitude(double value) + inline double ConvertToNativeFormat(double value) { - return value == -1.0 ? Tizen::Locations::NaN : value; + return value < 0.0 ? Tizen::Locations::NaN : value; } // @see @ref Tizen::Base::Runtime::EventDrivenThread::OnStart() @@ -282,6 +335,12 @@ private: // virtual void OnTimerExpired(Tizen::Base::Runtime::Timer& timer); + // @see @ref Tizen::System::ISettingEventListener::OnSettingChanged() + // + // @since 2.1 + // + virtual void OnSettingChanged(Tizen::Base::String& key); + // This callback is recieved from native location manager for satellite information. // // @since 2.0 @@ -321,31 +380,37 @@ private: private: const static RequestId REQ_ID_START_LOC_UPDATES = 1; const static RequestId REQ_ID_STOP_LOC_UPDATES = 2; - const static RequestId REQ_ID_RESTART_LOC_UPDATES = 3; - const static RequestId REQ_ID_SUSTAIN_GPS = 4; - const static RequestId REQ_ID_SUSTAIN_WPS = 5; - const static RequestId REQ_ID_SYNC_LOC_RETRIEVAL = 6; - const static RequestId REQ_ID_GET_LAST_LOCATION = 7; - const static RequestId REQ_ID_UPDATE_INTERVAL = 8; - const static RequestId REQ_ID_START_ALARM = 9; - const static RequestId REQ_ID_STOP_ALARM = 10; - - enum _LocationMethodRequested - { - LOC_METHOD_REQUESTED_NONE, - LOC_METHOD_REQUESTED_GPS, - LOC_METHOD_REQUESTED_WPS, - LOC_METHOD_REQUESTED_ALL, - } - __locMethodRequested; + const static RequestId REQ_ID_SYNC_LOC_RETRIEVAL = 3; + const static RequestId REQ_ID_GET_LAST_LOCATION = 4; + const static RequestId REQ_ID_UPDATE_INTERVAL = 5; + const static RequestId REQ_ID_START_ALARM = 6; + const static RequestId REQ_ID_STOP_ALARM = 7; enum _LocationManagerState { LOC_MGR_STATE_IDLE, - LOC_MGR_STATE_FAST_SENSING, - LOC_MGR_STATE_FAST_SENSING_SETTLED - } - __locationMgrState; + LOC_MGR_STATE_PASSIVE_IDLE, + LOC_MGR_STATE_BOTH_GPS_WPS, + LOC_MGR_STATE_GPS_ONLY, + LOC_MGR_STATE_WPS_ONLY + }; + + enum _LocationManagerSubState + { + LM_SS_IDLE, + LM_SS_SETTLED, + LM_SS_SENSING, + LM_SS_NO_FIX, + LM_SS_BOTH_SENSING, + LM_SS_BOTH_SETTLED_WAITING, + LM_SS_GPS_ONLY_SETTLED, + LM_SS_GPS_ONLY_SENSING, + LM_SS_GPS_ONLY_NO_FIX, + LM_SS_WPS_ONLY_LESS_ACC_SENSING, + LM_SS_WPS_ONLY_FINE_ACC_SENSING, + LM_SS_WPS_ONLY_SENSING, + LM_SS_WPS_ONLY_NO_FIX + }; class _LocationManagerHandle { @@ -355,6 +420,7 @@ private: , handle(null) , pLocation(null) { + oldTimeStamp.SetValue(1970, 1, 1); } ~_LocationManagerHandle(void) @@ -364,20 +430,48 @@ private: public: location_service_state_e serviceState; location_manager_h handle; + Tizen::Base::DateTime oldTimeStamp; std::unique_ptr< Tizen::Locations::Location > pLocation; }; + class _LocationManagerStatus + { + public: + _LocationManagerStatus(void) + : isSubStateTimerStarted(false) + , locMgrState(LOC_MGR_STATE_IDLE) + , locMgrSubState(LM_SS_IDLE) + , gpsFailCount(0) + { + } + ~_LocationManagerStatus(void) + { + } + + public: + bool isSubStateTimerStarted; + _LocationManagerState locMgrState; + _LocationManagerSubState locMgrSubState; + int gpsFailCount; + Tizen::Base::DateTime gpsTimeAtSubstateTimerStart; + std::unique_ptr< Tizen::Base::Runtime::Timer > pLocMgrSubStateTimer; + _LocationManagerHandle gpsHandler; + _LocationManagerHandle wpsHandler; + }; + + bool __gpsEnabled; + bool __wpsEnabled; + _LocationManagerStatus __locMgrStatus; LocationAccuracy __minRequestedAccuracy; int __timerInterval; int __timerTicks; - _LocationManagerHandle __gpsHandler; - _LocationManagerHandle __wpsHandler; std::unique_ptr< Tizen::Base::Collection::ArrayList, Tizen::Base::Collection::AllElementsDeleter > __pLocRequestInfoList; std::unique_ptr< Tizen::Base::Collection::ArrayList, Tizen::Base::Collection::AllElementsDeleter > __pSyncLocRequestInfoList; std::unique_ptr< Tizen::Base::Collection::ArrayList, Tizen::Base::Collection::AllElementsDeleter > __pAlarmRequestInfoList; - std::unique_ptr< Tizen::Base::Runtime::Timer > __pLocUpdateTimer; - static _LocationManager* __pUniqueInstance; + std::unique_ptr< Tizen::Base::Runtime::Timer > __pLocCallbackTimer; + std::unique_ptr< Tizen::Base::Runtime::Timer > __pLocCheckTimer; Tizen::Base::Runtime::Monitor* __pInitMonitor; + static _LocationManager* __pUniqueInstance; friend class std::default_delete< _LocationManager >; }; // class _LocationManager diff --git a/src/FLoc_LocationProviderImpl.cpp b/src/FLoc_LocationProviderImpl.cpp index dcb75da..f37894a 100644 --- a/src/FLoc_LocationProviderImpl.cpp +++ b/src/FLoc_LocationProviderImpl.cpp @@ -39,6 +39,7 @@ #include <FLocTypes.h> #include <FSysPowerManager.h> #include <FSysSystemTime.h> +#include <FSec_AccessController.h> #include <FSys_SettingInfoImpl.h> #include "FLoc_LocationImpl.h" #include "FLoc_LocationManager.h" @@ -53,6 +54,7 @@ using namespace Tizen::Base; using namespace Tizen::Base::Collection; using namespace Tizen::Base::Runtime; using namespace Tizen::Base::Utility; +using namespace Tizen::Security; using namespace Tizen::System; namespace Tizen { namespace Locations @@ -68,7 +70,7 @@ _LocationProviderImpl::_LocationProviderImpl(void) _LocationProviderImpl::~_LocationProviderImpl(void) { - UiApp* pAppInstance = Tizen::App::UiApp::GetInstance(); + UiApp* pAppInstance = UiApp::GetInstance(); if (pAppInstance) { _AppManagerImpl* pAppManager = _AppManagerImpl::GetInstance(); @@ -88,17 +90,17 @@ _LocationProviderImpl::Construct(const LocationCriteria& criteria, ILocationProv _LocationManager* pLocationManager = _LocationManager::GetInstance(); SysTryReturn(NID_LOC, pLocationManager != null, GetLastResult(), GetLastResult(), "[%s] Failed to get the location manager instance.", GetErrorMessage(GetLastResult())); - std::unique_ptr< Tizen::Base::Collection::ArrayList, AllElementsDeleter > pRegionList(new (std::nothrow) ArrayList(SingleObjectDeleter)); + std::unique_ptr< ArrayList, AllElementsDeleter > pRegionList(new (std::nothrow) ArrayList(SingleObjectDeleter)); SysTryReturn(NID_LOC, pRegionList != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); result 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()); + std::unique_ptr< 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)); - UiApp* pAppInstance = Tizen::App::UiApp::GetInstance(); + UiApp* pAppInstance = UiApp::GetInstance(); if (pAppInstance != null) { _AppManagerImpl* pAppManager = _AppManagerImpl::GetInstance(); @@ -180,7 +182,7 @@ _LocationProviderImpl::KeepLocationUpdateAwake(bool enable) } __locationUpdater.awakeEnabled = enable; - UiApp* appInstance = Tizen::App::UiApp::GetInstance(); + UiApp* appInstance = UiApp::GetInstance(); if (appInstance == null) // This is service APP. So should be handled now. { SysLog(NID_LOC, "Handling the request awake mode(%d) for the service application.", enable); @@ -427,6 +429,7 @@ _LocationProviderImpl::OnLocationEventReceivedN(RequestId reqId, Tizen::Location { SysLog(NID_LOC, "Location Event received."); bool isNew = false; + bool isPrivilegeDenied = false; LocationAccuracy currentAccuracy = LOC_ACCURACY_INVALID; LocationAccuracy lastLocAccuracy = __lastLocationAccuracy; long long lastLocationTime = 0; @@ -453,6 +456,11 @@ _LocationProviderImpl::OnLocationEventReceivedN(RequestId reqId, Tizen::Location currentAccuracy = __pLocationManager->GetAccuracyLevel(pLocation->GetHorizontalAccuracy()); } + if (!GetUserPrivilege()) + { + isPrivilegeDenied = true; + } + if (currentAccuracy != __lastLocationAccuracy) { SysLog(NID_LOC, "Notify the accuracy change."); @@ -462,13 +470,14 @@ _LocationProviderImpl::OnLocationEventReceivedN(RequestId reqId, Tizen::Location if (reqId == __locationUpdater.reqId) { - HandleLocationUpdate(location, isNew); + HandleLocationUpdate(location, isNew, isPrivilegeDenied); } else if (reqId == __regionMonitor.reqId) { if (isNew) { bool gpsEnabled = false; + bool isAccuracyMet = false; _SettingInfoImpl::GetValue(L"http://tizen.org/setting/location.gps", gpsEnabled); SysLog(NID_LOC, "The GPS settings value is %d", gpsEnabled); @@ -479,18 +488,17 @@ _LocationProviderImpl::OnLocationEventReceivedN(RequestId reqId, Tizen::Location *__regionMonitor.pLocation = location; } - if ((currentAccuracy != LOC_ACCURACY_INVALID && currentAccuracy <= __criteria.GetAccuracy()) || !gpsEnabled) + if (!gpsEnabled || (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."); - - HandleRegionMonitoring(location, isNew); + isAccuracyMet = true; } else { SysLog(NID_LOC, "Location criteria (accuracy: %ld) is not met for handling region monitoring.", currentAccuracy); } + + HandleRegionMonitoring(location, isNew, isPrivilegeDenied, isAccuracyMet); } } @@ -521,7 +529,7 @@ void _LocationProviderImpl::OnActiveAppChanged(const Tizen::App::AppId& appId) { Tizen::App::App* pApp = Tizen::App::App::GetInstance(); - Tizen::App::AppId currentAppId = pApp->GetAppId(); + AppId currentAppId = pApp->GetAppId(); SysLog(NID_LOC, "Active App ID is (%ls) and the current app Id is (%ls)", appId.GetPointer(), currentAppId.GetPointer()); @@ -555,8 +563,7 @@ 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()); + HandleRegionMonitoring(*__regionMonitor.pLocation, __regionMonitor.pLocation->IsValid(), !GetUserPrivilege(), true); } result @@ -577,7 +584,7 @@ _LocationProviderImpl::StartLocationUpdates(LocationUpdateType updateType, int i if (!__locationUpdater.awakeEnabled) { - UiApp* pAppInstance = Tizen::App::UiApp::GetInstance(); + UiApp* pAppInstance = UiApp::GetInstance(); if (pAppInstance == null) { startUpdate = false; @@ -690,23 +697,23 @@ _LocationProviderImpl::FireImpl(Tizen::Base::Runtime::IEventListener& listener, } void -_LocationProviderImpl::HandleLocationUpdate(Tizen::Locations::Location& location, bool isNew) +_LocationProviderImpl::HandleLocationUpdate(Tizen::Locations::Location& location, bool isNew, bool isPrivilegeDenied) { LocationServiceStatus newLocationUpdateStatus = __locationUpdater.status; - if (isNew) + if (isPrivilegeDenied) { + SysLog(NID_LOC, "User consent not available."); if (__locationUpdater.type != _LOCATION_UPDATE_TYPE_NONE && __locationUpdater.status != LOC_SVC_STATUS_PAUSED) { - newLocationUpdateStatus = LOC_SVC_STATUS_RUNNING; + newLocationUpdateStatus = LOC_SVC_STATUS_DENIED; } } - else if (!GetUserPrivilege()) + else if (isNew) { - SysLog(NID_LOC, "User consent not available."); if (__locationUpdater.type != _LOCATION_UPDATE_TYPE_NONE && __locationUpdater.status != LOC_SVC_STATUS_PAUSED) { - newLocationUpdateStatus = LOC_SVC_STATUS_DENIED; + newLocationUpdateStatus = LOC_SVC_STATUS_RUNNING; } } else @@ -746,17 +753,17 @@ _LocationProviderImpl::HandleLocationUpdate(Tizen::Locations::Location& location } void -_LocationProviderImpl::HandleRegionMonitoring(Tizen::Locations::Location& location, bool isNew) +_LocationProviderImpl::HandleRegionMonitoring(Tizen::Locations::Location& location, bool isNew, bool isPrivilegeDenied, bool isAccuracyMet) { LocationServiceStatus newRegionMonitorStatus = __regionMonitor.status; - if (isNew) + if (isPrivilegeDenied) { - newRegionMonitorStatus = LOC_SVC_STATUS_RUNNING; + newRegionMonitorStatus = LOC_SVC_STATUS_DENIED; } - else if (!GetUserPrivilege()) + else if (isNew) { - newRegionMonitorStatus = LOC_SVC_STATUS_DENIED; + newRegionMonitorStatus = LOC_SVC_STATUS_RUNNING; } else { @@ -770,12 +777,16 @@ _LocationProviderImpl::HandleRegionMonitoring(Tizen::Locations::Location& locati __pLocationListener->OnRegionMonitoringStatusChanged(__regionMonitor.status); } - if (newRegionMonitorStatus == LOC_SVC_STATUS_RUNNING) + if (isAccuracyMet) { - NotifyRegionCrossedStatus(location); + result r = __regionMonitor.pTimer->Cancel(); + SysTryLog(NID_LOC, r == E_SUCCESS, "Failed to cancel the timer."); + if (newRegionMonitorStatus == LOC_SVC_STATUS_RUNNING) + { + NotifyRegionCrossedStatus(location); + } + SetNextRegionMonitoringTime(); } - - SetNextRegionMonitoringTime(); } void @@ -829,7 +840,12 @@ _LocationProviderImpl::NotifyRegionCrossedStatus(const Tizen::Locations::Locatio _RegionState _LocationProviderImpl::GetRegionCurrentState(const _RegionInfo& region, const Location& location) { - TryReturn(location.GetHorizontalAccuracy() >= 0.0, REGION_STATE_UNKNOWN, "Location received with invalid accuracy"); + double horAcc = location.GetHorizontalAccuracy(); + if (Double::IsNaN(horAcc)) + { + horAcc = 0.0; + } + TryReturn(horAcc >= 0.0, REGION_STATE_UNKNOWN, "Location received with invalid accuracy"); SysSecureLog(NID_LOC, "[RegionID %d] Region Information is (Center latitude: %lf, Center longitude: %lf, Region radius:%lf", region.GetRegionId(), region.GetCoordinate().GetLatitude(), region.GetCoordinate().GetLongitude(), region.GetRadius()); @@ -937,6 +953,10 @@ _LocationProviderImpl::GetUserPrivilege(void) { return false; } + + result r = _AccessController::CheckUserPrivilege(_PRV_LOCATION); + SysTryReturn(NID_LOC, r == E_SUCCESS, false, r, "[%s] The user does not allow the application to use location information.", GetErrorMessage(r)); + return true; } diff --git a/src/FLoc_LocationProviderImpl.h b/src/FLoc_LocationProviderImpl.h index 450380b..5cdd1e8 100644 --- a/src/FLoc_LocationProviderImpl.h +++ b/src/FLoc_LocationProviderImpl.h @@ -221,13 +221,13 @@ private: // // @since 2.0 // - void HandleLocationUpdate(Tizen::Locations::Location& location, bool isLocationValid); + void HandleLocationUpdate(Tizen::Locations::Location& location, bool isLocationValid, bool isPrivilegeDenied); // This method handles the region monitoring. // // @since 2.0 // - void HandleRegionMonitoring(Tizen::Locations::Location& location, bool isLocationValid); + void HandleRegionMonitoring(Tizen::Locations::Location& location, bool isLocationValid, bool isPrivilegeDenied, bool isAccuracyMet); // This method sends the callbacks to the applications regarding the Region events. // @since 2.0 diff --git a/src/FLoc_SyncLocationRequestInfo.h b/src/FLoc_SyncLocationRequestInfo.h index e7b72cb..d5b99c6 100644 --- a/src/FLoc_SyncLocationRequestInfo.h +++ b/src/FLoc_SyncLocationRequestInfo.h @@ -31,7 +31,6 @@ #include <FBaseRtTimer.h> #include <FBaseRtITimerEventListener.h> #include <FLocTypes.h> -#include <FSysSystemTime.h> namespace Tizen { namespace Locations { |