From f52b5366f624919364918f9b0100d41de14e7864 Mon Sep 17 00:00:00 2001 From: Jinkun Jang Date: Sat, 16 Mar 2013 01:16:58 +0900 Subject: [PATCH] merge with master --- CMakeLists.txt | 1 + inc/FLocLocationProvider.h | 24 +- packaging/osp-locations.spec | 2 +- src/FLoc_Config.h | 33 +- src/FLoc_LocationImpl.cpp | 2 - src/FLoc_LocationManager.cpp | 1029 ++++++++++++++++++++++-------------- src/FLoc_LocationManager.h | 70 ++- src/FLoc_LocationProviderImpl.cpp | 396 +++++++++----- src/FLoc_LocationProviderImpl.h | 106 +++- src/FLoc_LocationRequestInfo.h | 2 + src/FLoc_MathUtils.cpp | 29 +- src/FLoc_MathUtils.h | 11 + src/FLoc_SyncLocationRequestInfo.h | 28 +- 13 files changed, 1101 insertions(+), 632 deletions(-) mode change 100755 => 100644 inc/FLocLocationProvider.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 49827e9..9697a40 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,7 @@ INCLUDE_DIRECTORIES ( /usr/include/osp /usr/include/osp/app /usr/include/osp/base + /usr/include/osp/io /usr/include/osp/system /usr/include/osp/security ) diff --git a/inc/FLocLocationProvider.h b/inc/FLocLocationProvider.h old mode 100755 new mode 100644 index 33a6c60..9b88f1b --- a/inc/FLocLocationProvider.h +++ b/inc/FLocLocationProvider.h @@ -114,7 +114,8 @@ public: * the location provider cancels the prior request and restarts the updates with the specified parameter. * * @since 2.0 - * @privilege %http://tizen.org/privilege/location + * @privlevel public + * @privilege http://tizen.org/privilege/location * * @return An error code * @param[in] interval The update interval in seconds @@ -149,7 +150,8 @@ public: * the location provider cancels the prior request and restarts the updates with the specified parameter. * * @since 2.0 - * @privilege %http://tizen.org/privilege/location + * @privlevel public + * @privilege http://tizen.org/privilege/location * * @return An error code * @param[in] distance The distance in meters @@ -188,7 +190,8 @@ public: * during the location updates. * * @since 2.0 - * @privilege %http://tizen.org/privilege/location and %http://tizen.org/privilege/power @n + * @privlevel public + * @privilege http://tizen.org/privilege/location and http://tizen.org/privilege/power @n * Both privileges are required. * * @return An error code @@ -218,7 +221,8 @@ public: * Note that, the monitoring service can sometimes makes the system awake by running costly positioning devices. * * @since 2.0 - * @privilege %http://tizen.org/privilege/location and %http://tizen.org/privilege/power @n + * @privlevel public + * @privilege http://tizen.org/privilege/location and http://tizen.org/privilege/power @n * Both privileges are required. * * @return An error code @@ -303,7 +307,8 @@ public: * an invalid location with an @c E_LOCATION_UNAVAILABLE error. * * @since 2.0 - * @privilege %http://tizen.org/privilege/location + * @privlevel public + * @privilege http://tizen.org/privilege/location * * @return The current location * @param[in] criteria The desired location criteria @@ -313,11 +318,7 @@ public: * @exception E_USER_NOT_CONSENTED The user blocks an application from using the location information. * @exception E_SYSTEM A system error has occurred. * @remarks This method call takes time as the location provider runs and waits for positioning system. - * If the method is called from the application's main thread, it makes the application unresponsive until it returns. - * If an application wants to be responsive, especially within the user interaction, it should use this method - * in a separated thread using Tizen::Base::Runtime::Thread class, - * rather than in the application's main thread which handles the ui events. - * @remarks The specific error code can be accessed using the GetLastResult() method. + * @remarks The specific error code can be accessed using the GetLastResult() method. */ static Location GetLocation(const LocationCriteria& criteria); @@ -329,7 +330,8 @@ public: * since using the last location preserves the location provider from running costly positioning systems. * * @since 2.0 - * @privilege %http://tizen.org/privilege/location + * @privlevel public + * @privilege http://tizen.org/privilege/location * * @return The last location * @exception E_SUCCESS The method is successful. diff --git a/packaging/osp-locations.spec b/packaging/osp-locations.spec index 29333a0..24f9170 100755 --- a/packaging/osp-locations.spec +++ b/packaging/osp-locations.spec @@ -3,7 +3,7 @@ Name: osp-locations Summary: osp locations library -Version: 1.2.0.0 +Version: 1.2.1.0 Release: 2 Group: System/Libraries License: TO_BE/FILLED_IN diff --git a/src/FLoc_Config.h b/src/FLoc_Config.h index 83d336a..819d1a1 100644 --- a/src/FLoc_Config.h +++ b/src/FLoc_Config.h @@ -16,18 +16,23 @@ // /** - * @file FLoc_Config.h - * @brief This header file contains the constants used in the location namespace internally. + * @file FLoc_Config.h + * @brief This header file contains the constants used in the location namespace internally. * - */ - -#ifndef _FLOC_INTERNAL_CONFIG_H_ -#define _FLOC_INTERNAL_CONFIG_H_ - -namespace Tizen { namespace Locations -{ - -const int MAX_WAIT_TIME_FOR_SYNC_LOC = 5; - -}} // Tizen::Locations -#endif //_FLOC_INTERNAL_CONFIG_H_ \ No newline at end of file + */ + +#ifndef _FLOC_INTERNAL_CONFIG_H_ +#define _FLOC_INTERNAL_CONFIG_H_ + +namespace Tizen { namespace Locations +{ + +const int MAX_WAIT_TIME_FOR_SYNC_LOC = 5; +const int MIN_LOCATION_UPDATE_INTERVAL = 1; +const int DEFAULT_WAITING_TIME_FOR_FIXING_LOCATION = 40; +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; + +}} // Tizen::Locations +#endif //_FLOC_INTERNAL_CONFIG_H_ diff --git a/src/FLoc_LocationImpl.cpp b/src/FLoc_LocationImpl.cpp index b072933..56791ed 100644 --- a/src/FLoc_LocationImpl.cpp +++ b/src/FLoc_LocationImpl.cpp @@ -41,8 +41,6 @@ _LocationImpl::_LocationImpl(void) , __horizontalAccuracy(Tizen::Locations::NaN) , __verticalAccuracy(Tizen::Locations::NaN) , __timestamp(0) - , __locationMethod("") - , __satelliteInformation("") , __isLocationValid(false) , __isDenied(false) { diff --git a/src/FLoc_LocationManager.cpp b/src/FLoc_LocationManager.cpp index 6c1002d..cb7d55e 100644 --- a/src/FLoc_LocationManager.cpp +++ b/src/FLoc_LocationManager.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -60,15 +61,8 @@ _LocationManager::_LocationManager(void) , __locMethodRequested(LOC_METHOD_REQUESTED_NONE) , __locationMgrState(LOC_MGR_STATE_IDLE) , __minRequestedAccuracy(LOC_ACCURACY_INVALID) - , __nativeGPSServiceState(LOCATIONS_SERVICE_DISABLED) - , __nativeWPSServiceState(LOCATIONS_SERVICE_DISABLED) - , __nativeCPSServiceState(LOCATIONS_SERVICE_DISABLED) , __timerInterval(0) , __timerTicks(0) - , __gpsHandler(null) - , __wpsHandler(null) - , __cpsHandler(null) - , __pCurrentLocation(null) , __pLocRequestInfoList(null) , __pSyncLocRequestInfoList(null) , __pLocUpdateTimer(null) @@ -145,6 +139,44 @@ _LocationManager::StopLocationUpdates(RequestId reqId) } result +_LocationManager::ChangeUpdateInterval(RequestId reqId, int interval) +{ + SysLog(NID_LOC, "Interval update requested for request ID (%d).", reqId); + + result r = E_SUCCESS; + const int ARRAY_LIST_CAPACITY = 2; + + std::unique_ptr< Tizen::Base::Collection::ArrayList, Tizen::Base::Collection::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)); + + r = pArgList->Construct(ARRAY_LIST_CAPACITY); + SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Array Construct failed. Propogating.", GetErrorMessage(r)); + + 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)); + + 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)); + SysTryReturn(NID_LOC, pInterval, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + + 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; +} + +result _LocationManager::RegisterLocationMonitor(_LocationMonitor* pLocationMonitor) { RequestId reqId; @@ -194,18 +226,18 @@ _LocationManager::GetLastKnownLocation(void) SysTryReturn(NID_LOC, r == E_SUCCESS, location, r, "[%s] Propogating.", GetErrorMessage(r)); r = pArgList->Add(location); - SysTryReturn(NID_LOC, r == E_SUCCESS, location, r, "[%s] Propogating.", GetErrorMessage(r)); + SysTryCatch(NID_LOC, r == E_SUCCESS, , r, "[%s] Propogating", GetErrorMessage(r)); r = pArgList->Add(synchronizer); - SysTryCatch(NID_LOC, r == E_SUCCESS, pArgList->RemoveAll(false), r, "[%s] Propogating", GetErrorMessage(r)); + SysTryCatch(NID_LOC, r == E_SUCCESS, , r, "[%s] Propogating", GetErrorMessage(r)); r = synchronizer.Enter(); - SysTryCatch(NID_LOC, r == E_SUCCESS, pArgList->RemoveAll(false), r, "[%s] Propogating", GetErrorMessage(r)); + SysTryCatch(NID_LOC, r == E_SUCCESS, , r, "[%s] Propogating", GetErrorMessage(r)); r = SendUserEvent(REQ_ID_GET_LAST_LOCATION, pArgList.get()); - SysTryCatch(NID_LOC, r == E_SUCCESS, pArgList->RemoveAll(false); synchronizer.Exit(), r, "[%s] Propogating", GetErrorMessage(r)); + SysTryCatch(NID_LOC, r == E_SUCCESS, synchronizer.Exit(), r, "[%s] Propogating", GetErrorMessage(r)); pArgList.release(); - SysLog(NID_LOC, "Wait the location manager to get the last location."); + SysLog(NID_LOC, "Wait till location manager gets the last location."); r = synchronizer.Wait(); SysTryCatch(NID_LOC, r == E_SUCCESS, synchronizer.Exit(), r, "[%s] Propogating", GetErrorMessage(r)); synchronizer.Exit(); @@ -216,6 +248,7 @@ _LocationManager::GetLastKnownLocation(void) return location; CATCH: + pArgList->RemoveAll(false); return location; } @@ -273,7 +306,7 @@ _LocationManager::IsAppEnabled(void) SysTryCatch(NID_LOC, r == E_SUCCESS, synchronizer.Exit(), r, "[%s] Propogating", GetErrorMessage(r)); pArgList.release(); - SysLog(NID_LOC, "Wait the location manager to check the app is allowed to use location."); + SysLog(NID_LOC, "Wait till location manager checks if the app is allowed to use location."); r = synchronizer.Wait(); SysTryCatch(NID_LOC, r == E_SUCCESS, synchronizer.Exit(), r, "[%s] Propogating", GetErrorMessage(r)); SysLog(NID_LOC, "Application setting state is '%ls'.", enable.ToString().GetPointer()); @@ -347,9 +380,9 @@ _LocationManager::RemoveFromLocRequestInfoList(RequestId reqId) _PowerManagerImpl::PowerControl(1, 0); __pLocUpdateTimer->Cancel(); - location_manager_stop(__gpsHandler); - location_manager_stop(__wpsHandler); - location_manager_stop(__cpsHandler); + location_manager_stop(__gpsHandler.handle); + location_manager_stop(__wpsHandler.handle); + location_manager_stop(__cpsHandler.handle); Reset(); } @@ -364,13 +397,38 @@ void _LocationManager::AddToSyncLocationRequestInfoList(_SyncLocationRequestInfo& syncLocRequestInfo) { result r = E_SUCCESS; - - r = syncLocRequestInfo.StartTimer(*this); - SysTryCatch(NID_LOC, r == E_SUCCESS, , r, "[%s] Failed to start the sync timer.", GetErrorMessage(r)); + static bool hasRetrievalStarted = false; r = __pSyncLocRequestInfoList->Add(syncLocRequestInfo); SysTryCatch(NID_LOC, r == E_SUCCESS, , r, "[%s] Failed to add the sync request into the list.", GetErrorMessage(r)); + if (hasRetrievalStarted == true) + { + SysLog(NID_LOC, "The retrieval under process."); + return; + } + + while (__pSyncLocRequestInfoList->GetCount() != 0) + { + hasRetrievalStarted = true; + const int WAIT_TIME = 1000; + WaitingLoop::GetInstance()->Wait(WAIT_TIME); + + int count = __pSyncLocRequestInfoList->GetCount(); + for (int i = 0; i < count; i++) + { + _SyncLocationRequestInfo* pSyncLocRequestInfo = static_cast< _SyncLocationRequestInfo* >(__pSyncLocRequestInfoList->GetAt(i)); + if (pSyncLocRequestInfo != null) + { + SysLog(NID_LOC, "Handle the sync location request with request ID (%ld)", pSyncLocRequestInfo->GetRequestId()); + + HandleSyncRetrievalTimerExpiry(*pSyncLocRequestInfo); + } + } + } + + hasRetrievalStarted = false; + return; CATCH: @@ -410,25 +468,65 @@ _LocationManager::RestartLocationUpdates(void) SysLog(NID_LOC, "Location updates are restarted and new minimum requested Accuracy is (%d).", __minRequestedAccuracy); - __pLocUpdateTimer->Cancel(); + switch (__locMethodRequested) + { + case LOC_METHOD_REQUESTED_NONE: + { + SysLog(NID_LOC, "None of the methods running. Start all"); + + result = location_manager_start(__gpsHandler.handle); + SysTryLog(NID_LOC, result == 0, "Failed to start the location updates for GPS."); + + result = location_manager_start(__wpsHandler.handle); + SysTryLog(NID_LOC, result == 0, "Failed to start the location updates for WPS."); + + result = location_manager_start(__cpsHandler.handle); + SysTryLog(NID_LOC, result == 0, "Failed to start the location updates for CPS."); + } + break; + + case LOC_METHOD_REQUESTED_GPS: + { + SysLog(NID_LOC, "GPS Running. Start other two."); - location_manager_stop(__gpsHandler); - location_manager_stop(__wpsHandler); - location_manager_stop(__cpsHandler); + result = location_manager_start(__wpsHandler.handle); + SysTryLog(NID_LOC, result == 0, "Failed to start the location updates for WPS."); - __nativeGPSServiceState = LOCATIONS_SERVICE_DISABLED; - __nativeWPSServiceState = LOCATIONS_SERVICE_DISABLED; - __nativeCPSServiceState = LOCATIONS_SERVICE_DISABLED; + result = location_manager_start(__cpsHandler.handle); + SysTryLog(NID_LOC, result == 0, "Failed to start the location updates for CPS."); + } + break; + + case LOC_METHOD_REQUESTED_WPS: + { + SysLog(NID_LOC, "WPS Running. Start other two."); + + result = location_manager_start(__gpsHandler.handle); + SysTryLog(NID_LOC, result == 0, "Failed to start the location updates for GPS."); + + result = location_manager_start(__cpsHandler.handle); + SysTryLog(NID_LOC, result == 0, "Failed to start the location updates for CPS."); + } + break; + case LOC_METHOD_REQUESTED_CPS: + { + SysLog(NID_LOC, "CPS Running. Start other two."); - result = location_manager_start(__gpsHandler); - SysTryLog(NID_LOC, result == 0, "Failed to start the location updates for GPS."); + result = location_manager_start(__gpsHandler.handle); + SysTryLog(NID_LOC, result == 0, "Failed to start the location updates for GPS."); - result = location_manager_start(__wpsHandler); - SysTryLog(NID_LOC, result == 0, "Failed to start the location updates for WPS."); + result = location_manager_start(__wpsHandler.handle); + SysTryLog(NID_LOC, result == 0, "Failed to start the location updates for WPS."); + } + break; - result = location_manager_start(__cpsHandler); - SysTryLog(NID_LOC, result == 0, "Failed to start the location updates for CPS."); + case LOC_METHOD_REQUESTED_ALL: + { + SysLog(NID_LOC, "All the providers are already started."); + } + break; + } __locationMgrState = LOC_MGR_STATE_FAST_SENSING; __locMethodRequested = LOC_METHOD_REQUESTED_ALL; @@ -442,6 +540,8 @@ _LocationManager::RestartUpdateTimer(void) int count = __pLocRequestInfoList->GetCount(); result r = E_SUCCESS; + __pLocUpdateTimer->Cancel(); + if (count > 0) { const _LocationRequestInfo* pLocRequestInfo = static_cast< _LocationRequestInfo* >(__pLocRequestInfoList->GetAt(0)); @@ -523,7 +623,7 @@ _LocationManager::HandleSyncRetrievalTimerExpiry(_SyncLocationRequestInfo& syncL } SysLog(NID_LOC, "Wait for next location(Tick: %d).", syncLocRequestInfo.GetTickCount()); - syncLocRequestInfo.StartTimer(*this); + syncLocRequestInfo.IncrementTickCount(); return; NOTIFY: @@ -532,7 +632,7 @@ NOTIFY: } result -_LocationManager::SetLocationInformation(double latitude, double longitude, double altitude, time_t timestamp, location_method_e locMethod) +_LocationManager::SetLocationInformation(double latitude, double longitude, double altitude, time_t timestamp, location_method_e locMethod, Location* pLocation) { SysLog(NID_LOC, "Location Information is: Latitude (%lf), Longitude (%lf), Altitude (%lf), TimeStamp (%ld), Location method (%d)", latitude, longitude, altitude, timestamp, locMethod); @@ -560,11 +660,11 @@ _LocationManager::SetLocationInformation(double latitude, double longitude, doub { case LOCATIONS_METHOD_GPS: { - res = location_manager_get_accuracy(__gpsHandler, &accLevel, &horAcc, &verAcc); + 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, &climb, &direction, &speed, &time_stamp); + 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."); @@ -575,11 +675,11 @@ _LocationManager::SetLocationInformation(double latitude, double longitude, doub case LOCATIONS_METHOD_WPS: { - res = location_manager_get_accuracy(__wpsHandler, &accLevel, &horAcc, &verAcc); + 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, &climb, &direction, &speed, &time_stamp); + 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"); @@ -589,7 +689,7 @@ _LocationManager::SetLocationInformation(double latitude, double longitude, doub case LOCATIONS_METHOD_CPS: { - res = location_manager_get_accuracy(__cpsHandler, &accLevel, &horAcc, &verAcc); + res = location_manager_get_accuracy(__cpsHandler.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."); @@ -612,7 +712,7 @@ _LocationManager::SetLocationInformation(double latitude, double longitude, doub pLocDataImpl->SetCourse(direction); pLocDataImpl->SetSpeed(speed); pLocDataImpl->SetValidity(true); - *__pCurrentLocation = locationData; + *pLocation = locationData; requiredAcc = __minRequestedAccuracy; switch (requiredAcc) @@ -662,9 +762,10 @@ void _LocationManager::SendLocationCallbacks(void) { bool isAllowed = GetAppAccessibility(); - SysLog(NID_LOC, "Send location(validity: %x) and accessibility(%x) through the callback.", __pCurrentLocation->IsValid(), isAllowed); + const Location* pBestLocation = FindBestLocation(); - unique_ptr< Location > pLocation(new (std::nothrow) Location(*__pCurrentLocation)); + SysLog(NID_LOC, "Send location(validity: %x) and accessibility(%x) through the callback.", pBestLocation->IsValid(), isAllowed); + unique_ptr< Location > pLocation(new (std::nothrow) Location(*pBestLocation)); SysTryReturnVoidResult(NID_LOC, pLocation != null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); int interval = __timerTicks * __timerInterval; @@ -690,9 +791,6 @@ _LocationManager::Reset(void) __minRequestedAccuracy = LOC_ACCURACY_INVALID; __timerInterval = 0; __timerTicks = 0; - __nativeGPSServiceState = LOCATIONS_SERVICE_DISABLED; - __nativeWPSServiceState = LOCATIONS_SERVICE_DISABLED; - __nativeCPSServiceState = LOCATIONS_SERVICE_DISABLED; } result @@ -701,131 +799,474 @@ _LocationManager::Construct() return EventDrivenThread::Construct(); } -bool -_LocationManager::OnStart(void) +Location +_LocationManager::GetLastKnownLocation(location_method_e nativeLocMethod) { - int res = -1; - result r = E_SUCCESS; - - unique_ptr< Mutex > pMutex(new (std::nothrow) Mutex()); - SysTryReturn(NID_LOC, pMutex != null, false, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); - - r = pMutex->Create(); - SysTryReturn(NID_LOC, r == E_SUCCESS, false, E_SYSTEM, "[E_SYSTEM] Failed to construct the mutex."); - - std::unique_ptr< Tizen::Base::Collection::ArrayList, AllElementsDeleter > pLocInfoRequestList(new (std::nothrow) ArrayList()); - SysTryReturn(NID_LOC, pLocInfoRequestList != null, false, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); - - r = pLocInfoRequestList->Construct(); - SysTryReturn(NID_LOC, r == E_SUCCESS, false, E_SYSTEM, "[E_SYSTEM] Failed to construct the Location Request list."); + String locationMethod; + location_manager_h nativeHandle = null; + switch (nativeLocMethod) + { + case LOCATIONS_METHOD_GPS: + nativeHandle = __gpsHandler.handle; + locationMethod = L"gps"; + break; + case LOCATIONS_METHOD_WPS: + nativeHandle = __wpsHandler.handle; + locationMethod = L"network"; + break; + case LOCATIONS_METHOD_CPS: + nativeHandle = __cpsHandler.handle; + locationMethod = L"network"; + break; + default: + break; + } + SysLog(NID_LOC, "Last location requested(method: %x, handle: %x).", nativeLocMethod, nativeHandle); - std::unique_ptr< Tizen::Base::Collection::ArrayList, AllElementsDeleter > pSyncLocInfoRequestList(new (std::nothrow) ArrayList()); - SysTryReturn(NID_LOC, pSyncLocInfoRequestList != null, false, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + Location location = _LocationImpl::GetLocationInstance(); + if (nativeHandle != null) + { + _LocationImpl* pLocationImpl = _LocationImpl::GetInstance(location); - r = pSyncLocInfoRequestList->Construct(); - SysTryReturn(NID_LOC, r == E_SUCCESS, false, E_SYSTEM, "[E_SYSTEM] Failed to construct the Sync Location Request list."); + double altitude = Tizen::Locations::NaN; + double latitude = Tizen::Locations::NaN; + double longitude = Tizen::Locations::NaN; + time_t timestampPosition = 0; - unique_ptr< Tizen::Locations::Location > pLocation(_LocationImpl::GetLocationInstanceN()); - SysTryReturn(NID_LOC, pLocation != null, false, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + int res = location_manager_get_last_position(nativeHandle, &altitude, &latitude, &longitude, ×tampPosition); + SysTryCatch(NID_LOC, res == 0, , E_SYSTEM, "[E_SYSTEM] Failed to fetch last position from nativeHandle(%x).", nativeHandle); + SysLog(NID_LOC, "Last position(latitude: %lf, longitude: %lf, altitude: %lf, timestamp: %ld", + latitude, longitude, altitude, timestampPosition); - std::unique_ptr< Tizen::Base::Runtime::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."); + Coordinates coord; + coord.Set(latitude, longitude, altitude); + pLocationImpl->SetCoordinates(coord); - res = location_manager_create(LOCATIONS_METHOD_GPS, &__gpsHandler); - SysTryReturn(NID_LOC, res == 0, false, E_SYSTEM, "[E_SYSTEM] Failed to create Native GPS Location provider."); + double horAcc = Tizen::Locations::NaN; + double verAcc = Tizen::Locations::NaN; + location_accuracy_level_e level; + res = location_manager_get_last_accuracy(nativeHandle, &level, &horAcc, &verAcc); + if (res == 0) + { + SysLog(NID_LOC, "Last accuracy(horAcc: %lf, vAcc: %lf, level: %x)", horAcc, verAcc, level); + pLocationImpl->SetHorizontalAccuracy(horAcc); + pLocationImpl->SetVerticalAccuracy(verAcc); + } - res = location_manager_set_service_state_changed_cb(__gpsHandler, GpsServiceUpdateCallback, this); - SysTryCatch(NID_LOC, res == 0, , E_SYSTEM, "[E_SYSTEM] Failed to register service callback for Native GPS Location provider."); + double climb = Tizen::Locations::NaN; + double direction = Tizen::Locations::NaN; + double speed = Tizen::Locations::NaN; + time_t timestampVelocity = 0; + 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); + pLocationImpl->SetCourse(direction); + pLocationImpl->SetSpeed(speed); + } - res = location_manager_create(LOCATIONS_METHOD_WPS, &__wpsHandler); - SysTryCatch(NID_LOC, res == 0, , E_SYSTEM, "[E_SYSTEM] Failed to create Native WPS Location provider."); + if (nativeLocMethod == LOCATIONS_METHOD_GPS) + { + int satUsedCount = 0; + int satViewCount = 0; + time_t timestampSatellite = 0; + String satInfo = L""; + res = gps_status_get_last_satellite(nativeHandle, &satUsedCount, &satViewCount, ×tampSatellite); + if (res == 0) + { + long timeDiff = 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); - res = location_manager_set_service_state_changed_cb(__wpsHandler, WpsServiceUpdateCallback, this); - SysTryCatch(NID_LOC, res == 0, , E_SYSTEM, "[E_SYSTEM] Failed to register service callback for Native WPS Location provider."); + satInfo.Trim(); + SysLog(NID_LOC, "Last satellite(info: %ls)", satInfo.GetPointer()); + pLocationImpl->SetExtraInfo(L"satellite", satInfo); + } + } - res = location_manager_create(LOCATIONS_METHOD_CPS, &__cpsHandler); - SysTryCatch(NID_LOC, res == 0, , E_SYSTEM, "[E_SYSTEM] Failed to create Native CPS Location provider."); + pLocationImpl->SetTimestamp(((long long)timestampPosition) * 1000); // in milliseconds + pLocationImpl->SetValidity(true); + pLocationImpl->SetExtraInfo(L"location_method", locationMethod); + } - res = location_manager_set_service_state_changed_cb(__cpsHandler, CpsServiceUpdateCallback, this); - SysTryCatch(NID_LOC, res == 0, , E_SYSTEM, "[E_SYSTEM] Failed to register service callback for Native CPS Location provider."); + ClearLastResult(); + return location; - __pLocRequestInfoList = std::move(pLocInfoRequestList); - __pSyncLocRequestInfoList = std::move(pSyncLocInfoRequestList); - __pLocUpdateTimer = std::move(pLocUpdateTimer); - __pCurrentLocation = std::move(pLocation); +CATCH: + return location; +} - return true; +Location +_LocationManager::GetRecentLocationAvailable(void) +{ + long long gpsTimestamp = 0; + long long wpsTimestamp = 0; + long long cpsTimestamp = 0; -CATCH: - if (__gpsHandler) + Location lastGpsLocation = GetLastKnownLocation(LOCATIONS_METHOD_GPS); + if (lastGpsLocation.IsValid()) { - location_manager_destroy(__gpsHandler); + gpsTimestamp = _LocationImpl::GetInstance(lastGpsLocation)->GetTimestampInMs(); } - if (__wpsHandler) + Location lastWpsLocation = GetLastKnownLocation(LOCATIONS_METHOD_WPS); + if (lastWpsLocation.IsValid()) { - location_manager_destroy(__wpsHandler); + wpsTimestamp = _LocationImpl::GetInstance(lastWpsLocation)->GetTimestampInMs(); } - if (__cpsHandler) + Location lastCpsLocation = GetLastKnownLocation(LOCATIONS_METHOD_CPS); + if (lastCpsLocation.IsValid()) { - location_manager_destroy(__cpsHandler); + cpsTimestamp = _LocationImpl::GetInstance(lastCpsLocation)->GetTimestampInMs(); } - return false; -} -void -_LocationManager::OnStop(void) -{ - if (__gpsHandler) + SysLog(NID_LOC, "Compare timestamp(gps: %lld, wps: %lld, cps: %lld) for recent location.", + gpsTimestamp, wpsTimestamp, cpsTimestamp); + + if (gpsTimestamp >= wpsTimestamp && gpsTimestamp >= cpsTimestamp) { - location_manager_destroy(__gpsHandler); + return lastGpsLocation; } - - if (__wpsHandler) + else if (wpsTimestamp > gpsTimestamp && wpsTimestamp > cpsTimestamp) { - location_manager_destroy(__wpsHandler); + return lastWpsLocation; } - - if (__cpsHandler) + else { - location_manager_destroy(__cpsHandler); + return lastCpsLocation; } } -void -_LocationManager::OnUserEventReceivedN(RequestId requestId, IList* pArgs) +void +_LocationManager::UpdateLocRequestInfoList(RequestId reqId, int interval) { - const int ARRAY_LIST_CAPACITY = 1; + int count = __pLocRequestInfoList->GetCount(); - switch (requestId) - { - case REQ_ID_START_LOC_UPDATES: + for (int i = 0; i < count; i++) { - SysLog(NID_LOC, "REQ_ID_START_LOC_UPDATES"); - SysTryReturnVoidResult(NID_LOC, pArgs, E_INVALID_ARG, "[E_INVALID_ARG] Null argument encountered. Ignored."); - _LocationRequestInfo* pLocRequestInfo = null; - SysTryCatch(NID_LOC, pArgs->GetCount() == ARRAY_LIST_CAPACITY, pArgs->RemoveAll(true), E_INVALID_ARG, "[E_INVALID_ARG] Invalid argument encountered. Ignored."); - pLocRequestInfo = static_cast< _LocationRequestInfo* >(pArgs->GetAt(0)); - SysTryCatch(NID_LOC, pLocRequestInfo, , E_INVALID_ARG, "[E_INVALID_ARG] Invalid argument encountered. Ignored."); - - AddToLocRequestInfoList(pLocRequestInfo); + _LocationRequestInfo* pLocRequestInfo = static_cast< _LocationRequestInfo* >(__pLocRequestInfoList->GetAt(i)); + if (reqId == pLocRequestInfo->GetRequestId()) + { + pLocRequestInfo->SetInterval(interval); + RestartUpdateTimer(); + break; + } } - break; +} - case REQ_ID_STOP_LOC_UPDATES: +const Location* +_LocationManager::FindBestLocation(void) +{ + switch (__locMethodRequested) { - SysLog(NID_LOC, "REQ_ID_STOP_LOC_UPDATES"); - SysTryReturnVoidResult(NID_LOC, pArgs, E_INVALID_ARG, "[E_INVALID_ARG] Null argument encountered. Ignored."); - Integer* pReqId = null; - SysTryCatch(NID_LOC, pArgs->GetCount() == ARRAY_LIST_CAPACITY, pArgs->RemoveAll(true), E_INVALID_ARG, "[E_INVALID_ARG] Invalid argument encountered. Ignored."); - pReqId = static_cast< Integer* >(pArgs->GetAt(0)); - SysTryCatch(NID_LOC, pReqId, , E_INVALID_ARG, "[E_INVALID_ARG] Invalid argument encountered. Ignored."); + case LOC_METHOD_REQUESTED_GPS: + SysLog(NID_LOC, "GPS location provider running."); + return __gpsHandler.pLocation.get(); + break; - RemoveFromLocRequestInfoList(static_cast< long >(pReqId->ToInt())); - } - break; + case LOC_METHOD_REQUESTED_WPS: + SysLog(NID_LOC, "WPS location provider running."); + return __wpsHandler.pLocation.get(); + break; + + case LOC_METHOD_REQUESTED_CPS: + SysLog(NID_LOC, "CPS location provider running."); + return __cpsHandler.pLocation.get(); + break; + + case LOC_METHOD_REQUESTED_ALL: + { + SysLog(NID_LOC, "All the methods are running. Get the best location among all the providers."); + + long long gpsTimestamp = 0; + long long wpsTimestamp = 0; + long long cpsTimestamp = 0; + + if (__gpsHandler.pLocation->IsValid() && !_LocationImpl::GetInstance(*__gpsHandler.pLocation)->IsDenied()) + { + gpsTimestamp = _LocationImpl::GetInstance(*__gpsHandler.pLocation)->GetTimestampInMs(); + } + if (__wpsHandler.pLocation->IsValid() && !_LocationImpl::GetInstance(*__wpsHandler.pLocation)->IsDenied()) + { + wpsTimestamp = _LocationImpl::GetInstance(*__wpsHandler.pLocation)->GetTimestampInMs(); + } + if (__cpsHandler.pLocation->IsValid() && !_LocationImpl::GetInstance(*__cpsHandler.pLocation)->IsDenied()) + { + cpsTimestamp = _LocationImpl::GetInstance(*__cpsHandler.pLocation)->GetTimestampInMs(); + } + + SysLog(NID_LOC, "Compare timestamp(gps: %lld, wps: %lld, cps: %lld) of different locations.", gpsTimestamp, wpsTimestamp, cpsTimestamp); + + if (gpsTimestamp > wpsTimestamp && gpsTimestamp > cpsTimestamp) + { + SysLog(NID_LOC, "GPS time stamp is greater than WPS and CPS."); + return __gpsHandler.pLocation.get(); + } + else if (wpsTimestamp > gpsTimestamp && wpsTimestamp > cpsTimestamp) + { + SysLog(NID_LOC, "WPS time stamp is greater than GPS and CPS."); + return __wpsHandler.pLocation.get(); + } + else if (cpsTimestamp > gpsTimestamp && cpsTimestamp > wpsTimestamp) + { + SysLog(NID_LOC, "CPS time stamp is greater than GPS and WPS."); + return __cpsHandler.pLocation.get(); + } + else if (gpsTimestamp == wpsTimestamp) + { + if (__gpsHandler.pLocation->GetHorizontalAccuracy() <= __wpsHandler.pLocation->GetHorizontalAccuracy()) + { + SysLog(NID_LOC, "GPS time stamp is equal to WPS and GPS accuracy is better than WPS."); + return __gpsHandler.pLocation.get(); + } + else + { + SysLog(NID_LOC, "GPS time stamp is equal to WPS but GPS accuracy is worse than WPS."); + return __wpsHandler.pLocation.get(); + } + } + else if (gpsTimestamp == cpsTimestamp) + { + if (__gpsHandler.pLocation->GetHorizontalAccuracy() <= __cpsHandler.pLocation->GetHorizontalAccuracy()) + { + SysLog(NID_LOC, "GPS time stamp is equal to CPS and GPS accuracy is better than CPS."); + return __gpsHandler.pLocation.get(); + } + else + { + SysLog(NID_LOC, "GPS time stamp is equal to CPS but GPS accuracy is worse than CPS."); + return __cpsHandler.pLocation.get(); + } + } + else if (wpsTimestamp == cpsTimestamp) + { + if (__wpsHandler.pLocation->GetHorizontalAccuracy() <= __cpsHandler.pLocation->GetHorizontalAccuracy()) + { + SysLog(NID_LOC, "WPS time stamp is equal to CPS and WPS accuracy is better than CPS."); + return __wpsHandler.pLocation.get(); + } + else + { + SysLog(NID_LOC, "WPS time stamp is equal to CPS but WPS accuracy is worse than CPS."); + return __cpsHandler.pLocation.get(); + } + } + } + break; + + case LOC_METHOD_REQUESTED_NONE: + // follow through + default: + SysLog(NID_LOC, "Location updates not running."); + return null; + } + + SysLog(NID_LOC, "Returning null as none of the conditions are satsfied."); + return null; +} + +result +_LocationManager::GetLocation(location_method_e nativeLocMethod) +{ + const int MAX_VALID_TIME_DIFFERENCE = 2000; + result r = E_SUCCESS; + double altitude = 0.0; + double latitude = 0.0; + double longitude = 0.0; + time_t timestamp; + int res = -1; + int satellitesInViewCount = 0; + int satellitesInUseCount = 0; + time_t timestampSatellite = 0; + String satInfo = L""; + long long timeDiff = 0; + location_manager_h nativeHandle = null; + Location* pLocation = null; + + switch (nativeLocMethod) + { + case LOCATIONS_METHOD_GPS: + nativeHandle = __gpsHandler.handle; + pLocation = __gpsHandler.pLocation.get(); + break; + case LOCATIONS_METHOD_WPS: + nativeHandle = __wpsHandler.handle; + pLocation = __wpsHandler.pLocation.get(); + break; + case LOCATIONS_METHOD_CPS: + nativeHandle = __cpsHandler.handle; + pLocation = __cpsHandler.pLocation.get(); + break; + default: + break; + } + + res = location_manager_get_position(nativeHandle, &altitude, &latitude, &longitude, ×tamp); + SysTryReturnResult(NID_LOC, res == 0, E_SYSTEM, "[E_SYSTEM] Failed to obtain the natvie location information for the method (%x)", nativeLocMethod); + + if (res == 0) + { + r = SetLocationInformation(latitude, longitude, altitude, timestamp, nativeLocMethod, pLocation); + if (r != E_SUCCESS) + { + SysLog(NID_LOC, "Failed to set the location information"); + } + + if (nativeLocMethod == LOCATIONS_METHOD_GPS) + { + res = gps_status_get_satellite(__gpsHandler.handle, &satellitesInUseCount, &satellitesInViewCount, ×tampSatellite); + + timeDiff = 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); + } + + 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); + } + } + + return E_SUCCESS; +} + +bool +_LocationManager::OnStart(void) +{ + int res = -1; + result r = E_SUCCESS; + + std::unique_ptr< Tizen::Base::Collection::ArrayList, AllElementsDeleter > pLocInfoRequestList(new (std::nothrow) ArrayList()); + SysTryReturn(NID_LOC, pLocInfoRequestList != null, false, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + + 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()); + 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."); + + unique_ptr< Tizen::Locations::Location > pGpsLocation(_LocationImpl::GetLocationInstanceN()); + SysTryReturn(NID_LOC, pGpsLocation != null, false, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + + 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)); + + unique_ptr< Tizen::Locations::Location > pCpsLocation(_LocationImpl::GetLocationInstanceN()); + SysTryReturn(NID_LOC, pCpsLocation != 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()); + 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); + 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); + 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); + SysTryCatch(NID_LOC, res == 0, , E_SYSTEM, "[E_SYSTEM] Failed to register service callback for Native WPS Location provider."); + + res = location_manager_create(LOCATIONS_METHOD_CPS, &__cpsHandler.handle); + SysTryCatch(NID_LOC, res == 0, , E_SYSTEM, "[E_SYSTEM] Failed to create Native CPS Location provider."); + + res = location_manager_set_service_state_changed_cb(__cpsHandler.handle, CpsServiceUpdateCallback, this); + SysTryCatch(NID_LOC, res == 0, , E_SYSTEM, "[E_SYSTEM] Failed to register service callback for Native CPS Location provider."); + + __pLocRequestInfoList = std::move(pLocInfoRequestList); + __pSyncLocRequestInfoList = std::move(pSyncLocInfoRequestList); + __pLocUpdateTimer = std::move(pLocUpdateTimer); + __gpsHandler.pLocation= std::move(pGpsLocation); + __wpsHandler.pLocation= std::move(pWpsLocation); + __cpsHandler.pLocation= std::move(pCpsLocation); + + SysLog(NID_LOC, "All the resources for location manager successfully created."); + + return true; + +CATCH: + if (__gpsHandler.handle) + { + location_manager_destroy(__gpsHandler.handle); + } + + if (__wpsHandler.handle) + { + location_manager_destroy(__wpsHandler.handle); + } + + if (__cpsHandler.handle) + { + location_manager_destroy(__cpsHandler.handle); + } + return false; +} + +void +_LocationManager::OnStop(void) +{ + if (__gpsHandler.handle) + { + location_manager_destroy(__gpsHandler.handle); + } + + if (__wpsHandler.handle) + { + location_manager_destroy(__wpsHandler.handle); + } + + if (__cpsHandler.handle) + { + location_manager_destroy(__cpsHandler.handle); + } +} + +void +_LocationManager::OnUserEventReceivedN(RequestId requestId, IList* pArgs) +{ + const int ARRAY_LIST_CAPACITY = 1; + + switch (requestId) + { + case REQ_ID_START_LOC_UPDATES: + { + SysLog(NID_LOC, "REQ_ID_START_LOC_UPDATES"); + SysTryReturnVoidResult(NID_LOC, pArgs, E_INVALID_ARG, "[E_INVALID_ARG] Null argument encountered. Ignored."); + _LocationRequestInfo* pLocRequestInfo = null; + SysTryCatch(NID_LOC, pArgs->GetCount() == ARRAY_LIST_CAPACITY, pArgs->RemoveAll(true), E_INVALID_ARG, "[E_INVALID_ARG] Invalid argument encountered. Ignored."); + pLocRequestInfo = static_cast< _LocationRequestInfo* >(pArgs->GetAt(0)); + SysTryCatch(NID_LOC, pLocRequestInfo, , E_INVALID_ARG, "[E_INVALID_ARG] Invalid argument encountered. Ignored."); + + AddToLocRequestInfoList(pLocRequestInfo); + } + break; + + case REQ_ID_STOP_LOC_UPDATES: + { + SysLog(NID_LOC, "REQ_ID_STOP_LOC_UPDATES"); + SysTryReturnVoidResult(NID_LOC, pArgs, E_INVALID_ARG, "[E_INVALID_ARG] Null argument encountered. Ignored."); + Integer* pReqId = null; + SysTryCatch(NID_LOC, pArgs->GetCount() == ARRAY_LIST_CAPACITY, pArgs->RemoveAll(true), E_INVALID_ARG, "[E_INVALID_ARG] Invalid argument encountered. Ignored."); + pReqId = static_cast< Integer* >(pArgs->GetAt(0)); + SysTryCatch(NID_LOC, pReqId, , E_INVALID_ARG, "[E_INVALID_ARG] Invalid argument encountered. Ignored."); + + RemoveFromLocRequestInfoList(static_cast< long >(pReqId->ToInt())); + } + break; case REQ_ID_RESTART_LOC_UPDATES: { @@ -837,8 +1278,8 @@ _LocationManager::OnUserEventReceivedN(RequestId requestId, IList* pArgs) case REQ_ID_SUSTAIN_GPS: { SysLog(NID_LOC, "REQ_ID_SUSTAIN_GPS."); - location_manager_stop(__wpsHandler); - location_manager_stop(__cpsHandler); + location_manager_stop(__wpsHandler.handle); + location_manager_stop(__cpsHandler.handle); __locMethodRequested = LOC_METHOD_REQUESTED_GPS; } break; @@ -846,8 +1287,8 @@ _LocationManager::OnUserEventReceivedN(RequestId requestId, IList* pArgs) case REQ_ID_SUSTAIN_WPS: { SysLog(NID_LOC, "REQ_ID_SUSTAIN_WPS."); - location_manager_stop(__gpsHandler); - location_manager_stop(__cpsHandler); + location_manager_stop(__gpsHandler.handle); + location_manager_stop(__cpsHandler.handle); __locMethodRequested = LOC_METHOD_REQUESTED_WPS; } break; @@ -855,8 +1296,8 @@ _LocationManager::OnUserEventReceivedN(RequestId requestId, IList* pArgs) case REQ_ID_SUSTAIN_CPS: { SysLog(NID_LOC, "REQ_ID_SUSTAIN_CPS."); - location_manager_stop(__gpsHandler); - location_manager_stop(__wpsHandler); + location_manager_stop(__gpsHandler.handle); + location_manager_stop(__wpsHandler.handle); __locMethodRequested = LOC_METHOD_REQUESTED_CPS; } break; @@ -921,6 +1362,27 @@ _LocationManager::OnUserEventReceivedN(RequestId requestId, IList* pArgs) pArgs->RemoveAt(0); } break; + + case REQ_ID_UPDATE_INTERVAL: + { + const int ARRAY_LIST_LENGTH = 2; + + SysLog(NID_LOC, "REQ_ID_UPDATE_INTERVAL"); + SysTryReturnVoidResult(NID_LOC, pArgs, E_INVALID_ARG, "[E_INVALID_ARG] Null argument encountered. Ignored."); + SysTryCatch(NID_LOC, pArgs->GetCount() == ARRAY_LIST_LENGTH, pArgs->RemoveAll(true), E_INVALID_ARG, "[E_INVALID_ARG] Invalid argument encountered. Ignored."); + + Integer* pReqId = null; + pReqId = static_cast< Integer* >(pArgs->GetAt(0)); + SysTryCatch(NID_LOC, pReqId, , E_INVALID_ARG, "[E_INVALID_ARG] Invalid argument encountered. Ignored."); + + Integer* pInterval = null; + 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()); + } + break; + } if (pArgs) @@ -939,159 +1401,69 @@ CATCH: void _LocationManager::OnTimerExpired(Tizen::Base::Runtime::Timer& timer) { - const int MAX_VALID_TIME_DIFFERENCE = 2000; - if (__pLocUpdateTimer->Equals(timer)) { __timerTicks++; SysLog(NID_LOC, "LocationManager update timer expired. Timer Tick value is (%d).", __timerTicks); result r = E_SUCCESS; - double altitude = 0.0; - double latitude = 0.0; - double longitude = 0.0; - time_t timestamp; - - int res = -1; - int satellitesInViewCount = 0; - int satellitesInUseCount = 0; - time_t timestampSatellite = 0; - String satInfo = L""; - long long timeDiff = 0; switch (__locMethodRequested) { case LOC_METHOD_REQUESTED_GPS: - res = location_manager_get_position(__gpsHandler, &altitude, &latitude, &longitude, ×tamp); - SysTryLog(NID_LOC, res == 0, "[E_SYSTEM] Failed to obtain the GPS location information"); + r = GetLocation(LOCATIONS_METHOD_GPS); + SysTryLog(NID_LOC, r == E_SUCCESS, "[E_SYSTEM] Failed to obtain the GPS location information"); - if (res == 0) - { - r = SetLocationInformation(latitude, longitude, altitude, timestamp, LOCATIONS_METHOD_GPS); - if (r != E_SUCCESS) - { - SysLog(NID_LOC, "Failed to set the location information"); - } - - res = gps_status_get_satellite(__gpsHandler, &satellitesInUseCount, &satellitesInViewCount, ×tampSatellite); - - timeDiff = 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, SatelliteInfoUpdated, &satInfo); - } - SysLog(NID_LOC, "Result of get satellite is (%d) and satelliteInfo string representation is (%ls)", res, satInfo.GetPointer()); - - _LocationImpl::GetInstance(*__pCurrentLocation.get())->SetExtraInfo(L"satellite", satInfo); - } - else + if (IsFailed(r)) { SendUserEvent(REQ_ID_RESTART_LOC_UPDATES, null); - return; } break; case LOC_METHOD_REQUESTED_WPS: - res = location_manager_get_position(__wpsHandler, &altitude, &latitude, &longitude, ×tamp); - SysTryLog(NID_LOC, res == 0, "[E_SYSTEM] Failed to obtain the WPS location information"); - if (res == 0) - { - r = SetLocationInformation(latitude, longitude, altitude, timestamp, LOCATIONS_METHOD_WPS); - if (r != E_SUCCESS) - { - SysLog(NID_LOC, "Failed to set the location information"); - } - } - else + r = GetLocation(LOCATIONS_METHOD_WPS); + SysTryLog(NID_LOC, r == E_SUCCESS, "[E_SYSTEM] Failed to obtain the WPS location information"); + + if (IsFailed(r)) { SendUserEvent(REQ_ID_RESTART_LOC_UPDATES, null); - return; } break; case LOC_METHOD_REQUESTED_CPS: - res = location_manager_get_position(__cpsHandler, &altitude, &latitude, &longitude, ×tamp); - SysTryLog(NID_LOC, res == 0, "[E_SYSTEM] Failed to obtain the CPS location information"); - if (res == 0) - { - r = SetLocationInformation(latitude, longitude, altitude, timestamp, LOCATIONS_METHOD_CPS); - if (r != E_SUCCESS) - { - SysLog(NID_LOC, "Failed to set the location information"); - } - } - else + r = GetLocation(LOCATIONS_METHOD_CPS); + SysTryLog(NID_LOC, r == E_SUCCESS, "[E_SYSTEM] Failed to obtain the CPS location information"); + + if (IsFailed(r)) { SendUserEvent(REQ_ID_RESTART_LOC_UPDATES, null); - return; } break; case LOC_METHOD_REQUESTED_ALL: - if (__nativeCPSServiceState == LOCATIONS_SERVICE_ENABLED) + if (__cpsHandler.serviceState == LOCATIONS_SERVICE_ENABLED) { - res = location_manager_get_position(__cpsHandler, &altitude, &latitude, &longitude, ×tamp); - SysTryLog(NID_LOC, res == 0, "[E_SYSTEM] Failed to obtain the CPS location information"); - if (res == 0) - { - r = SetLocationInformation(latitude, longitude, altitude, timestamp, LOCATIONS_METHOD_CPS); - if (r != E_SUCCESS) - { - SysLog(NID_LOC, "Failed to set the location information"); - } - } + r = GetLocation(LOCATIONS_METHOD_CPS); + SysTryLog(NID_LOC, r == E_SUCCESS, "[E_SYSTEM] Failed to obtain the CPS location information"); } else { SysLog(NID_LOC, "CPS Location not available at the Native side."); } - if (__nativeWPSServiceState == LOCATIONS_SERVICE_ENABLED) + if (__wpsHandler.serviceState == LOCATIONS_SERVICE_ENABLED) { - res = location_manager_get_position(__wpsHandler, &altitude, &latitude, &longitude, ×tamp); - SysTryLog(NID_LOC, res == 0, "[E_SYSTEM] Failed to obtain the WPS location information"); - if (res == 0) - { - r = SetLocationInformation(latitude, longitude, altitude, timestamp, LOCATIONS_METHOD_WPS); - if (r != E_SUCCESS) - { - SysLog(NID_LOC, "Failed to set the location information"); - } - } + 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 Location not available at the Native side."); } - if (__nativeGPSServiceState == LOCATIONS_SERVICE_ENABLED) + if (__gpsHandler.serviceState == LOCATIONS_SERVICE_ENABLED) { - res = location_manager_get_position(__gpsHandler, &altitude, &latitude, &longitude, ×tamp); - SysTryLog(NID_LOC, res == 0, "[E_SYSTEM] Failed to obtain the GPS location information"); - if (res == 0) - { - r = SetLocationInformation(latitude, longitude, altitude, timestamp, LOCATIONS_METHOD_GPS); - if (r != E_SUCCESS) - { - SysLog(NID_LOC, "Failed to set the location information"); - } - - res = gps_status_get_satellite(__gpsHandler, &satellitesInUseCount, &satellitesInViewCount, ×tampSatellite); - - timeDiff = 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, SatelliteInfoUpdated, &satInfo); - } - SysLog(NID_LOC, "Result of get satellite is (%d) and satelliteInfo string representation is (%ls)", res, satInfo.GetPointer()); - - _LocationImpl::GetInstance(*__pCurrentLocation.get())->SetExtraInfo(L"satellite", satInfo); - } + r = GetLocation(LOCATIONS_METHOD_GPS); + SysTryLog(NID_LOC, r == E_SUCCESS, "[E_SYSTEM] Failed to obtain the GPS location information"); } else { @@ -1109,21 +1481,6 @@ _LocationManager::OnTimerExpired(Tizen::Base::Runtime::Timer& timer) __pLocUpdateTimer->Start(__timerInterval * 1000); SendLocationCallbacks(); } - else - { - int count = __pSyncLocRequestInfoList->GetCount(); - for (int i = 0; i < count; i++) - { - _SyncLocationRequestInfo* pSyncLocRequestInfo = static_cast< _SyncLocationRequestInfo* >(__pSyncLocRequestInfoList->GetAt(i)); - if (pSyncLocRequestInfo != null && pSyncLocRequestInfo->Equals(timer)) - { - SysLog(NID_LOC, "Timer expired for the sync location request with request ID (%ld)", pSyncLocRequestInfo->GetRequestId()); - - HandleSyncRetrievalTimerExpiry(*pSyncLocRequestInfo); - break; - } - } - } return; } @@ -1167,7 +1524,7 @@ _LocationManager::GpsServiceUpdateCallback(location_service_state_e state, void* } _LocationManager* pThis = static_cast< _LocationManager* >(user_data); - pThis->__nativeGPSServiceState = state; + pThis->__gpsHandler.serviceState = state; } void @@ -1181,7 +1538,7 @@ _LocationManager::WpsServiceUpdateCallback(location_service_state_e state, void* } _LocationManager* pThis = static_cast< _LocationManager* >(user_data); - pThis->__nativeWPSServiceState = state; + pThis->__wpsHandler.serviceState = state; } void @@ -1195,7 +1552,7 @@ _LocationManager::CpsServiceUpdateCallback(location_service_state_e state, void* } _LocationManager* pThis = static_cast< _LocationManager* >(user_data); - pThis->__nativeCPSServiceState = state; + pThis->__cpsHandler.serviceState = state; } void @@ -1223,104 +1580,6 @@ _LocationManager::DestroyLocationManager(void) delete __pUniqueInstance; } -Location -_LocationManager::GetLastKnownLocation(location_method_e nativeLocMethod) -{ - String locationMethod; - location_manager_h nativeHandle = null; - switch (nativeLocMethod) - { - case LOCATIONS_METHOD_GPS: - nativeHandle = __gpsHandler; - locationMethod = L"gps"; - break; - case LOCATIONS_METHOD_WPS: - nativeHandle = __wpsHandler; - locationMethod = L"network"; - break; - case LOCATIONS_METHOD_CPS: - nativeHandle = __cpsHandler; - locationMethod = L"network"; - break; - default: - break; - } - SysLog(NID_LOC, "Last location requested(method: %x, handle: %x).", nativeLocMethod, nativeHandle); - - Location location = _LocationImpl::GetLocationInstance(); - if (nativeHandle != null) - { - _LocationImpl* pLocationImpl = _LocationImpl::GetInstance(location); - - double altitude = Tizen::Locations::NaN; - double latitude = Tizen::Locations::NaN; - double longitude = Tizen::Locations::NaN; - time_t timestampPosition = 0; - - int res = location_manager_get_last_position(nativeHandle, &altitude, &latitude, &longitude, ×tampPosition); - SysTryCatch(NID_LOC, res == 0, , E_SYSTEM, "[E_SYSTEM] Failed to fetch last position from nativeHandle(%x).", nativeHandle); - SysLog(NID_LOC, "Last position(latitude: %lf, longitude: %lf, altitude: %lf, timestamp: %lld", - latitude, longitude, altitude, timestampPosition); - - Coordinates coord; - coord.Set(latitude, longitude, altitude); - pLocationImpl->SetCoordinates(coord); - - double horAcc = Tizen::Locations::NaN; - double verAcc = Tizen::Locations::NaN; - location_accuracy_level_e level; - res = location_manager_get_last_accuracy(nativeHandle, &level, &horAcc, &verAcc); - if (res == 0) - { - SysLog(NID_LOC, "Last accuracy(horAcc: %lf, vAcc: %lf, level: %x)", horAcc, verAcc, level); - pLocationImpl->SetHorizontalAccuracy(horAcc); - pLocationImpl->SetVerticalAccuracy(verAcc); - } - - double climb = Tizen::Locations::NaN; - double direction = Tizen::Locations::NaN; - double speed = Tizen::Locations::NaN; - time_t timestampVelocity = 0; - res = location_manager_get_last_velocity(nativeHandle, &climb, &direction, &speed, ×tampVelocity); - if (res == 0) - { - SysLog(NID_LOC, "Last velocity(climb: %lf, direction: %lf, speed: %x, timestamp: %lld)", - climb, direction, speed, timestampVelocity); - pLocationImpl->SetCourse(direction); - pLocationImpl->SetSpeed(speed); - } - - if (nativeLocMethod == LOCATIONS_METHOD_GPS) - { - int satUsedCount = 0; - int satViewCount = 0; - time_t timestampSatellite = 0; - String satInfo = L""; - res = gps_status_get_last_satellite(nativeHandle, &satUsedCount, &satViewCount, ×tampSatellite); - if (res == 0) - { - long timeDiff = 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: %lld, timeDiff: %ld)", - res, satUsedCount, satViewCount, timestampSatellite, timeDiff); - - SysLog(NID_LOC, "Last satellite(info: %ls)", satInfo.GetPointer()); - pLocationImpl->SetExtraInfo(L"satellite", satInfo); - } - } - - pLocationImpl->SetTimestamp(((long long)timestampPosition) * 1000); // in milliseconds - pLocationImpl->SetValidity(true); - pLocationImpl->SetExtraInfo(L"location_method", locationMethod); - } - - ClearLastResult(); - return location; - -CATCH: - return location; -} - bool _LocationManager::GetAppAccessibility(void) { @@ -1348,46 +1607,4 @@ _LocationManager::GetAppAccessibility(void) return (accessState == LOCATIONS_ACCESS_STATE_ALLOWED) ? true : false; } - -Location -_LocationManager::GetRecentLocationAvailable(void) -{ - long long gpsTimestamp = 0; - long long wpsTimestamp = 0; - long long cpsTimestamp = 0; - - Location lastGpsLocation = GetLastKnownLocation(LOCATIONS_METHOD_GPS); - if (lastGpsLocation.IsValid()) - { - gpsTimestamp = _LocationImpl::GetInstance(lastGpsLocation)->GetTimestampInMs(); - } - - Location lastWpsLocation = GetLastKnownLocation(LOCATIONS_METHOD_WPS); - if (lastWpsLocation.IsValid()) - { - wpsTimestamp = _LocationImpl::GetInstance(lastWpsLocation)->GetTimestampInMs(); - } - - Location lastCpsLocation = GetLastKnownLocation(LOCATIONS_METHOD_CPS); - if (lastCpsLocation.IsValid()) - { - cpsTimestamp = _LocationImpl::GetInstance(lastCpsLocation)->GetTimestampInMs(); - } - - SysLog(NID_LOC, "Compare timestamp(gps: %lld, wps: %lld, cps: %lld) for recent location.", - gpsTimestamp, wpsTimestamp, cpsTimestamp); - - if (gpsTimestamp >= wpsTimestamp && gpsTimestamp >= cpsTimestamp) - { - return lastGpsLocation; - } - else if (wpsTimestamp > gpsTimestamp && wpsTimestamp > cpsTimestamp) - { - return lastWpsLocation; - } - else - { - return lastCpsLocation; - } -} }} diff --git a/src/FLoc_LocationManager.h b/src/FLoc_LocationManager.h index 531eabb..75c5d97 100644 --- a/src/FLoc_LocationManager.h +++ b/src/FLoc_LocationManager.h @@ -57,6 +57,12 @@ public: // result StopLocationUpdates(RequestId reqId); + // This method updates the requested interval from the location provider. + // + // @since 2.0 + // + result ChangeUpdateInterval(RequestId reqId, int interval); + // This method initiates the synchronous location retrieval. The location monitor instance provided is used to intimate back the location. // // @since 2.0 @@ -158,7 +164,7 @@ private: // // @since 2.0 // - result SetLocationInformation(double latitude, double longitude, double altitude, time_t timestamp, location_method_e locMethod); + result SetLocationInformation(double latitude, double longitude, double altitude, time_t timestamp, location_method_e locMethod, Location* pLocation); // The method is called to send back the callbacks in case of async location updates. // @@ -184,6 +190,30 @@ private: // Location GetLastKnownLocation(location_method_e nativeLocMethod); + // This method returns the most recent location among available last known locations. + // + // @since 2.0 + // + Location GetRecentLocationAvailable(void); + + // This method updates the timer interval for a particular request Id. + // + // @since 2.0 + // + void UpdateLocRequestInfoList(RequestId reqId, int interval); + + // This method gets the better location among the three location providers. + // + // @since 2.0 + // + const Location* FindBestLocation(void); + + // This method gets the location from the native side depending on the location handle. + // + // @since 2.0 + // + result GetLocation(location_method_e nativeLocMethod); + // @see @ref Tizen::Base::Runtime::EventDrivenThread::OnStart() // // @since 2.0 @@ -251,12 +281,6 @@ private: // static bool GetAppAccessibility(void); - // This method returns the most recent location among available last known locations. - // - // @since 2.0 - // - Location GetRecentLocationAvailable(void); - private: const static RequestId REQ_ID_START_LOC_UPDATES = 1; const static RequestId REQ_ID_STOP_LOC_UPDATES = 2; @@ -267,6 +291,7 @@ private: const static RequestId REQ_ID_SYNC_LOC_RETRIEVAL = 7; const static RequestId REQ_ID_GET_APP_ACCESSIBILITY = 8; const static RequestId REQ_ID_GET_LAST_LOCATION = 9; + const static RequestId REQ_ID_UPDATE_INTERVAL = 10; enum _LocationMethodRequested { @@ -286,19 +311,34 @@ private: } __locationMgrState; + class __LocationManagerHandle + { + public: + __LocationManagerHandle(void) + : serviceState(LOCATIONS_SERVICE_DISABLED) + , handle(null) + , pLocation(null) + { + } + + ~__LocationManagerHandle(void) + { + } + + public: + location_service_state_e serviceState; + location_manager_h handle; + std::unique_ptr< Tizen::Locations::Location > pLocation; + }; + LocationAccuracy __minRequestedAccuracy; - location_service_state_e __nativeGPSServiceState; - location_service_state_e __nativeWPSServiceState; - location_service_state_e __nativeCPSServiceState; int __timerInterval; int __timerTicks; - location_manager_h __gpsHandler; - location_manager_h __wpsHandler; - location_manager_h __cpsHandler; - std::unique_ptr< Tizen::Locations::Location > __pCurrentLocation; + __LocationManagerHandle __gpsHandler; + __LocationManagerHandle __wpsHandler; + __LocationManagerHandle __cpsHandler; 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::Runtime::Mutex > __pLocMgrMutex; std::unique_ptr< Tizen::Base::Runtime::Timer > __pLocUpdateTimer; static _LocationManager* __pUniqueInstance; diff --git a/src/FLoc_LocationProviderImpl.cpp b/src/FLoc_LocationProviderImpl.cpp index 02a1229..bccc8a3 100644 --- a/src/FLoc_LocationProviderImpl.cpp +++ b/src/FLoc_LocationProviderImpl.cpp @@ -39,7 +39,9 @@ #include #include #include +#include #include +#include "FLoc_Config.h" #include "FLoc_LocationImpl.h" #include "FLoc_LocationManager.h" #include "FLoc_LocationMonitor.h" @@ -60,21 +62,9 @@ namespace Tizen { namespace Locations _LocationProviderImpl::_LocationProviderImpl(void) : Tizen::Base::Runtime::_Event() - , __firstLocationUpdate(true) - , __regionMonitoringActive(false) - , __awakeEnabled(false) - , __updateInterval(0) - , __locationUpdateType(_LOCATION_UPDATE_TYPE_NONE) - , __locationUpdateStatus(LOC_SVC_STATUS_IDLE) - , __regionMonitorStatus(LOC_SVC_STATUS_IDLE) , __lastLocationAccuracy(LOC_ACCURACY_INVALID) - , __reqId(-1) - , __regionReqId(-1) - , __distanceThreshold(0.0) , __pLocationListener(null) , __pLocationManager(null) - , __pLastLocation(null) - , __pRegionList(null) { } @@ -109,6 +99,18 @@ _LocationProviderImpl::Construct(const LocationCriteria& criteria, ILocationProv r = pRegionList->Construct(); SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Failed to construct the list. Propagating.", GetErrorMessage(r)); + std::unique_ptr< Tizen::Base::Runtime::Timer> pTimer (new (std::nothrow) Timer()); + SysTryReturn(NID_LOC, pTimer != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + + r = pTimer->Construct(*this); + SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Failed to construct the timer. Propagating.", GetErrorMessage(r)); + + std::unique_ptr< Tizen::System::Alarm> pAlarm (new (std::nothrow) Alarm()); + SysTryReturn(NID_LOC, pAlarm != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + + r = pAlarm->Construct(*this); + SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Failed to construct the alarm. Propagating.", GetErrorMessage(r)); + UiApp* pAppInstance = Tizen::App::UiApp::GetInstance(); if (pAppInstance != null) { @@ -119,14 +121,21 @@ _LocationProviderImpl::Construct(const LocationCriteria& criteria, ILocationProv SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Error occured during adding the event listener to app manager. Propagating.", GetErrorMessage(r)); } - std::unique_ptr< Tizen::Locations::Location > pLocation(_LocationImpl::GetLocationInstanceN()); - SysTryReturn(NID_LOC, pLocation != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + std::unique_ptr< Tizen::Locations::Location > pLastLocation(_LocationImpl::GetLocationInstanceN()); + SysTryReturn(NID_LOC, pLastLocation != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + + std::unique_ptr pLastRegionLocation (_LocationImpl::GetLocationInstanceN()); + SysTryReturn(NID_LOC, pLastRegionLocation != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); _Event::Initialize(); _Event::AddListener(*this); - __pRegionList = std::move(pRegionList); - __pLastLocation = std::move(pLocation); + __regionMonitor.pRegionList = std::move(pRegionList); + __regionMonitor.pTimer = std::move(pTimer); + __regionMonitor.pAlarm = std::move(pAlarm); + __regionMonitor.pLocation = std::move(pLastRegionLocation); + __locationUpdater.pLocation = std::move(pLastLocation); + __criteria = criteria; __pLocationListener = &listener; __pLocationManager = pLocationManager; @@ -144,15 +153,10 @@ _LocationProviderImpl::StartLocationUpdatesByInterval(int interval) SysTryReturn(NID_LOC, interval >= 1, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The interval(%d) should be greater than or equal to 1", interval); - if (__locationUpdateType == _LOCATION_UPDATE_TYPE_INTERVAL && __updateInterval == interval) + if (__locationUpdater.type == _LOCATION_UPDATE_TYPE_INTERVAL && __locationUpdater.updateInterval == interval) { return E_SUCCESS; } - else if (__locationUpdateType == _LOCATION_UPDATE_TYPE_DISTANCE || __locationUpdateType == _LOCATION_UPDATE_TYPE_INTERVAL) - { - __pLocationManager->StopLocationUpdates(__reqId); - __locationUpdateStatus = LOC_SVC_STATUS_IDLE; - } const double INVALID_DISTANCE_THRESHOLD = 0.0; return StartLocationUpdates(_LOCATION_UPDATE_TYPE_INTERVAL, interval, INVALID_DISTANCE_THRESHOLD); @@ -168,15 +172,10 @@ _LocationProviderImpl::StartLocationUpdatesByDistance(double distance) SysTryReturn(NID_LOC, Double::IsNaN(distance) == false, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The distance is NaN."); - if (__locationUpdateType == _LOCATION_UPDATE_TYPE_DISTANCE && (Double::Compare(__distanceThreshold, distance) == 0)) + if (__locationUpdater.type == _LOCATION_UPDATE_TYPE_DISTANCE && (Double::Compare(__locationUpdater.distanceThreshold, distance) == 0)) { return E_SUCCESS; } - else if (__locationUpdateType == _LOCATION_UPDATE_TYPE_DISTANCE || __locationUpdateType == _LOCATION_UPDATE_TYPE_INTERVAL) - { - __pLocationManager->StopLocationUpdates(__reqId); - __locationUpdateStatus = LOC_SVC_STATUS_IDLE; - } const int INVALID_INTERVAL = 0; return StartLocationUpdates(_LOCATION_UPDATE_TYPE_DISTANCE, INVALID_INTERVAL, distance); @@ -185,11 +184,11 @@ _LocationProviderImpl::StartLocationUpdatesByDistance(double distance) result _LocationProviderImpl::StopLocationUpdates(void) { - SysLog(NID_LOC, "Stopping the location updates for the request ID (%ld)", __reqId); + SysLog(NID_LOC, "Stopping the location updates for the request ID (%ld)", __locationUpdater.reqId); - SysTryReturn(NID_LOC, __locationUpdateType != _LOCATION_UPDATE_TYPE_NONE, E_INVALID_OPERATION, E_INVALID_OPERATION, "[E_INVALID_OPERATION] Location update has not been requested."); + SysTryReturn(NID_LOC, __locationUpdater.type != _LOCATION_UPDATE_TYPE_NONE, E_INVALID_OPERATION, E_INVALID_OPERATION, "[E_INVALID_OPERATION] Location update has not been requested."); - result r = __pLocationManager->StopLocationUpdates(__reqId); + result r = __pLocationManager->StopLocationUpdates(__locationUpdater.reqId); ResetLocationUpdates(); @@ -199,11 +198,11 @@ _LocationProviderImpl::StopLocationUpdates(void) void _LocationProviderImpl::KeepLocationUpdateAwake(bool enable) { - if (__awakeEnabled == enable) + if (__locationUpdater.awakeEnabled == enable) { return; } - __awakeEnabled = enable; + __locationUpdater.awakeEnabled = enable; UiApp* appInstance = Tizen::App::UiApp::GetInstance(); if (appInstance == null) // This is service APP. So should be handled now. @@ -211,24 +210,24 @@ _LocationProviderImpl::KeepLocationUpdateAwake(bool enable) SysLog(NID_LOC, "Handling the request awake mode(%d) for the service application.", enable); if (enable == true) { - if (__locationUpdateType != _LOCATION_UPDATE_TYPE_NONE && __locationUpdateStatus == LOC_SVC_STATUS_PAUSED) + if (__locationUpdater.type != _LOCATION_UPDATE_TYPE_NONE && __locationUpdater.status == LOC_SVC_STATUS_PAUSED) { - SysLog(NID_LOC, "Requesting to start the location updates as the update type is (%x)", __locationUpdateType); - __locationUpdateStatus = LOC_SVC_STATUS_NOT_FIXED; - __pLocationManager->StartLocationUpdates(__criteria.GetAccuracy(), __updateInterval, this, __reqId); + SysLog(NID_LOC, "Requesting to start the location updates as the update type is (%x)", __locationUpdater.type); + __locationUpdater.status = LOC_SVC_STATUS_NOT_FIXED; + __pLocationManager->StartLocationUpdates(__criteria.GetAccuracy(), __locationUpdater.updateInterval, this, __locationUpdater.reqId); - NotifyServiceStatus(_LOC_PRV_EVENT_SEND_LOC_SVC_CB, __locationUpdateStatus); + NotifyServiceStatus(_LOC_PRV_EVENT_SEND_LOC_SVC_CB, __locationUpdater.status); } } else { - if (__locationUpdateType != _LOCATION_UPDATE_TYPE_NONE && (__locationUpdateStatus == LOC_SVC_STATUS_RUNNING || __locationUpdateStatus == LOC_SVC_STATUS_NOT_FIXED)) + if (__locationUpdater.type != _LOCATION_UPDATE_TYPE_NONE && (__locationUpdater.status == LOC_SVC_STATUS_RUNNING || __locationUpdater.status == LOC_SVC_STATUS_NOT_FIXED)) { - SysLog(NID_LOC, "Requesting to stop the location updates as the update type is (%x)", __locationUpdateType); - __locationUpdateStatus = LOC_SVC_STATUS_PAUSED; - __pLocationManager->StopLocationUpdates(__reqId); + SysLog(NID_LOC, "Requesting to stop the location updates as the update type is (%x)", __locationUpdater.type); + __locationUpdater.status = LOC_SVC_STATUS_PAUSED; + __pLocationManager->StopLocationUpdates(__locationUpdater.reqId); - NotifyServiceStatus(_LOC_PRV_EVENT_SEND_LOC_SVC_CB, __locationUpdateStatus); + NotifyServiceStatus(_LOC_PRV_EVENT_SEND_LOC_SVC_CB, __locationUpdater.status); } } } @@ -247,50 +246,51 @@ _LocationProviderImpl::AddMonitoringRegion(const Coordinates& regionCenter, doub SysLog(NID_LOC, "Requested to add the monitoring region with center (Latitude: %lf, Longitude %lf) and radius (%lf).", regionCenter.GetLatitude(), regionCenter.GetLongitude(), radius); - const int DEAULT_REGION_MONITOR_INTERVAL = 5; static int nextRegionId = 0; result r = E_SUCCESS; std::unique_ptr< _RegionInfo > pRegionInfo(new (std::nothrow) _RegionInfo(regionCenter, radius, nextRegionId)); SysTryReturn(NID_LOC, pRegionInfo != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); - r = __pRegionList->Add(*pRegionInfo.get()); + r = __regionMonitor.pRegionList->Add(*pRegionInfo.get()); SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Failed to add the Region info into the list. Propogated.", GetErrorMessage(r)); pRegionInfo.release(); regionId = nextRegionId; nextRegionId++; - if (__regionMonitoringActive == true) + if (__regionMonitor.status != LOC_SVC_STATUS_IDLE) { return E_SUCCESS; } - r = __pLocationManager->StartLocationUpdates(__criteria.GetAccuracy(), DEAULT_REGION_MONITOR_INTERVAL, this, __regionReqId); - SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Failed to start the location updates. Propogating.", GetErrorMessage(r)); + r = ActivateRegionMonitoring(); + SysTryCatch(NID_LOC, r == E_SUCCESS, , r, "[%s] Failed to start the region monitoring. Propogating.", GetErrorMessage(r)); - __regionMonitoringActive = true; - __regionMonitorStatus = LOC_SVC_STATUS_NOT_FIXED; - NotifyServiceStatus(_LOC_PRV_EVENT_SEND_MONITOR_SVC_CB, __regionMonitorStatus); + __regionMonitor.status = LOC_SVC_STATUS_NOT_FIXED; + NotifyServiceStatus(_LOC_PRV_EVENT_SEND_MONITOR_SVC_CB, __regionMonitor.status); return E_SUCCESS; + +CATCH: + __regionMonitor.pRegionList->RemoveAt(0); + return r; } result _LocationProviderImpl::RemoveMonitoringRegion(RegionId regionId) { - int count = __pRegionList->GetCount(); - result r = E_SUCCESS; + int count = __regionMonitor.pRegionList->GetCount(); bool isIdValid = false; SysLog(NID_LOC, "Total regions currently monitored is (%d).", count); for (int i = 0; i < count; i++) { - _RegionInfo* pRegionInfo = static_cast< _RegionInfo* >(__pRegionList->GetAt(i)); + _RegionInfo* pRegionInfo = static_cast< _RegionInfo* >(__regionMonitor.pRegionList->GetAt(i)); if (regionId == pRegionInfo->GetRegionId()) { - __pRegionList->RemoveAt(i, true); + __regionMonitor.pRegionList->RemoveAt(i, true); isIdValid = true; break; } @@ -298,16 +298,14 @@ _LocationProviderImpl::RemoveMonitoringRegion(RegionId regionId) SysTryReturn(NID_LOC, isIdValid == true, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The region ID is invalid."); - if (__pRegionList->GetCount() == 0) + if (__regionMonitor.pRegionList->GetCount() == 0) { - __regionMonitoringActive = false; - __regionMonitorStatus = LOC_SVC_STATUS_IDLE; - if (__locationUpdateStatus == LOC_SVC_STATUS_IDLE) // As we are using the same variable for both region monitoring and location updates, this set is required here. + __regionMonitor.status = LOC_SVC_STATUS_IDLE; + if (__locationUpdater.status == LOC_SVC_STATUS_IDLE) // As we are using the same variable for both region monitoring and location updates, this set is required here. { __lastLocationAccuracy = LOC_ACCURACY_INVALID; } - r = __pLocationManager->StopLocationUpdates(__regionReqId); - SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] All regions are removed but failed to stop the location updates. Propagating.", GetErrorMessage(r)); + StopRegionMonitoring(); } return E_SUCCESS; @@ -316,20 +314,16 @@ _LocationProviderImpl::RemoveMonitoringRegion(RegionId regionId) void _LocationProviderImpl::RemoveAllMonitoringRegions(void) { - result r = E_SUCCESS; + __regionMonitor.pRegionList->RemoveAll(true); - __pRegionList->RemoveAll(true); - - if (__regionMonitoringActive == true) + if (__regionMonitor.status != LOC_SVC_STATUS_IDLE) { - __regionMonitoringActive = false; - __regionMonitorStatus = LOC_SVC_STATUS_IDLE; - if (__locationUpdateStatus == LOC_SVC_STATUS_IDLE) // As we are using the same variable for both region monitoring and location updates, this set is required here. + __regionMonitor.status = LOC_SVC_STATUS_IDLE; + if (__locationUpdater.status == LOC_SVC_STATUS_IDLE) // As we are using the same variable for both region monitoring and location updates, this set is required here. { __lastLocationAccuracy = LOC_ACCURACY_INVALID; } - r = __pLocationManager->StopLocationUpdates(__regionReqId); - SysTryReturnVoidResult(NID_LOC, r == E_SUCCESS, r, "[%s] All regions are removed but failed to stop the location updates. Ignored.", GetErrorMessage(r)); + StopRegionMonitoring(); } return; @@ -338,13 +332,13 @@ _LocationProviderImpl::RemoveAllMonitoringRegions(void) LocationServiceStatus _LocationProviderImpl::GetLocationUpdateStatus(void) const { - return __locationUpdateStatus; + return __locationUpdater.status; } LocationServiceStatus _LocationProviderImpl::GetRegionMonitoringStatus(void) const { - return __regionMonitorStatus; + return __regionMonitor.status; } LocationAccuracy @@ -464,12 +458,19 @@ _LocationProviderImpl::OnLocationEventReceivedN(RequestId reqId, Tizen::Location Location* pLocation = &location; _LocationImpl* pLocationImpl = _LocationImpl::GetInstance(*pLocation); - if (__pLastLocation) + + if (reqId == __locationUpdater.reqId) { - lastLocationTime = _LocationImpl::GetInstance(*__pLastLocation.get())->GetTimestampInMs(); + SysLog(NID_LOC, "The location is updated for Location request."); + lastLocationTime = _LocationImpl::GetInstance(*__locationUpdater.pLocation.get())->GetTimestampInMs(); + } + else if (reqId == __regionMonitor.reqId) + { + SysLog(NID_LOC, "The location is updated for Region monitoring."); + lastLocationTime = _LocationImpl::GetInstance(*__regionMonitor.pLocation.get())->GetTimestampInMs(); } - long long timeDifference = abs(pLocationImpl->GetTimestampInMs() - lastLocationTime); + long long timeDifference = pLocationImpl->GetTimestampInMs() - lastLocationTime; SysLog(NID_LOC, "Time difference between last location timestamp (%lld) and current location timestamp (%lld) is (%lld).", lastLocationTime, pLocationImpl->GetTimestampInMs(), timeDifference); if (timeDifference > 0) { @@ -484,13 +485,31 @@ _LocationProviderImpl::OnLocationEventReceivedN(RequestId reqId, Tizen::Location __pLocationListener->OnAccuracyChanged(currentAccuracy); } - if (reqId == __reqId) + if (reqId == __locationUpdater.reqId) { HandleLocationUpdate(location, isNew); } - else if (reqId == __regionReqId) + else if (reqId == __regionMonitor.reqId) { - HandleRegionMonitoring(location, isNew); + if (isNew) // Copy the location only if it is new. + { + *__regionMonitor.pLocation = location; + } + + if (currentAccuracy != LOC_ACCURACY_INVALID && currentAccuracy <= __criteria.GetAccuracy()) + { + SysLog(NID_LOC, "Location criteria (accuracy: %ld) is met for handling region monitoring.", currentAccuracy); + result r = __regionMonitor.pTimer->Cancel(); + SysTryLog(NID_LOC, r == E_SUCCESS, "Failed to cancel the timer."); + + r = __pLocationManager->StopLocationUpdates(__regionMonitor.reqId); + SysTryLog(NID_LOC, r == E_SUCCESS, "Failed to stop the location updates."); + HandleRegionMonitoring(location, isNew); + } + else + { + SysLog(NID_LOC, "Location criteria (accuracy: %ld) is not met for handling region monitoring.", currentAccuracy); + } } delete pLocation; @@ -520,81 +539,111 @@ _LocationProviderImpl::OnActiveAppChanged(const Tizen::App::AppId& appId) { SysLog(NID_LOC, "Application is active."); - if (__locationUpdateStatus == LOC_SVC_STATUS_PAUSED) + if (__locationUpdater.status == LOC_SVC_STATUS_PAUSED) { SysLog(NID_LOC, "Start the location updates as the location update status is PAUSED."); - __pLocationManager->StartLocationUpdates(__criteria.GetAccuracy(), __updateInterval, this, __reqId); - __locationUpdateStatus = LOC_SVC_STATUS_NOT_FIXED; - __pLocationListener->OnLocationUpdateStatusChanged(__locationUpdateStatus); + __pLocationManager->StartLocationUpdates(__criteria.GetAccuracy(), __locationUpdater.updateInterval, this, __locationUpdater.reqId); + __locationUpdater.status = LOC_SVC_STATUS_NOT_FIXED; + __pLocationListener->OnLocationUpdateStatusChanged(__locationUpdater.status); } } else { SysLog(NID_LOC, "Application is not active."); - if (__awakeEnabled == false && (__locationUpdateStatus == LOC_SVC_STATUS_RUNNING || __locationUpdateStatus == LOC_SVC_STATUS_NOT_FIXED)) + + if (__locationUpdater.awakeEnabled == false && (__locationUpdater.status == LOC_SVC_STATUS_RUNNING || __locationUpdater.status == LOC_SVC_STATUS_NOT_FIXED)) { - SysLog(NID_LOC, "Stop the location updates as application is not active with awake mode as (%d) and location update state as (%x).", __awakeEnabled, __locationUpdateStatus); - __pLocationManager->StopLocationUpdates(__reqId); - __locationUpdateStatus = LOC_SVC_STATUS_PAUSED; - __pLocationListener->OnLocationUpdateStatusChanged(__locationUpdateStatus); + SysLog(NID_LOC, "Stop the location updates as application is not active with awake mode as (%d) and location update state as (%x).", __locationUpdater.awakeEnabled, __locationUpdater.status); + __pLocationManager->StopLocationUpdates(__locationUpdater.reqId); + __locationUpdater.status = LOC_SVC_STATUS_PAUSED; + __pLocationListener->OnLocationUpdateStatusChanged(__locationUpdater.status); } } } +void +_LocationProviderImpl::OnAlarmExpired(Alarm& alarm) +{ + SysLog(NID_LOC, "Region Monitor Alarm expired."); + + result r = ActivateRegionMonitoring(); + SysTryReturnVoidResult(NID_LOC, r == E_SUCCESS, r, "[%s] Failed to start the region monitoring. Propogating.", GetErrorMessage(r)); +} + +void +_LocationProviderImpl::OnTimerExpired(Timer& timer) +{ + SysLog(NID_LOC, "Region Monitor timer expired due to unavailability of location information."); + __pLocationManager->StopLocationUpdates(__regionMonitor.reqId); + HandleRegionMonitoring(*__regionMonitor.pLocation, __regionMonitor.pLocation->IsValid()); +} + result _LocationProviderImpl::StartLocationUpdates(LocationUpdateType updateType, int interval, double distance) { result r = E_SUCCESS; - const int CHECKING_INTERVAL = 10; + bool startUpdate = true; if (updateType == _LOCATION_UPDATE_TYPE_INTERVAL) { - __updateInterval = interval; + __locationUpdater.updateInterval = interval; } else if (updateType == _LOCATION_UPDATE_TYPE_DISTANCE) { - __updateInterval = CHECKING_INTERVAL; - __distanceThreshold = distance; + __locationUpdater.updateInterval = DEFAULT_DISTANCE_CHECKING_INTERVAL; + __locationUpdater.distanceThreshold = distance; } - __locationUpdateType = updateType; - - if (__awakeEnabled == true) - { - r = __pLocationManager->StartLocationUpdates(__criteria.GetAccuracy(), __updateInterval, this, __reqId); - SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Failed to start the Native location updates.", GetErrorMessage(r)); - __locationUpdateStatus = LOC_SVC_STATUS_NOT_FIXED; - } - else + if (!__locationUpdater.awakeEnabled) { UiApp* pAppInstance = Tizen::App::UiApp::GetInstance(); if (pAppInstance == null) { - __locationUpdateStatus = LOC_SVC_STATUS_PAUSED; + startUpdate = false; } - else + else { AppUiState appUiState = pAppInstance->GetAppUiState(); - if (appUiState == APP_UI_STATE_FOREGROUND || appUiState == APP_UI_STATE_PARTIAL_BACKGROUND) - { - r = __pLocationManager->StartLocationUpdates(__criteria.GetAccuracy(), __updateInterval, this, __reqId); - SysTryCatch(NID_LOC, r == E_SUCCESS, , r, "[%s] Failed to start the location updates. Propagating.", GetErrorMessage(r)); - __locationUpdateStatus = LOC_SVC_STATUS_NOT_FIXED; - } - else + + if (appUiState == APP_UI_STATE_BACKGROUND) { - __locationUpdateStatus = LOC_SVC_STATUS_PAUSED; + SysLog(NID_LOC, "App is background."); + startUpdate = false; } } } - SysLog(NID_LOC, "Update type is (%x). The request Id is (%ld) and the update status is (%x).", __locationUpdateType, __reqId, __locationUpdateStatus); - NotifyServiceStatus(_LOC_PRV_EVENT_SEND_LOC_SVC_CB, __locationUpdateStatus); + if (startUpdate) + { + if (__locationUpdater.type != _LOCATION_UPDATE_TYPE_NONE) + { + SysLog(NID_LOC, "Update session already running. Updating the interval to %d seconds", __locationUpdater.updateInterval); + r = __pLocationManager->ChangeUpdateInterval(__locationUpdater.reqId, __locationUpdater.updateInterval); + SysTryCatch(NID_LOC, r == E_SUCCESS, , r, "[%s] Failed to update the request interval. Propagating.", GetErrorMessage(r)); + __locationUpdater.type = updateType; + return E_SUCCESS; + } + else + { + r = __pLocationManager->StartLocationUpdates(__criteria.GetAccuracy(), __locationUpdater.updateInterval, this, __locationUpdater.reqId); + SysTryCatch(NID_LOC, r == E_SUCCESS, , r, "[%s] Failed to start the Native location updates. Propagating.", GetErrorMessage(r)); + __locationUpdater.status = LOC_SVC_STATUS_NOT_FIXED; + } + } + else + { + __locationUpdater.status = LOC_SVC_STATUS_PAUSED; + } + + __locationUpdater.type = updateType; + + SysLog(NID_LOC, "Update type is (%x). The request Id is (%ld) and the update status is (%x).", __locationUpdater.type, __locationUpdater.reqId, __locationUpdater.status); + NotifyServiceStatus(_LOC_PRV_EVENT_SEND_LOC_SVC_CB, __locationUpdater.status); return E_SUCCESS; CATCH: - __locationUpdateType = _LOCATION_UPDATE_TYPE_NONE; + __locationUpdater.type = _LOCATION_UPDATE_TYPE_NONE; return r; } @@ -605,28 +654,28 @@ _LocationProviderImpl::CheckDistanceThreshold(const Location& oldPosition, const const Coordinates coordOld = oldPosition.GetCoordinates(); const Coordinates coordNew = newPosition.GetCoordinates(); - if (__firstLocationUpdate) + if (__locationUpdater.firstLocationUpdate) { SysLog(NID_LOC, "First location update. So send true."); - __firstLocationUpdate = false; + __locationUpdater.firstLocationUpdate = false; return true; } displacement = coordOld.GetDistanceTo(coordNew); SysLog(NID_LOC, "Displacement is (%lf)", displacement); - return ((displacement > __distanceThreshold) ? true : false); + return ((displacement > __locationUpdater.distanceThreshold) ? true : false); } void _LocationProviderImpl::ResetLocationUpdates(void) { - __firstLocationUpdate = true; - __reqId = -1; + __locationUpdater.firstLocationUpdate = true; + __locationUpdater.reqId = -1; __lastLocationAccuracy = LOC_ACCURACY_INVALID; - __locationUpdateType = _LOCATION_UPDATE_TYPE_NONE; - __locationUpdateStatus = LOC_SVC_STATUS_IDLE; - __updateInterval = 0; - __distanceThreshold = 0.0; + __locationUpdater.type = _LOCATION_UPDATE_TYPE_NONE; + __locationUpdater.status = LOC_SVC_STATUS_IDLE; + __locationUpdater.updateInterval = 0; + __locationUpdater.distanceThreshold = 0.0; } void @@ -659,11 +708,11 @@ _LocationProviderImpl::FireImpl(Tizen::Base::Runtime::IEventListener& listener, void _LocationProviderImpl::HandleLocationUpdate(Tizen::Locations::Location& location, bool isNew) { - LocationServiceStatus newLocationUpdateStatus = __locationUpdateStatus; + LocationServiceStatus newLocationUpdateStatus = __locationUpdater.status; if (isNew) { - if (__locationUpdateType != _LOCATION_UPDATE_TYPE_NONE && __locationUpdateStatus != LOC_SVC_STATUS_PAUSED) + if (__locationUpdater.type != _LOCATION_UPDATE_TYPE_NONE && __locationUpdater.status != LOC_SVC_STATUS_PAUSED) { newLocationUpdateStatus = LOC_SVC_STATUS_RUNNING; } @@ -671,7 +720,7 @@ _LocationProviderImpl::HandleLocationUpdate(Tizen::Locations::Location& location else if (_LocationImpl::GetInstance(location)->IsDenied()) { SysLog(NID_LOC, "User consent not available."); - if (__locationUpdateType != _LOCATION_UPDATE_TYPE_NONE && __locationUpdateStatus != LOC_SVC_STATUS_PAUSED) + if (__locationUpdater.type != _LOCATION_UPDATE_TYPE_NONE && __locationUpdater.status != LOC_SVC_STATUS_PAUSED) { newLocationUpdateStatus = LOC_SVC_STATUS_DENIED; } @@ -679,35 +728,35 @@ _LocationProviderImpl::HandleLocationUpdate(Tizen::Locations::Location& location else { SysLog(NID_LOC, "Invalid Location Update."); - if (__locationUpdateType != _LOCATION_UPDATE_TYPE_NONE && __locationUpdateStatus != LOC_SVC_STATUS_PAUSED) + if (__locationUpdater.type != _LOCATION_UPDATE_TYPE_NONE && __locationUpdater.status != LOC_SVC_STATUS_PAUSED) { newLocationUpdateStatus = LOC_SVC_STATUS_NOT_FIXED; } } - if (newLocationUpdateStatus != __locationUpdateStatus) + if (newLocationUpdateStatus != __locationUpdater.status) { SysLog(NID_LOC, "Location Update Satus changed to (%x). Notify the status.", newLocationUpdateStatus); - __locationUpdateStatus = newLocationUpdateStatus; - __pLocationListener->OnLocationUpdateStatusChanged(__locationUpdateStatus); + __locationUpdater.status = newLocationUpdateStatus; + __pLocationListener->OnLocationUpdateStatusChanged(__locationUpdater.status); } if (newLocationUpdateStatus == LOC_SVC_STATUS_RUNNING) { - if (__locationUpdateType == _LOCATION_UPDATE_TYPE_DISTANCE) + if (__locationUpdater.type == _LOCATION_UPDATE_TYPE_DISTANCE) { - if (CheckDistanceThreshold(*__pLastLocation.get(), location) == true) + if (CheckDistanceThreshold(*__locationUpdater.pLocation.get(), location) == true) { - SysLog(NID_LOC, "Location displacement exceeds the distance threshold (%lf). Notify the location.", __distanceThreshold); + SysLog(NID_LOC, "Location displacement exceeds the distance threshold (%lf). Notify the location.", __locationUpdater.distanceThreshold); __pLocationListener->OnLocationUpdated(location); - *__pLastLocation.get() = location; + *__locationUpdater.pLocation.get() = location; } } - else if (__locationUpdateType == _LOCATION_UPDATE_TYPE_INTERVAL) + else if (__locationUpdater.type == _LOCATION_UPDATE_TYPE_INTERVAL) { SysLog(NID_LOC, "Location time interval expired. Notify the location."); __pLocationListener->OnLocationUpdated(location); - *__pLastLocation.get() = location; + *__locationUpdater.pLocation.get() = location; } } } @@ -715,7 +764,7 @@ _LocationProviderImpl::HandleLocationUpdate(Tizen::Locations::Location& location void _LocationProviderImpl::HandleRegionMonitoring(Tizen::Locations::Location& location, bool isNew) { - LocationServiceStatus newRegionMonitorStatus = __regionMonitorStatus; + LocationServiceStatus newRegionMonitorStatus = __regionMonitor.status; if (isNew) { @@ -730,30 +779,31 @@ _LocationProviderImpl::HandleRegionMonitoring(Tizen::Locations::Location& locati newRegionMonitorStatus = LOC_SVC_STATUS_NOT_FIXED; } - if (newRegionMonitorStatus != __regionMonitorStatus) + if (newRegionMonitorStatus != __regionMonitor.status) { SysLog(NID_LOC, "Region Monitoring Satus changed to (%x). Notify the status.", newRegionMonitorStatus); - __regionMonitorStatus = newRegionMonitorStatus; - __pLocationListener->OnRegionMonitoringStatusChanged(__regionMonitorStatus); + __regionMonitor.status = newRegionMonitorStatus; + __pLocationListener->OnRegionMonitoringStatusChanged(__regionMonitor.status); } if (newRegionMonitorStatus == LOC_SVC_STATUS_RUNNING) { NotifyRegionCrossedStatus(location); - *__pLastLocation.get() = location; } + + SetNextRegionMonitoringTime(); } void _LocationProviderImpl::NotifyRegionCrossedStatus(const Tizen::Locations::Location& location) { - int count = __pRegionList->GetCount(); + int count = __regionMonitor.pRegionList->GetCount(); SysLog(NID_LOC, "Number of regions currently monitored is (%d)", count); for (int i = 0; i < count; i++) { - _RegionInfo* pRegionInfo = static_cast< _RegionInfo* >(__pRegionList->GetAt(i)); + _RegionInfo* pRegionInfo = static_cast< _RegionInfo* >(__regionMonitor.pRegionList->GetAt(i)); if (pRegionInfo) { @@ -920,4 +970,66 @@ _LocationProviderImpl::GetUserPrivilege(void) return true; } + +result +_LocationProviderImpl::ActivateRegionMonitoring(void) +{ + long long currentTime; + SystemTime::GetTicks(currentTime); + + SysLog(NID_LOC, "Current system time is %lld", currentTime); + + _LocationImpl::GetInstance(*__regionMonitor.pLocation)->SetValidity(false); + _LocationImpl::GetInstance(*__regionMonitor.pLocation)->SetTimestamp(currentTime); + + result r = __regionMonitor.pTimer->Start(DEFAULT_WAITING_TIME_FOR_FIXING_LOCATION * 1000); + SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Failed to start the timer. Propogating.", GetErrorMessage(r)); + + r = __pLocationManager->StartLocationUpdates(__criteria.GetAccuracy(), MIN_LOCATION_UPDATE_INTERVAL, this, __regionMonitor.reqId); + SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Failed to start the location updates. Propogating.", GetErrorMessage(r)); + + SysLog(NID_LOC, "Timer & Location updates are started."); + return E_SUCCESS; +} + +void +_LocationProviderImpl::StopRegionMonitoring(void) +{ + result r = _AlarmImpl::GetInstance(__regionMonitor.pAlarm.get())->Cancel(); + SysTryReturnVoidResult(NID_LOC, r == E_SUCCESS, r, "[%s] Failed to stop the alarm. Ignored.", GetErrorMessage(r)); + + r = __regionMonitor.pTimer->Cancel(); + SysTryReturnVoidResult(NID_LOC, r == E_SUCCESS, r, "[%s] Failed to stop the timer. Ignored.", GetErrorMessage(r)); + + r = __pLocationManager->StopLocationUpdates(__regionMonitor.reqId); + SysTryReturnVoidResult(NID_LOC, r == E_SUCCESS, r, "[%s] All regions are removed but failed to stop the location updates. Ignored.", GetErrorMessage(r)); +} + +void +_LocationProviderImpl::SetNextRegionMonitoringTime(void) +{ + DateTime alarmDateTime; + long long alarmTime = DEFAULT_REGION_MONITORING_CYCLE_INTERVAL; + SystemTime::GetCurrentTime(TIME_MODE_WALL, alarmDateTime); + + SysLog(NID_LOC, "Current System Time is %ls", alarmDateTime.ToString().GetPointer()); + + if (__regionMonitor.pLocation->IsValid()) + { + const int bufferTime = 5; //Buffer of 5 seconds for determining the alarmTime; + double minDistance = _MathUtils::GetShortestDistance(*__regionMonitor.pLocation, *__regionMonitor.pRegionList); + long long newAlarmTime = ((int) minDistance / DEFAULT_AVG_SPEED) - bufferTime; //Calculate the alarm time based on the shortest distance between current location and nearest region boundary. + + if (newAlarmTime > alarmTime) + { + alarmTime = newAlarmTime; + } + } + + alarmDateTime.AddSeconds(alarmTime); + result r = _AlarmImpl::GetInstance(__regionMonitor.pAlarm.get())->Set(alarmDateTime, 0, null); + SysTryLog(NID_LOC, r == E_SUCCESS, "Failed to set the alarm for next cycle."); + + SysLog(NID_LOC, "Next alarm expires after %ld seconds.", alarmTime); +} }} diff --git a/src/FLoc_LocationProviderImpl.h b/src/FLoc_LocationProviderImpl.h index 3b78e53..cc23a48 100644 --- a/src/FLoc_LocationProviderImpl.h +++ b/src/FLoc_LocationProviderImpl.h @@ -28,9 +28,12 @@ #include #include #include -#include #include +#include +#include #include +#include +#include #include #include "FLoc_ILocationManagerListener.h" #include "FLoc_ILocProviderEventListener.h" @@ -56,6 +59,8 @@ class _LocationProviderImpl , public Tizen::Locations::_ILocationManagerListener , public Tizen::Locations::_ILocProviderEventListener , public Tizen::App::IActiveAppEventListener + , public Tizen::Base::Runtime::ITimerEventListener + , public Tizen::System::IAlarmEventListener { public: /** @@ -175,6 +180,16 @@ private: */ virtual void OnActiveAppChanged(const Tizen::App::AppId& appId); + /** + * @see @ref Tizen::System::IAlarmEventListener::OnAlarmExpired() + */ + virtual void OnAlarmExpired(Tizen::System::Alarm& alarm); + + /** + * @see @ref Tizen::Base::Runtime::ITimerEventListener::OnTimerExpired() + */ + virtual void OnTimerExpired(Tizen::Base::Runtime::Timer& timer); + // This method requests the location update to the Location Manager. // // @since 2.0 @@ -226,29 +241,92 @@ private: // void NotifyServiceStatus(_LocProviderEventType eventType, LocationServiceStatus svcStatus); - // This method is returns the bool value depicting the privilege details depending on the location settings. + // This method returns the bool value depicting the privilege details depending on the location settings. // // @since 2.0 // static bool GetUserPrivilege(void); + // This method starts the location updates and the timer for region monitoring. + // + // @since 2.0 + // + result ActivateRegionMonitoring(void); + + // This method stops the location updates and cancels the timer and alarm set for the area monitoring. + // + // @since 2.0 + // + void StopRegionMonitoring(void); + + // This method determines the time for the alarm to be set for next cycle of region monitoring. + // + // @since 2.0 + // + void SetNextRegionMonitoringTime(void); + private: - bool __firstLocationUpdate; - bool __regionMonitoringActive; - bool __awakeEnabled; - int __updateInterval; - LocationUpdateType __locationUpdateType; - LocationServiceStatus __locationUpdateStatus; - LocationServiceStatus __regionMonitorStatus; + class _LocationUpdater + { + public: + _LocationUpdater(void) + : firstLocationUpdate(true) + , awakeEnabled(false) + , updateInterval(0) + , status(LOC_SVC_STATUS_IDLE) + , type(_LOCATION_UPDATE_TYPE_NONE) + , reqId(-1) + , distanceThreshold(0.0) + , pLocation(null) + { + } + + ~_LocationUpdater(void) + { + } + + public: + bool firstLocationUpdate; + bool awakeEnabled; + int updateInterval; + LocationServiceStatus status; + LocationUpdateType type; + RequestId reqId; + double distanceThreshold; + std::unique_ptr pLocation; + }__locationUpdater; + + class _RegionMonitor + { + public: + _RegionMonitor(void) + : reqId(-1) + , status(LOC_SVC_STATUS_IDLE) + , pTimer(null) + , pAlarm(null) + , pLocation(null) + , pRegionList(null) + { + } + + ~_RegionMonitor(void) + { + } + + public: + RequestId reqId; + LocationServiceStatus status; + std::unique_ptr pTimer; + std::unique_ptr pAlarm; + std::unique_ptr pLocation; + std::unique_ptr< Tizen::Base::Collection::ArrayList, Tizen::Base::Collection::AllElementsDeleter > pRegionList; + }__regionMonitor; + LocationAccuracy __lastLocationAccuracy; - RequestId __reqId; - RequestId __regionReqId; - double __distanceThreshold; LocationCriteria __criteria; ILocationProviderListener* __pLocationListener; _LocationManager* __pLocationManager; - std::unique_ptr< Tizen::Locations::Location > __pLastLocation; - std::unique_ptr< Tizen::Base::Collection::ArrayList, Tizen::Base::Collection::AllElementsDeleter > __pRegionList; + }; // _LocationProviderImpl }} // Tizen::Locations diff --git a/src/FLoc_LocationRequestInfo.h b/src/FLoc_LocationRequestInfo.h index de3602c..ef3046c 100644 --- a/src/FLoc_LocationRequestInfo.h +++ b/src/FLoc_LocationRequestInfo.h @@ -67,6 +67,8 @@ public: RequestId GetRequestId(void) const {return __reqId;} + void SetInterval(int interval) { __interval = interval;} + private: _LocationRequestInfo(void); diff --git a/src/FLoc_MathUtils.cpp b/src/FLoc_MathUtils.cpp index 25c2b6a..dc6042b 100644 --- a/src/FLoc_MathUtils.cpp +++ b/src/FLoc_MathUtils.cpp @@ -23,6 +23,7 @@ */ #include +#include #include #include #include @@ -30,7 +31,7 @@ #include "FLoc_RegionInfo.h" using namespace Tizen::Base::Utility; - +using namespace Tizen::Base; namespace Tizen { namespace Locations { @@ -70,4 +71,30 @@ _MathUtils::CalculateOverlapRegion(const _RegionInfo& region, const Location& lo return overlapArea; } +double +_MathUtils::GetShortestDistance(const Location& location, const Tizen::Base::Collection::IList& regionList) +{ + double minDistance = Double::GetMaxValue(); + int count = regionList.GetCount(); + + for (int i = 0; i < count; i++) + { + const _RegionInfo* pRegionInfo = static_cast (regionList.GetAt(i)); + + if (pRegionInfo) + { + Coordinates regionCoordinate = pRegionInfo->GetCoordinate(); + double distance = abs(regionCoordinate.GetDistanceTo(location.GetCoordinates()) - pRegionInfo->GetRadius()); + + if (minDistance > distance) + { + minDistance = distance; + } + } + } + + SysLog(NID_LOC, "Shortest distance from location (lat: %lf and lon: %lf) to the nearest region boundary is (%lf) meters", location.GetCoordinates().GetLatitude(), location.GetCoordinates().GetLongitude(), minDistance); + + return minDistance; +} } } // Tizen::Locations diff --git a/src/FLoc_MathUtils.h b/src/FLoc_MathUtils.h index 082de85..7459b2d 100644 --- a/src/FLoc_MathUtils.h +++ b/src/FLoc_MathUtils.h @@ -27,6 +27,11 @@ #ifndef _FLOC_INTERNAL_MATH_UTILS_H_ #define _FLOC_INTERNAL_MATH_UTILS_H_ +namespace Tizen { namespace Base { namespace Collection +{ + class IList; +}}} + namespace Tizen { namespace Locations { @@ -48,6 +53,12 @@ public: // static double CalculateOverlapRegion(const _RegionInfo& region, const Location& location); + // This method returns the distance between the user's current location and the the nearest boundary among the added monitoring regions. + // @since 2.0 + // + static double GetShortestDistance(const Location& location, const Tizen::Base::Collection::IList& regionList); + + public: static const double PI; static const double PI2; diff --git a/src/FLoc_SyncLocationRequestInfo.h b/src/FLoc_SyncLocationRequestInfo.h index 0b22c78..f286707 100644 --- a/src/FLoc_SyncLocationRequestInfo.h +++ b/src/FLoc_SyncLocationRequestInfo.h @@ -45,7 +45,6 @@ public: _SyncLocationRequestInfo(_LocationMonitor* pLocMonitor, RequestId reqId) : Tizen::Base::Object() , __pLocMonitor(pLocMonitor) - , __pTimer(null) , __reqId(reqId) , __tickCount(0) { @@ -56,34 +55,12 @@ public: _LocationMonitor* GetLocationMonitor(void) const {return __pLocMonitor;} - result StartTimer(Tizen::Base::Runtime::ITimerEventListener& listener) - { - result r = E_SUCCESS; - - if (__pTimer == null) - { - std::unique_ptr< Tizen::Base::Runtime::Timer > pTimer(new (std::nothrow) Tizen::Base::Runtime::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(listener); - SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Failed to construct the timer.", GetErrorMessage(r)); - - __pTimer = std::move(pTimer); - } - - const int DEFAULT_TIME_OUT = 1000; - r = __pTimer->Start(DEFAULT_TIME_OUT); - SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Failed to start the timer.", GetErrorMessage(r)); - __tickCount++; - return E_SUCCESS; - } - - bool Equals(const Tizen::Base::Runtime::Timer& timer) {return __pTimer->Equals(timer);} - RequestId GetRequestId(void) const {return __reqId;} int GetTickCount(void) const {return __tickCount;} + void IncrementTickCount(void) { __tickCount++;} + bool IsInTime(const Tizen::Base::DateTime& timestamp) { return (timestamp > __requestTime) ? true : false; @@ -109,7 +86,6 @@ private: private: Tizen::Base::DateTime __requestTime; _LocationMonitor* __pLocMonitor; - std::unique_ptr< Tizen::Base::Runtime::Timer > __pTimer; RequestId __reqId; int __tickCount; }; //_SyncLocationRequestInfo -- 2.7.4