From 44d5c9e2cf9f1ce0670be5bedd1e415cd5c3e739 Mon Sep 17 00:00:00 2001 From: kleidione Freitas Date: Thu, 24 Mar 2022 09:16:43 -0300 Subject: veux: Merge common tree to veux - Ref: https://github.com/xiaomi-sm6375-devs/android_device_xiaomi_sm6375-common Signed-off-by: kleidione --- gps/location/Android.bp | 36 + gps/location/ILocationAPI.h | 406 +++++++ gps/location/LocationAPI.cpp | 976 +++++++++++++++ gps/location/LocationAPI.h | 512 ++++++++ gps/location/LocationAPIClientBase.cpp | 977 +++++++++++++++ gps/location/LocationAPIClientBase.h | 592 +++++++++ gps/location/LocationDataTypes.h | 2070 ++++++++++++++++++++++++++++++++ gps/location/Makefile.am | 44 + gps/location/configure.ac | 95 ++ gps/location/location-api.pc.in | 10 + gps/location/location_interface.h | 144 +++ 11 files changed, 5862 insertions(+) create mode 100644 gps/location/Android.bp create mode 100644 gps/location/ILocationAPI.h create mode 100644 gps/location/LocationAPI.cpp create mode 100644 gps/location/LocationAPI.h create mode 100644 gps/location/LocationAPIClientBase.cpp create mode 100644 gps/location/LocationAPIClientBase.h create mode 100644 gps/location/LocationDataTypes.h create mode 100644 gps/location/Makefile.am create mode 100644 gps/location/configure.ac create mode 100644 gps/location/location-api.pc.in create mode 100644 gps/location/location_interface.h (limited to 'gps/location') diff --git a/gps/location/Android.bp b/gps/location/Android.bp new file mode 100644 index 0000000..8532a08 --- /dev/null +++ b/gps/location/Android.bp @@ -0,0 +1,36 @@ + +cc_library_shared { + + name: "liblocation_api", + vendor: true, + + sanitize: GNSS_SANITIZE, + + shared_libs: [ + "libutils", + "libcutils", + "libgps.utils", + "libdl", + "liblog", + ], + + srcs: [ + "LocationAPI.cpp", + "LocationAPIClientBase.cpp", + ], + + cflags: ["-fno-short-enums"] + GNSS_CFLAGS, + + header_libs: [ + "libloc_pla_headers", + "libgps.utils_headers", + ], + +} + +cc_library_headers { + + name: "liblocation_api_headers", + export_include_dirs: ["."], + vendor: true, +} diff --git a/gps/location/ILocationAPI.h b/gps/location/ILocationAPI.h new file mode 100644 index 0000000..29846ac --- /dev/null +++ b/gps/location/ILocationAPI.h @@ -0,0 +1,406 @@ +/* Copyright (c) 2018-2020 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ILOCATIONAPI_H +#define ILOCATIONAPI_H + +#include "LocationDataTypes.h" + +class ILocationAPI +{ +public: + virtual ~ILocationAPI(){}; + + /** @brief Updates/changes the callbacks that will be called. + mandatory callbacks must be present for callbacks to be successfully updated + no return value */ + virtual void updateCallbacks(LocationCallbacks&) = 0; + + /* ================================== TRACKING ================================== */ + + /** @brief Starts a tracking session, which returns a session id that will be + used by the other tracking APIs and also in the responseCallback to match command + with response. locations are reported on the registered trackingCallback + periodically according to LocationOptions. + @return session id + responseCallback returns: + LOCATION_ERROR_SUCCESS if session was successfully started + LOCATION_ERROR_ALREADY_STARTED if a startTracking session is already in progress + LOCATION_ERROR_CALLBACK_MISSING if no trackingCallback was passed + LOCATION_ERROR_INVALID_PARAMETER if LocationOptions parameter is invalid */ + virtual uint32_t startTracking(TrackingOptions&) = 0; + + /** @brief Stops a tracking session associated with id parameter. + responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_ID_UNKNOWN if id is not associated with a tracking session */ + virtual void stopTracking(uint32_t id) = 0; + + /** @brief Changes the LocationOptions of a tracking session associated with id. + responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_INVALID_PARAMETER if LocationOptions parameters are invalid + LOCATION_ERROR_ID_UNKNOWN if id is not associated with a tracking session */ + virtual void updateTrackingOptions(uint32_t id, TrackingOptions&) = 0; + + /* ================================== BATCHING ================================== */ + + /** @brief starts a batching session, which returns a session id that will be + used by the other batching APIs and also in the responseCallback to match command + with response. locations are reported on the batchingCallback passed in createInstance + periodically according to LocationOptions. A batching session starts tracking on + the low power processor and delivers them in batches by the batchingCallback when + the batch is full or when getBatchedLocations is called. This allows for the processor + that calls this API to sleep when the low power processor can batch locations in the + backgroup and wake up the processor calling the API only when the batch is full, thus + saving power. + @return session id + responseCallback returns: + LOCATION_ERROR_SUCCESS if session was successful + LOCATION_ERROR_ALREADY_STARTED if a startBatching session is already in progress + LOCATION_ERROR_CALLBACK_MISSING if no batchingCallback + LOCATION_ERROR_INVALID_PARAMETER if a parameter is invalid + LOCATION_ERROR_NOT_SUPPORTED if batching is not supported */ + virtual uint32_t startBatching(BatchingOptions&) = 0; + + /** @brief Stops a batching session associated with id parameter. + responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_ID_UNKNOWN if id is not associated with batching session */ + virtual void stopBatching(uint32_t id) = 0; + + /** @brief Changes the LocationOptions of a batching session associated with id. + responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_INVALID_PARAMETER if LocationOptions parameters are invalid + LOCATION_ERROR_ID_UNKNOWN if id is not associated with a batching session */ + virtual void updateBatchingOptions(uint32_t id, BatchingOptions&) = 0; + + /** @brief Gets a number of locations that are currently stored/batched + on the low power processor, delivered by the batchingCallback passed in createInstance. + Location are then deleted from the batch stored on the low power processor. + responseCallback returns: + LOCATION_ERROR_SUCCESS if successful, will be followed by batchingCallback call + LOCATION_ERROR_CALLBACK_MISSING if no batchingCallback + LOCATION_ERROR_ID_UNKNOWN if id is not associated with a batching session */ + virtual void getBatchedLocations(uint32_t id, size_t count) = 0; + + /* ================================== GEOFENCE ================================== */ + + /** @brief Adds any number of geofences and returns an array of geofence ids that + will be used by the other geofence APIs and also in the collectiveResponseCallback to + match command with response. The geofenceBreachCallback will deliver the status of each + geofence according to the GeofenceOption for each. The geofence id array returned will + be valid until the collectiveResponseCallback is called and has returned. + @return id array + collectiveResponseCallback returns: + LOCATION_ERROR_SUCCESS if session was successful + LOCATION_ERROR_CALLBACK_MISSING if no geofenceBreachCallback + LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid + LOCATION_ERROR_NOT_SUPPORTED if geofence is not supported */ + virtual uint32_t* addGeofences(size_t count, GeofenceOption*, GeofenceInfo*) = 0; + + /** @brief Removes any number of geofences. Caller should delete ids array after + removeGeofences returneds. + collectiveResponseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_ID_UNKNOWN if id is not associated with a geofence session */ + virtual void removeGeofences(size_t count, uint32_t* ids) = 0; + + /** @brief Modifies any number of geofences. Caller should delete ids array after + modifyGeofences returns. + collectiveResponseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_ID_UNKNOWN if id is not associated with a geofence session + LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid */ + virtual void modifyGeofences(size_t count, uint32_t* ids, GeofenceOption* options) = 0; + + /** @brief Pauses any number of geofences, which is similar to removeGeofences, + only that they can be resumed at any time. Caller should delete ids array after + pauseGeofences returns. + collectiveResponseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_ID_UNKNOWN if id is not associated with a geofence session */ + virtual void pauseGeofences(size_t count, uint32_t* ids) = 0; + + /** @brief Resumes any number of geofences that are currently paused. Caller should + delete ids array after resumeGeofences returns. + collectiveResponseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_ID_UNKNOWN if id is not associated with a geofence session */ + virtual void resumeGeofences(size_t count, uint32_t* ids) = 0; + + /* ================================== GNSS ====================================== */ + + /** @brief gnssNiResponse is called in response to a gnssNiCallback. + responseCallback returns: + LOCATION_ERROR_SUCCESS if session was successful + LOCATION_ERROR_INVALID_PARAMETER if any parameters in GnssNiResponse are invalid + LOCATION_ERROR_ID_UNKNOWN if id does not match a gnssNiCallback */ + virtual void gnssNiResponse(uint32_t id, GnssNiResponse response) = 0; +}; + +class ILocationControlAPI +{ +public: + virtual ~ILocationControlAPI(){}; + + /** @brief Updates the gnss specific configuration, which returns a session id array + with an id for each of the bits set in GnssConfig.flags, order from low bits to high bits. + The response for each config that is set will be returned in collectiveResponseCallback. + The session id array returned will be valid until the collectiveResponseCallback is called + and has returned. This effect is global for all clients of ILocationAPI. + collectiveResponseCallback returns: + LOCATION_ERROR_SUCCESS if session was successful + LOCATION_ERROR_INVALID_PARAMETER if any other parameters are invalid + LOCATION_ERROR_GENERAL_FAILURE if failure for any other reason */ + virtual uint32_t* gnssUpdateConfig(const GnssConfig& config) = 0; + + /** @brief Delete specific gnss aiding data for testing, which returns a session id + that will be returned in responseCallback to match command with response. + Only allowed in userdebug builds. This effect is global for all clients of ILocationAPI. + responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid + LOCATION_ERROR_NOT_SUPPORTED if build is not userdebug */ + virtual uint32_t gnssDeleteAidingData(GnssAidingData& data) = 0; + + /** @brief + Configure the constellation and SVs to be used by the GNSS engine on + modem. + + @param + constellationEnablementConfig: configuration to enable/disable SV + constellation to be used by SPE engine. When size in + constellationEnablementConfig is set to 0, this indicates to reset SV + constellation configuration to modem NV default. + + blacklistSvConfig: configuration to blacklist or unblacklist SVs + used by SPE engine + + @return + A session id that will be returned in responseCallback to + match command with response. This effect is global for all + clients of LocationAPI responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid + */ + virtual uint32_t configConstellations( + const GnssSvTypeConfig& constellationEnablementConfig, + const GnssSvIdConfig& blacklistSvConfig) = 0; + + /** @brief + Configure the secondary band of constellations to be used by + the GNSS engine on modem. + + @param + secondaryBandConfig: configuration the secondary band usage + for SPE engine + + @return + A session id that will be returned in responseCallback to + match command with response. This effect is global for all + clients of LocationAPI responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid + */ + virtual uint32_t configConstellationSecondaryBand( + const GnssSvTypeConfig& secondaryBandConfig) = 0; + + /** @brief + Enable or disable the constrained time uncertainty feature. + + @param + enable: true to enable the constrained time uncertainty + feature and false to disable the constrainted time + uncertainty feature. + + @param + tuncThreshold: this specifies the time uncertainty threshold + that gps engine need to maintain, in units of milli-seconds. + Default is 0.0 meaning that modem default value of time + uncertainty threshold will be used. This parameter is + ignored when requesting to disable this feature. + + @param + energyBudget: this specifies the power budget that gps + engine is allowed to spend to maintain the time uncertainty. + Default is 0 meaning that GPS engine is not constained by + power budget and can spend as much power as needed. The + parameter need to be specified in units of 0.1 milli watt + second. This parameter is ignored requesting to disable this + feature. + + @return + A session id that will be returned in responseCallback to + match command with response. This effect is global for all + clients of LocationAPI responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_INVALID_PARAMETER if any parameters + are invalid + */ + virtual uint32_t configConstrainedTimeUncertainty( + bool enable, float tuncThreshold = 0.0, + uint32_t energyBudget = 0) = 0; + + /** @brief + Enable or disable position assisted clock estimator feature. + + @param + enable: true to enable position assisted clock estimator and + false to disable the position assisted clock estimator + feature. + + @return + A session id that will be returned in responseCallback to + match command with response. This effect is global for all + clients of LocationAPI responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid + */ + virtual uint32_t configPositionAssistedClockEstimator(bool enable) = 0; + + /** @brief + Sets the lever arm parameters for the vehicle. + + @param + configInfo: lever arm configuration info regarding below two + types of lever arm info: + a: GNSS Antenna w.r.t the origin at the IMU e.g.: inertial + measurement unit. + b: lever arm parameters regarding the OPF (output frame) + w.r.t the origin (at the GPS Antenna). Vehicle manufacturers + prefer the position output to be tied to a specific point in + the vehicle rather than where the antenna is placed + (midpoint of the rear axle is typical). + + Caller can choose types of lever arm info to configure via the + leverMarkTypeMask. + + @return + A session id that will be returned in responseCallback to + match command with response. This effect is global for all + clients of LocationAPI responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid + */ + virtual uint32_t configLeverArm(const LeverArmConfigInfo& configInfo) = 0; + + /** @brief + Configure the robust location setting. + + @param + enable: true to enable robust location and false to disable + robust location. + + @param + enableForE911: true to enable robust location when device is on + E911 session and false to disable on E911 session. + This parameter is only valid if robust location is enabled. + + @return + A session id that will be returned in responseCallback to + match command with response. This effect is global for all + clients of LocationAPI responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid + */ + virtual uint32_t configRobustLocation(bool enable, bool enableForE911) = 0; + + /** @brief + Config the minimum GPS week used by modem GNSS engine. + + @param + minGpsWeek: minimum GPS week to be used by modem GNSS engine. + + @return + A session id that will be returned in responseCallback to + match command with response. This effect is global for all + clients of LocationAPI responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid + */ + virtual uint32_t configMinGpsWeek(uint16_t minGpsWeek) = 0; + + /** @brief + Configure the vehicle body-to-Sensor mount parameters and + other parameters for dead reckoning position engine. + + @param + dreConfig: vehicle body-to-Sensor mount angles and other + parameters. + + @return + A session id that will be returned in responseCallback to + match command with response. This effect is global for all + clients of LocationAPI responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid + */ + virtual uint32_t configDeadReckoningEngineParams(const DeadReckoningEngineConfig& dreConfig)=0; + + /** @brief + This API is used to instruct the specified engine to be in + the pause/resume state.
+ + When the engine is placed in paused state, the engine will + stop. If there is an on-going session, engine will no longer + produce fixes. In the paused state, calling API to delete + aiding data from the paused engine may not have effect. + Request to delete Aiding data shall be issued after + engine resume.
+ + Currently, only DRE engine will support pause/resume + request. responseCb() will return not supported when request + is made to pause/resume none-DRE engine.
+ + Request to pause/resume DRE engine can be made with or + without an on-going session. With QDR engine, on resume, + GNSS position & heading re-acquisition is needed for DR + engine to engage. If DR engine is already in the requested + state, the request will be no-op.
+ + @param + engType: the engine that is instructed to change its run + state.
+ + engState: the new engine run state that the engine is + instructed to be in.
+ + @return + A session id that will be returned in responseCallback to + match command with response. This effect is global for all + clients of LocationAPI responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid + */ + virtual uint32_t configEngineRunState(PositioningEngineMask engType, + LocEngineRunState engState) = 0; +}; + +#endif /* ILOCATIONAPI_H */ diff --git a/gps/location/LocationAPI.cpp b/gps/location/LocationAPI.cpp new file mode 100644 index 0000000..3a50c46 --- /dev/null +++ b/gps/location/LocationAPI.cpp @@ -0,0 +1,976 @@ +/* Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#define LOG_NDEBUG 0 +#define LOG_TAG "LocSvc_LocationAPI" + +#include +#include +#include +#include +#include +#include +#include + +typedef const GnssInterface* (getGnssInterface)(); +typedef const GeofenceInterface* (getGeofenceInterface)(); +typedef const BatchingInterface* (getBatchingInterface)(); +typedef void (createOSFramework)(); +typedef void (destroyOSFramework)(); + +// GTP services +typedef uint32_t (setOptInStatusGetter)(bool userConsent, responseCallback* callback); +typedef void (enableProviderGetter)(); +typedef void (disableProviderGetter)(); +typedef void (getSingleNetworkLocationGetter)(trackingCallback* callback); +typedef void (stopNetworkLocationGetter)(trackingCallback* callback); + +typedef struct { + // bit mask of the adpaters that we need to wait for the removeClientCompleteCallback + // before we invoke the registered locationApiDestroyCompleteCallback + LocationAdapterTypeMask waitAdapterMask; + locationApiDestroyCompleteCallback destroyCompleteCb; +} LocationAPIDestroyCbData; + +// This is the map for the client that has requested destroy with +// destroy callback provided. +typedef std::map + LocationClientDestroyCbMap; + +typedef std::map LocationClientMap; +typedef struct { + LocationClientMap clientData; + LocationClientDestroyCbMap destroyClientData; + LocationControlAPI* controlAPI; + LocationControlCallbacks controlCallbacks; + GnssInterface* gnssInterface; + GeofenceInterface* geofenceInterface; + BatchingInterface* batchingInterface; +} LocationAPIData; + +static LocationAPIData gData = {}; +static pthread_mutex_t gDataMutex = PTHREAD_MUTEX_INITIALIZER; +static bool gGnssLoadFailed = false; +static bool gBatchingLoadFailed = false; +static bool gGeofenceLoadFailed = false; +static uint32_t gOSFrameworkRefCount = 0; + +template +static const T1* loadLocationInterface(const char* library, const char* name) { + void* libhandle = nullptr; + T2* getter = (T2*)dlGetSymFromLib(libhandle, library, name); + if (nullptr == getter) { + return (const T1*) getter; + }else { + return (*getter)(); + } +} + +static void createOSFrameworkInstance() { + void* libHandle = nullptr; + createOSFramework* getter = (createOSFramework*)dlGetSymFromLib(libHandle, + "liblocationservice_glue.so", "createOSFramework"); + if (getter != nullptr) { + (*getter)(); + } else { + LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so"); + } +} + +static void destroyOSFrameworkInstance() { + void* libHandle = nullptr; + destroyOSFramework* getter = (destroyOSFramework*)dlGetSymFromLib(libHandle, + "liblocationservice_glue.so", "destroyOSFramework"); + if (getter != nullptr) { + (*getter)(); + } else { + LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so"); + } +} + +static bool needsGnssTrackingInfo(LocationCallbacks& locationCallbacks) +{ + return (locationCallbacks.gnssLocationInfoCb != nullptr || + locationCallbacks.engineLocationsInfoCb != nullptr || + locationCallbacks.gnssSvCb != nullptr || + locationCallbacks.gnssNmeaCb != nullptr || + locationCallbacks.gnssDataCb != nullptr || + locationCallbacks.gnssMeasurementsCb != nullptr); +} + +static bool isGnssClient(LocationCallbacks& locationCallbacks) +{ + return (locationCallbacks.gnssNiCb != nullptr || + locationCallbacks.trackingCb != nullptr || + locationCallbacks.gnssLocationInfoCb != nullptr || + locationCallbacks.engineLocationsInfoCb != nullptr || + locationCallbacks.gnssSvCb != nullptr || + locationCallbacks.gnssNmeaCb != nullptr || + locationCallbacks.gnssDataCb != nullptr || + locationCallbacks.gnssMeasurementsCb != nullptr || + locationCallbacks.locationSystemInfoCb != nullptr); +} + +static bool isBatchingClient(LocationCallbacks& locationCallbacks) +{ + return (locationCallbacks.batchingCb != nullptr); +} + +static bool isGeofenceClient(LocationCallbacks& locationCallbacks) +{ + return (locationCallbacks.geofenceBreachCb != nullptr || + locationCallbacks.geofenceStatusCb != nullptr); +} + + +void LocationAPI::onRemoveClientCompleteCb (LocationAdapterTypeMask adapterType) +{ + bool invokeCallback = false; + locationApiDestroyCompleteCallback destroyCompleteCb; + LOC_LOGd("adatper type %x", adapterType); + pthread_mutex_lock(&gDataMutex); + auto it = gData.destroyClientData.find(this); + if (it != gData.destroyClientData.end()) { + it->second.waitAdapterMask &= ~adapterType; + if (it->second.waitAdapterMask == 0) { + invokeCallback = true; + destroyCompleteCb = it->second.destroyCompleteCb; + gData.destroyClientData.erase(it); + } + } + pthread_mutex_unlock(&gDataMutex); + + if (invokeCallback) { + LOC_LOGd("invoke client destroy cb"); + if (!destroyCompleteCb) { + (destroyCompleteCb) (); + } + + delete this; + } +} + +void onGnssRemoveClientCompleteCb (LocationAPI* client) +{ + client->onRemoveClientCompleteCb (LOCATION_ADAPTER_GNSS_TYPE_BIT); +} + +void onBatchingRemoveClientCompleteCb (LocationAPI* client) +{ + client->onRemoveClientCompleteCb (LOCATION_ADAPTER_BATCHING_TYPE_BIT); +} + +void onGeofenceRemoveClientCompleteCb (LocationAPI* client) +{ + client->onRemoveClientCompleteCb (LOCATION_ADAPTER_GEOFENCE_TYPE_BIT); +} + +LocationAPI* +LocationAPI::createInstance (LocationCallbacks& locationCallbacks) +{ + if (nullptr == locationCallbacks.capabilitiesCb || + nullptr == locationCallbacks.responseCb || + nullptr == locationCallbacks.collectiveResponseCb) { + LOC_LOGe("missing mandatory callback, return null"); + return NULL; + } + + LocationAPI* newLocationAPI = new LocationAPI(); + bool requestedCapabilities = false; + + pthread_mutex_lock(&gDataMutex); + + gOSFrameworkRefCount++; + if (1 == gOSFrameworkRefCount) { + createOSFrameworkInstance(); + } + + if (isGnssClient(locationCallbacks)) { + if (NULL == gData.gnssInterface && !gGnssLoadFailed) { + gData.gnssInterface = + (GnssInterface*)loadLocationInterface("libgnss.so", "getGnssInterface"); + if (NULL == gData.gnssInterface) { + gGnssLoadFailed = true; + LOC_LOGW("%s:%d]: No gnss interface available", __func__, __LINE__); + } else { + gData.gnssInterface->initialize(); + } + } + if (NULL != gData.gnssInterface) { + gData.gnssInterface->addClient(newLocationAPI, locationCallbacks); + if (!requestedCapabilities) { + gData.gnssInterface->requestCapabilities(newLocationAPI); + requestedCapabilities = true; + } + } + } + + if (isBatchingClient(locationCallbacks)) { + if (NULL == gData.batchingInterface && !gBatchingLoadFailed) { + gData.batchingInterface = + (BatchingInterface*)loadLocationInterface("libbatching.so", "getBatchingInterface"); + if (NULL == gData.batchingInterface) { + gBatchingLoadFailed = true; + LOC_LOGW("%s:%d]: No batching interface available", __func__, __LINE__); + } else { + gData.batchingInterface->initialize(); + } + } + if (NULL != gData.batchingInterface) { + gData.batchingInterface->addClient(newLocationAPI, locationCallbacks); + if (!requestedCapabilities) { + gData.batchingInterface->requestCapabilities(newLocationAPI); + requestedCapabilities = true; + } + } + } + + if (isGeofenceClient(locationCallbacks)) { + if (NULL == gData.geofenceInterface && !gGeofenceLoadFailed) { + gData.geofenceInterface = + (GeofenceInterface*)loadLocationInterface("libgeofencing.so", "getGeofenceInterface"); + if (NULL == gData.geofenceInterface) { + gGeofenceLoadFailed = true; + LOC_LOGW("%s:%d]: No geofence interface available", __func__, __LINE__); + } else { + gData.geofenceInterface->initialize(); + } + } + if (NULL != gData.geofenceInterface) { + gData.geofenceInterface->addClient(newLocationAPI, locationCallbacks); + if (!requestedCapabilities) { + gData.geofenceInterface->requestCapabilities(newLocationAPI); + requestedCapabilities = true; + } + } + } + + gData.clientData[newLocationAPI] = locationCallbacks; + + pthread_mutex_unlock(&gDataMutex); + + return newLocationAPI; +} + +void +LocationAPI::destroy(locationApiDestroyCompleteCallback destroyCompleteCb) +{ + bool invokeDestroyCb = false; + + pthread_mutex_lock(&gDataMutex); + auto it = gData.clientData.find(this); + if (it != gData.clientData.end()) { + bool removeFromGnssInf = (NULL != gData.gnssInterface); + bool removeFromBatchingInf = (NULL != gData.batchingInterface); + bool removeFromGeofenceInf = (NULL != gData.geofenceInterface); + bool needToWait = (removeFromGnssInf || removeFromBatchingInf || removeFromGeofenceInf); + LOC_LOGe("removeFromGnssInf: %d, removeFromBatchingInf: %d, removeFromGeofenceInf: %d," + "needToWait: %d", removeFromGnssInf, removeFromBatchingInf, removeFromGeofenceInf, + needToWait); + + if ((NULL != destroyCompleteCb) && (true == needToWait)) { + LocationAPIDestroyCbData destroyCbData = {}; + destroyCbData.destroyCompleteCb = destroyCompleteCb; + // record down from which adapter we need to wait for the destroy complete callback + // only when we have received all the needed callbacks from all the associated stacks, + // we shall notify the client. + destroyCbData.waitAdapterMask = + (removeFromGnssInf ? LOCATION_ADAPTER_GNSS_TYPE_BIT : 0); + destroyCbData.waitAdapterMask |= + (removeFromBatchingInf ? LOCATION_ADAPTER_BATCHING_TYPE_BIT : 0); + destroyCbData.waitAdapterMask |= + (removeFromGeofenceInf ? LOCATION_ADAPTER_GEOFENCE_TYPE_BIT : 0); + gData.destroyClientData[this] = destroyCbData; + LOC_LOGi("destroy data stored in the map: 0x%x", destroyCbData.waitAdapterMask); + } + + if (removeFromGnssInf) { + gData.gnssInterface->removeClient(it->first, + onGnssRemoveClientCompleteCb); + } + if (removeFromBatchingInf) { + gData.batchingInterface->removeClient(it->first, + onBatchingRemoveClientCompleteCb); + } + if (removeFromGeofenceInf) { + gData.geofenceInterface->removeClient(it->first, + onGeofenceRemoveClientCompleteCb); + } + + gData.clientData.erase(it); + + if (!needToWait) { + invokeDestroyCb = true; + } + } else { + LOC_LOGE("%s:%d]: Location API client %p not found in client data", + __func__, __LINE__, this); + } + + if (1 == gOSFrameworkRefCount) { + destroyOSFrameworkInstance(); + } + gOSFrameworkRefCount--; + + pthread_mutex_unlock(&gDataMutex); + if (invokeDestroyCb) { + if (!destroyCompleteCb) { + (destroyCompleteCb) (); + } + delete this; + } +} + +LocationAPI::LocationAPI() +{ + LOC_LOGD("LOCATION API CONSTRUCTOR"); +} + +// private destructor +LocationAPI::~LocationAPI() +{ + LOC_LOGD("LOCATION API DESTRUCTOR"); +} + +void +LocationAPI::updateCallbacks(LocationCallbacks& locationCallbacks) +{ + if (nullptr == locationCallbacks.capabilitiesCb || + nullptr == locationCallbacks.responseCb || + nullptr == locationCallbacks.collectiveResponseCb) { + return; + } + + pthread_mutex_lock(&gDataMutex); + + if (isGnssClient(locationCallbacks)) { + if (NULL == gData.gnssInterface && !gGnssLoadFailed) { + gData.gnssInterface = + (GnssInterface*)loadLocationInterface("libgnss.so", "getGnssInterface"); + if (NULL == gData.gnssInterface) { + gGnssLoadFailed = true; + LOC_LOGW("%s:%d]: No gnss interface available", __func__, __LINE__); + } else { + gData.gnssInterface->initialize(); + } + } + if (NULL != gData.gnssInterface) { + // either adds new Client or updates existing Client + gData.gnssInterface->addClient(this, locationCallbacks); + } + } + + if (isBatchingClient(locationCallbacks)) { + if (NULL == gData.batchingInterface && !gBatchingLoadFailed) { + gData.batchingInterface = + (BatchingInterface*)loadLocationInterface("libbatching.so", "getBatchingInterface"); + if (NULL == gData.batchingInterface) { + gBatchingLoadFailed = true; + LOC_LOGW("%s:%d]: No batching interface available", __func__, __LINE__); + } else { + gData.batchingInterface->initialize(); + } + } + if (NULL != gData.batchingInterface) { + // either adds new Client or updates existing Client + gData.batchingInterface->addClient(this, locationCallbacks); + } + } + + if (isGeofenceClient(locationCallbacks)) { + if (NULL == gData.geofenceInterface && !gGeofenceLoadFailed) { + gData.geofenceInterface = + (GeofenceInterface*)loadLocationInterface("libgeofencing.so", "getGeofenceInterface"); + if (NULL == gData.geofenceInterface) { + gGeofenceLoadFailed = true; + LOC_LOGW("%s:%d]: No geofence interface available", __func__, __LINE__); + } else { + gData.geofenceInterface->initialize(); + } + } + if (NULL != gData.geofenceInterface) { + // either adds new Client or updates existing Client + gData.geofenceInterface->addClient(this, locationCallbacks); + } + } + + gData.clientData[this] = locationCallbacks; + + pthread_mutex_unlock(&gDataMutex); +} + +uint32_t +LocationAPI::startTracking(TrackingOptions& trackingOptions) +{ + uint32_t id = 0; + pthread_mutex_lock(&gDataMutex); + + auto it = gData.clientData.find(this); + if (it != gData.clientData.end()) { + if (NULL != gData.gnssInterface) { + id = gData.gnssInterface->startTracking(this, trackingOptions); + } else { + LOC_LOGE("%s:%d]: No gnss interface available for Location API client %p ", + __func__, __LINE__, this); + } + } else { + LOC_LOGE("%s:%d]: Location API client %p not found in client data", + __func__, __LINE__, this); + } + + pthread_mutex_unlock(&gDataMutex); + return id; +} + +void +LocationAPI::stopTracking(uint32_t id) +{ + pthread_mutex_lock(&gDataMutex); + + auto it = gData.clientData.find(this); + if (it != gData.clientData.end()) { + if (gData.gnssInterface != NULL) { + gData.gnssInterface->stopTracking(this, id); + } else { + LOC_LOGE("%s:%d]: No gnss interface available for Location API client %p ", + __func__, __LINE__, this); + } + } else { + LOC_LOGE("%s:%d]: Location API client %p not found in client data", + __func__, __LINE__, this); + } + + pthread_mutex_unlock(&gDataMutex); +} + +void +LocationAPI::updateTrackingOptions( + uint32_t id, TrackingOptions& trackingOptions) +{ + pthread_mutex_lock(&gDataMutex); + + auto it = gData.clientData.find(this); + if (it != gData.clientData.end()) { + if (gData.gnssInterface != NULL) { + gData.gnssInterface->updateTrackingOptions(this, id, trackingOptions); + } else { + LOC_LOGE("%s:%d]: No gnss interface available for Location API client %p ", + __func__, __LINE__, this); + } + } else { + LOC_LOGE("%s:%d]: Location API client %p not found in client data", + __func__, __LINE__, this); + } + + pthread_mutex_unlock(&gDataMutex); +} + +uint32_t +LocationAPI::startBatching(BatchingOptions &batchingOptions) +{ + uint32_t id = 0; + pthread_mutex_lock(&gDataMutex); + + if (NULL != gData.batchingInterface) { + id = gData.batchingInterface->startBatching(this, batchingOptions); + } else { + LOC_LOGE("%s:%d]: No batching interface available for Location API client %p ", + __func__, __LINE__, this); + } + + pthread_mutex_unlock(&gDataMutex); + return id; +} + +void +LocationAPI::stopBatching(uint32_t id) +{ + pthread_mutex_lock(&gDataMutex); + + if (NULL != gData.batchingInterface) { + gData.batchingInterface->stopBatching(this, id); + } else { + LOC_LOGE("%s:%d]: No batching interface available for Location API client %p ", + __func__, __LINE__, this); + } + + pthread_mutex_unlock(&gDataMutex); +} + +void +LocationAPI::updateBatchingOptions(uint32_t id, BatchingOptions& batchOptions) +{ + pthread_mutex_lock(&gDataMutex); + + if (NULL != gData.batchingInterface) { + gData.batchingInterface->updateBatchingOptions(this, id, batchOptions); + } else { + LOC_LOGE("%s:%d]: No batching interface available for Location API client %p ", + __func__, __LINE__, this); + } + + pthread_mutex_unlock(&gDataMutex); +} + +void +LocationAPI::getBatchedLocations(uint32_t id, size_t count) +{ + pthread_mutex_lock(&gDataMutex); + + if (gData.batchingInterface != NULL) { + gData.batchingInterface->getBatchedLocations(this, id, count); + } else { + LOC_LOGE("%s:%d]: No batching interface available for Location API client %p ", + __func__, __LINE__, this); + } + + pthread_mutex_unlock(&gDataMutex); +} + +uint32_t* +LocationAPI::addGeofences(size_t count, GeofenceOption* options, GeofenceInfo* info) +{ + uint32_t* ids = NULL; + pthread_mutex_lock(&gDataMutex); + + if (gData.geofenceInterface != NULL) { + ids = gData.geofenceInterface->addGeofences(this, count, options, info); + } else { + LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ", + __func__, __LINE__, this); + } + + pthread_mutex_unlock(&gDataMutex); + return ids; +} + +void +LocationAPI::removeGeofences(size_t count, uint32_t* ids) +{ + pthread_mutex_lock(&gDataMutex); + + if (gData.geofenceInterface != NULL) { + gData.geofenceInterface->removeGeofences(this, count, ids); + } else { + LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ", + __func__, __LINE__, this); + } + + pthread_mutex_unlock(&gDataMutex); +} + +void +LocationAPI::modifyGeofences(size_t count, uint32_t* ids, GeofenceOption* options) +{ + pthread_mutex_lock(&gDataMutex); + + if (gData.geofenceInterface != NULL) { + gData.geofenceInterface->modifyGeofences(this, count, ids, options); + } else { + LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ", + __func__, __LINE__, this); + } + + pthread_mutex_unlock(&gDataMutex); +} + +void +LocationAPI::pauseGeofences(size_t count, uint32_t* ids) +{ + pthread_mutex_lock(&gDataMutex); + + if (gData.geofenceInterface != NULL) { + gData.geofenceInterface->pauseGeofences(this, count, ids); + } else { + LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ", + __func__, __LINE__, this); + } + + pthread_mutex_unlock(&gDataMutex); +} + +void +LocationAPI::resumeGeofences(size_t count, uint32_t* ids) +{ + pthread_mutex_lock(&gDataMutex); + + if (gData.geofenceInterface != NULL) { + gData.geofenceInterface->resumeGeofences(this, count, ids); + } else { + LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ", + __func__, __LINE__, this); + } + + pthread_mutex_unlock(&gDataMutex); +} + +void +LocationAPI::gnssNiResponse(uint32_t id, GnssNiResponse response) +{ + pthread_mutex_lock(&gDataMutex); + + if (gData.gnssInterface != NULL) { + gData.gnssInterface->gnssNiResponse(this, id, response); + } else { + LOC_LOGE("%s:%d]: No gnss interface available for Location API client %p ", + __func__, __LINE__, this); + } + + pthread_mutex_unlock(&gDataMutex); +} + +void LocationAPI::enableNetworkProvider() { + void* libHandle = nullptr; + enableProviderGetter* setter = (enableProviderGetter*)dlGetSymFromLib(libHandle, + "liblocationservice_glue.so", "enableNetworkProvider"); + if (setter != nullptr) { + (*setter)(); + } else { + LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so"); + } +} + +void LocationAPI::disableNetworkProvider() { + void* libHandle = nullptr; + disableProviderGetter* setter = (disableProviderGetter*)dlGetSymFromLib(libHandle, + "liblocationservice_glue.so", "disableNetworkProvider"); + if (setter != nullptr) { + (*setter)(); + } else { + LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so"); + } +} + +void LocationAPI::startNetworkLocation(trackingCallback* callback) { + void* libHandle = nullptr; + getSingleNetworkLocationGetter* setter = + (getSingleNetworkLocationGetter*)dlGetSymFromLib(libHandle, + "liblocationservice_glue.so", "startNetworkLocation"); + if (setter != nullptr) { + (*setter)(callback); + } else { + LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so"); + } +} + +void LocationAPI::stopNetworkLocation(trackingCallback* callback) { + void* libHandle = nullptr; + stopNetworkLocationGetter* setter = (stopNetworkLocationGetter*)dlGetSymFromLib(libHandle, + "liblocationservice_glue.so", "stopNetworkLocation"); + if (setter != nullptr) { + LOC_LOGe("called"); + (*setter)(callback); + } else { + LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so"); + } +} + +LocationControlAPI* +LocationControlAPI::createInstance(LocationControlCallbacks& locationControlCallbacks) +{ + LocationControlAPI* controlAPI = NULL; + pthread_mutex_lock(&gDataMutex); + + if (nullptr != locationControlCallbacks.responseCb && NULL == gData.controlAPI) { + if (NULL == gData.gnssInterface && !gGnssLoadFailed) { + gData.gnssInterface = + (GnssInterface*)loadLocationInterface("libgnss.so", "getGnssInterface"); + if (NULL == gData.gnssInterface) { + gGnssLoadFailed = true; + LOC_LOGW("%s:%d]: No gnss interface available", __func__, __LINE__); + } else { + gData.gnssInterface->initialize(); + } + } + if (NULL != gData.gnssInterface) { + gData.controlAPI = new LocationControlAPI(); + gData.controlCallbacks = locationControlCallbacks; + gData.gnssInterface->setControlCallbacks(locationControlCallbacks); + controlAPI = gData.controlAPI; + } + } + + pthread_mutex_unlock(&gDataMutex); + return controlAPI; +} + +void +LocationControlAPI::destroy() +{ + delete this; +} + +LocationControlAPI::LocationControlAPI() +{ + LOC_LOGD("LOCATION CONTROL API CONSTRUCTOR"); +} + +LocationControlAPI::~LocationControlAPI() +{ + LOC_LOGD("LOCATION CONTROL API DESTRUCTOR"); + pthread_mutex_lock(&gDataMutex); + + gData.controlAPI = NULL; + + pthread_mutex_unlock(&gDataMutex); +} + +uint32_t +LocationControlAPI::enable(LocationTechnologyType techType) +{ + uint32_t id = 0; + pthread_mutex_lock(&gDataMutex); + + if (gData.gnssInterface != NULL) { + id = gData.gnssInterface->enable(techType); + } else { + LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ", + __func__, __LINE__, this); + } + + pthread_mutex_unlock(&gDataMutex); + return id; +} + +void +LocationControlAPI::disable(uint32_t id) +{ + pthread_mutex_lock(&gDataMutex); + + if (gData.gnssInterface != NULL) { + gData.gnssInterface->disable(id); + } else { + LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ", + __func__, __LINE__, this); + } + + pthread_mutex_unlock(&gDataMutex); +} + +uint32_t* +LocationControlAPI::gnssUpdateConfig(const GnssConfig& config) +{ + uint32_t* ids = NULL; + pthread_mutex_lock(&gDataMutex); + + if (gData.gnssInterface != NULL) { + ids = gData.gnssInterface->gnssUpdateConfig(config); + } else { + LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ", + __func__, __LINE__, this); + } + + pthread_mutex_unlock(&gDataMutex); + return ids; +} + +uint32_t* LocationControlAPI::gnssGetConfig(GnssConfigFlagsMask mask) { + + uint32_t* ids = NULL; + pthread_mutex_lock(&gDataMutex); + + if (NULL != gData.gnssInterface) { + ids = gData.gnssInterface->gnssGetConfig(mask); + } else { + LOC_LOGe("No gnss interface available for Control API client %p", this); + } + + pthread_mutex_unlock(&gDataMutex); + return ids; +} + +uint32_t +LocationControlAPI::gnssDeleteAidingData(GnssAidingData& data) +{ + uint32_t id = 0; + pthread_mutex_lock(&gDataMutex); + + if (gData.gnssInterface != NULL) { + id = gData.gnssInterface->gnssDeleteAidingData(data); + } else { + LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ", + __func__, __LINE__, this); + } + + pthread_mutex_unlock(&gDataMutex); + return id; +} + +uint32_t LocationControlAPI::configConstellations( + const GnssSvTypeConfig& constellationEnablementConfig, + const GnssSvIdConfig& blacklistSvConfig) { + uint32_t id = 0; + pthread_mutex_lock(&gDataMutex); + + if (gData.gnssInterface != NULL) { + id = gData.gnssInterface->gnssUpdateSvConfig( + constellationEnablementConfig, blacklistSvConfig); + } else { + LOC_LOGe("No gnss interface available for Location Control API"); + } + + pthread_mutex_unlock(&gDataMutex); + return id; +} + +uint32_t LocationControlAPI::configConstellationSecondaryBand( + const GnssSvTypeConfig& secondaryBandConfig) { + uint32_t id = 0; + pthread_mutex_lock(&gDataMutex); + + if (gData.gnssInterface != NULL) { + id = gData.gnssInterface->gnssUpdateSecondaryBandConfig(secondaryBandConfig); + } else { + LOC_LOGe("No gnss interface available for Location Control API"); + } + + pthread_mutex_unlock(&gDataMutex); + return id; +} + +uint32_t LocationControlAPI::configConstrainedTimeUncertainty( + bool enable, float tuncThreshold, uint32_t energyBudget) { + uint32_t id = 0; + pthread_mutex_lock(&gDataMutex); + + if (gData.gnssInterface != NULL) { + id = gData.gnssInterface->setConstrainedTunc(enable, + tuncThreshold, + energyBudget); + } else { + LOC_LOGe("No gnss interface available for Location Control API"); + } + + pthread_mutex_unlock(&gDataMutex); + return id; +} + +uint32_t LocationControlAPI::configPositionAssistedClockEstimator(bool enable) { + uint32_t id = 0; + pthread_mutex_lock(&gDataMutex); + + if (gData.gnssInterface != NULL) { + id = gData.gnssInterface->setPositionAssistedClockEstimator(enable); + } else { + LOC_LOGe("No gnss interface available for Location Control API"); + } + + pthread_mutex_unlock(&gDataMutex); + return id; +} + +uint32_t LocationControlAPI::configLeverArm(const LeverArmConfigInfo& configInfo) { + uint32_t id = 0; + pthread_mutex_lock(&gDataMutex); + + if (gData.gnssInterface != NULL) { + id = gData.gnssInterface->configLeverArm(configInfo); + } else { + LOC_LOGe("No gnss interface available for Location Control API"); + } + + pthread_mutex_unlock(&gDataMutex); + return id; +} + +uint32_t LocationControlAPI::configRobustLocation(bool enable, bool enableForE911) { + uint32_t id = 0; + pthread_mutex_lock(&gDataMutex); + + if (gData.gnssInterface != NULL) { + id = gData.gnssInterface->configRobustLocation(enable, enableForE911); + } else { + LOC_LOGe("No gnss interface available for Location Control API"); + } + + pthread_mutex_unlock(&gDataMutex); + return id; +} + +uint32_t LocationControlAPI::configMinGpsWeek(uint16_t minGpsWeek) { + uint32_t id = 0; + pthread_mutex_lock(&gDataMutex); + + if (gData.gnssInterface != NULL) { + id = gData.gnssInterface->configMinGpsWeek(minGpsWeek); + } else { + LOC_LOGe("No gnss interface available for Location Control API"); + } + + pthread_mutex_unlock(&gDataMutex); + return id; +} + +uint32_t LocationControlAPI::configDeadReckoningEngineParams( + const DeadReckoningEngineConfig& dreConfig) { + uint32_t id = 0; + pthread_mutex_lock(&gDataMutex); + + if (gData.gnssInterface != NULL) { + id = gData.gnssInterface->configDeadReckoningEngineParams(dreConfig); + } else { + LOC_LOGe("No gnss interface available for Location Control API"); + } + + pthread_mutex_unlock(&gDataMutex); + return id; +} + +uint32_t LocationControlAPI::configEngineRunState( + PositioningEngineMask engType, LocEngineRunState engState) { + uint32_t id = 0; + pthread_mutex_lock(&gDataMutex); + + if (gData.gnssInterface != NULL) { + id = gData.gnssInterface->configEngineRunState(engType, engState); + } else { + LOC_LOGe("No gnss interface available for Location Control API"); + } + + pthread_mutex_unlock(&gDataMutex); + return id; +} + +uint32_t LocationControlAPI::setOptInStatus(bool userConsent) { + void* libHandle = nullptr; + uint32_t sessionId = 0; + setOptInStatusGetter* setter = (setOptInStatusGetter*)dlGetSymFromLib(libHandle, + "liblocationservice_glue.so", "setOptInStatus"); + if (setter != nullptr) { + sessionId = (*setter)(userConsent, &gData.controlCallbacks.responseCb); + } else { + LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so"); + } + return sessionId; +} diff --git a/gps/location/LocationAPI.h b/gps/location/LocationAPI.h new file mode 100644 index 0000000..7c70506 --- /dev/null +++ b/gps/location/LocationAPI.h @@ -0,0 +1,512 @@ +/* Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LOCATIONAPI_H +#define LOCATIONAPI_H + +#include "ILocationAPI.h" + +class LocationAPI : public ILocationAPI +{ +private: + LocationAPI(); + ~LocationAPI(); + +public: + /* creates an instance to LocationAPI object. + Will return NULL if mandatory parameters are invalid or if the maximum number + of instances have been reached */ + static LocationAPI* createInstance(LocationCallbacks&); + + /* destroy/cleans up the instance, which should be called when LocationControlAPI object is + no longer needed. LocationControlAPI* returned from createInstance will no longer valid + after destroy is called. + If the caller allocates the memory for LocationControlCallbacks used in + LocationControlAPI::createInstance, then the caller must ensure that the memory still remains + valid until destroyCompleteCb is invoked. + */ + void destroy(locationApiDestroyCompleteCallback destroyCompleteCb=nullptr); + + void onRemoveClientCompleteCb (LocationAdapterTypeMask adapterType); + + /* updates/changes the callbacks that will be called. + mandatory callbacks must be present for callbacks to be successfully updated + no return value */ + virtual void updateCallbacks(LocationCallbacks&) override; + + /* ================================== TRACKING ================================== */ + + /* startTracking starts a tracking session, which returns a session id that will be + used by the other tracking APIs and also in the responseCallback to match command + with response. locations are reported on the trackingCallback passed in createInstance + periodically according to LocationOptions. + responseCallback returns: + LOCATION_ERROR_SUCCESS if session was successfully started + LOCATION_ERROR_ALREADY_STARTED if a startTracking session is already in progress + LOCATION_ERROR_CALLBACK_MISSING if no trackingCallback was passed in createInstance + LOCATION_ERROR_INVALID_PARAMETER if TrackingOptions parameter is invalid */ + virtual uint32_t startTracking(TrackingOptions&) override; + + /* stopTracking stops a tracking session associated with id parameter. + responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_ID_UNKNOWN if id is not associated with a tracking session */ + virtual void stopTracking(uint32_t id) override; + + /* updateTrackingOptions changes the TrackingOptions of a tracking session associated with id + responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_INVALID_PARAMETER if TrackingOptions parameters are invalid + LOCATION_ERROR_ID_UNKNOWN if id is not associated with a tracking session */ + virtual void updateTrackingOptions(uint32_t id, TrackingOptions&) override; + + /* ================================== BATCHING ================================== */ + + /* startBatching starts a batching session, which returns a session id that will be + used by the other batching APIs and also in the responseCallback to match command + with response. locations are reported on the batchingCallback passed in createInstance + periodically according to LocationOptions. A batching session starts tracking on + the low power processor and delivers them in batches by the batchingCallback when + the batch is full or when getBatchedLocations is called. This allows for the processor + that calls this API to sleep when the low power processor can batch locations in the + backgroup and wake up the processor calling the API only when the batch is full, thus + saving power + responseCallback returns: + LOCATION_ERROR_SUCCESS if session was successful + LOCATION_ERROR_ALREADY_STARTED if a startBatching session is already in progress + LOCATION_ERROR_CALLBACK_MISSING if no batchingCallback was passed in createInstance + LOCATION_ERROR_INVALID_PARAMETER if a parameter is invalid + LOCATION_ERROR_NOT_SUPPORTED if batching is not supported */ + virtual uint32_t startBatching(BatchingOptions&) override; + + /* stopBatching stops a batching session associated with id parameter. + responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_ID_UNKNOWN if id is not associated with batching session */ + virtual void stopBatching(uint32_t id) override; + + /* updateBatchingOptions changes the BatchingOptions of a batching session associated with id + responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_INVALID_PARAMETER if BatchingOptions parameters are invalid + LOCATION_ERROR_ID_UNKNOWN if id is not associated with a batching session */ + virtual void updateBatchingOptions(uint32_t id, BatchingOptions&) override; + + /* getBatchedLocations gets a number of locations that are currently stored/batched + on the low power processor, delivered by the batchingCallback passed in createInstance. + Location are then deleted from the batch stored on the low power processor. + responseCallback returns: + LOCATION_ERROR_SUCCESS if successful, will be followed by batchingCallback call + LOCATION_ERROR_CALLBACK_MISSING if no batchingCallback was passed in createInstance + LOCATION_ERROR_ID_UNKNOWN if id is not associated with a batching session */ + virtual void getBatchedLocations(uint32_t id, size_t count) override; + + /* ================================== GEOFENCE ================================== */ + + /* addGeofences adds any number of geofences and returns an array of geofence ids that + will be used by the other geofence APIs and also in the collectiveResponseCallback to + match command with response. The geofenceBreachCallback will deliver the status of each + geofence according to the GeofenceOption for each. The geofence id array returned will + be valid until the collectiveResponseCallback is called and has returned. + collectiveResponseCallback returns: + LOCATION_ERROR_SUCCESS if session was successful + LOCATION_ERROR_CALLBACK_MISSING if no geofenceBreachCallback + LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid + LOCATION_ERROR_NOT_SUPPORTED if geofence is not supported */ + virtual uint32_t* addGeofences(size_t count, GeofenceOption*, GeofenceInfo*) override; + + /* removeGeofences removes any number of geofences. Caller should delete ids array after + removeGeofences returneds. + collectiveResponseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_ID_UNKNOWN if id is not associated with a geofence session */ + virtual void removeGeofences(size_t count, uint32_t* ids) override; + + /* modifyGeofences modifies any number of geofences. Caller should delete ids array after + modifyGeofences returns. + collectiveResponseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_ID_UNKNOWN if id is not associated with a geofence session + LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid */ + virtual void modifyGeofences(size_t count, uint32_t* ids, GeofenceOption* options) override; + + /* pauseGeofences pauses any number of geofences, which is similar to removeGeofences, + only that they can be resumed at any time. Caller should delete ids array after + pauseGeofences returns. + collectiveResponseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_ID_UNKNOWN if id is not associated with a geofence session */ + virtual void pauseGeofences(size_t count, uint32_t* ids) override; + + /* resumeGeofences resumes any number of geofences that are currently paused. Caller should + delete ids array after resumeGeofences returns. + collectiveResponseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_ID_UNKNOWN if id is not associated with a geofence session */ + virtual void resumeGeofences(size_t count, uint32_t* ids) override; + + /* ================================== GNSS ====================================== */ + + /* gnssNiResponse is called in response to a gnssNiCallback. + responseCallback returns: + LOCATION_ERROR_SUCCESS if session was successful + LOCATION_ERROR_INVALID_PARAMETER if any parameters in GnssNiResponse are invalid + LOCATION_ERROR_ID_UNKNOWN if id does not match a gnssNiCallback */ + virtual void gnssNiResponse(uint32_t id, GnssNiResponse response) override; + + /* ================================== NETWORK PROVIDER =========================== */ + + /* enableNetworkProvider enables Network Provider */ + virtual void enableNetworkProvider(); + + /* disableNetworkProvider disables Network Provider */ + virtual void disableNetworkProvider(); + + /* startNetworkLocation start a single shot network location request */ + virtual void startNetworkLocation(trackingCallback* callback); + + /* stopNetworkLocation stop any ongoing network location request */ + virtual void stopNetworkLocation(trackingCallback* callback); +}; + +typedef struct { + size_t size; // set to sizeof(LocationControlCallbacks) + responseCallback responseCb; // mandatory + collectiveResponseCallback collectiveResponseCb; // mandatory + gnssConfigCallback gnssConfigCb; // optional +} LocationControlCallbacks; + +class LocationControlAPI : public ILocationControlAPI +{ +private: + LocationControlAPI(); + ~LocationControlAPI(); + +public: + /* creates an instance to LocationControlAPI object. + Will return NULL if mandatory parameters are invalid or if the maximum number + of instances have been reached. Only once instance allowed */ + static LocationControlAPI* createInstance(LocationControlCallbacks&); + + /* destroy/cleans up the instance, which should be called when LocationControlAPI object is + no longer needed. LocationControlAPI* returned from createInstance will no longer valid + after destroy is called */ + void destroy(); + + /* enable will enable specific location technology to be used for calculation locations and + will effectively start a control session if call is successful, which returns a session id + that will be returned in responseCallback to match command with response. The session id is + also needed to call the disable command. + This effect is global for all clients of LocationAPI + responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_ALREADY_STARTED if an enable was already called for this techType + LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid + LOCATION_ERROR_GENERAL_FAILURE if failure for any other reason */ + uint32_t enable(LocationTechnologyType techType); + + /* disable will disable specific location technology to be used for calculation locations and + effectively ends the control session if call is successful. + id parameter is the session id that was returned in enable responseCallback for techType. + The session id is no longer valid after disable's responseCallback returns success. + This effect is global for all clients of LocationAPI + responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_ID_UNKNOWN if id was not returned from responseCallback from enable + LOCATION_ERROR_GENERAL_FAILURE if failure for any other reason */ + void disable(uint32_t id); + + /* gnssUpdateConfig updates the gnss specific configuration, which returns a session id array + with an id for each of the bits set in GnssConfig.flags, order from low bits to high bits. + The response for each config that is set will be returned in collectiveResponseCallback. + The session id array returned will be valid until the collectiveResponseCallback is called + and has returned. This effect is global for all clients of LocationAPI + collectiveResponseCallback returns: + LOCATION_ERROR_SUCCESS if session was successful + LOCATION_ERROR_INVALID_PARAMETER if any other parameters are invalid + LOCATION_ERROR_GENERAL_FAILURE if failure for any other reason + + PLEASE NOTE: It is caller's resposibility to FREE the memory of the return value. + The memory must be freed by delete [].*/ + virtual uint32_t* gnssUpdateConfig(const GnssConfig& config) override; + + /* gnssGetConfig fetches the current constellation and SV configuration + on the GNSS engine. + Returns a session id array with an id for each of the bits set in + the mask parameter, order from low bits to high bits. + Response is sent via the registered gnssConfigCallback. + This effect is global for all clients of LocationAPI + collectiveResponseCallback returns: + LOCATION_ERROR_SUCCESS if session was successful + LOCATION_ERROR_INVALID_PARAMETER if any parameter is invalid + LOCATION_ERROR_CALLBACK_MISSING If no gnssConfigCallback + was passed in createInstance + LOCATION_ERROR_NOT_SUPPORTED If read of requested configuration + is not supported + + PLEASE NOTE: It is caller's resposibility to FREE the memory of the return value. + The memory must be freed by delete [].*/ + uint32_t* gnssGetConfig(GnssConfigFlagsMask mask); + + /* delete specific gnss aiding data for testing, which returns a session id + that will be returned in responseCallback to match command with response. + Only allowed in userdebug builds. This effect is global for all clients of LocationAPI + responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid + LOCATION_ERROR_NOT_SUPPORTED if build is not userdebug */ + virtual uint32_t gnssDeleteAidingData(GnssAidingData& data) override; + + /** @brief + Configure the constellation and SVs to be used by the GNSS engine on + modem. + + @param + constellationEnablementConfig: configuration to enable/disable SV + constellation to be used by SPE engine. When size in + constellationEnablementConfig is set to 0, this indicates to reset SV + constellation configuration to modem NV default. + + blacklistSvConfig: configuration to blacklist or unblacklist SVs + used by SPE engine + + @return + A session id that will be returned in responseCallback to + match command with response. This effect is global for all + clients of LocationAPI responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid + */ + virtual uint32_t configConstellations( + const GnssSvTypeConfig& constellationEnablementConfig, + const GnssSvIdConfig& blacklistSvConfig) override; + + /** @brief + Configure the secondary band of constellations to be used by + the GNSS engine on modem. + + @param + secondaryBandConfig: configuration the secondary band usage + for SPE engine + + @return + A session id that will be returned in responseCallback to + match command with response. This effect is global for all + clients of LocationAPI responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid + */ + virtual uint32_t configConstellationSecondaryBand( + const GnssSvTypeConfig& secondaryBandConfig) override; + + /** @brief + Enable or disable the constrained time uncertainty feature. + + @param + enable: true to enable the constrained time uncertainty + feature and false to disable the constrainted time + uncertainty feature. + + @param + tuncThreshold: this specifies the time uncertainty threshold + that gps engine need to maintain, in units of milli-seconds. + Default is 0.0 meaning that modem default value of time + uncertainty threshold will be used. This parameter is + ignored when requesting to disable this feature. + + @param + energyBudget: this specifies the power budget that gps + engine is allowed to spend to maintain the time uncertainty. + Default is 0 meaning that GPS engine is not constained by + power budget and can spend as much power as needed. The + parameter need to be specified in units of 0.1 milli watt + second. This parameter is ignored requesting to disable this + feature. + + @return + A session id that will be returned in responseCallback to + match command with response. This effect is global for all + clients of LocationAPI responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_INVALID_PARAMETER if any parameters + are invalid + */ + virtual uint32_t configConstrainedTimeUncertainty( + bool enable, float tuncThreshold = 0.0, + uint32_t energyBudget = 0) override; + + /** @brief + Enable or disable position assisted clock estimator feature. + + @param + enable: true to enable position assisted clock estimator and + false to disable the position assisted clock estimator + feature. + + @return + A session id that will be returned in responseCallback to + match command with response. This effect is global for all + clients of LocationAPI responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid + */ + virtual uint32_t configPositionAssistedClockEstimator(bool enable) override; + + /** @brief + Sets the lever arm parameters for the vehicle. + + @param + configInfo: lever arm configuration info regarding below two + types of lever arm info: + a: GNSS Antenna w.r.t the origin at the IMU e.g.: inertial + measurement unit. + b: lever arm parameters regarding the OPF (output frame) + w.r.t the origin (at the GPS Antenna). Vehicle manufacturers + prefer the position output to be tied to a specific point in + the vehicle rather than where the antenna is placed + (midpoint of the rear axle is typical). + + Caller can choose types of lever arm info to configure via the + leverMarkTypeMask. + + @return + A session id that will be returned in responseCallback to + match command with response. This effect is global for all + clients of LocationAPI responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid + */ + virtual uint32_t configLeverArm(const LeverArmConfigInfo& configInfo) override; + + /** @brief + Configure the robust location setting. + + @param + enable: true to enable robust location and false to disable + robust location. + + @param + enableForE911: true to enable robust location when device is + on E911 session and false to disable on E911 session. + This parameter is only valid if robust location is enabled. + + @return + A session id that will be returned in responseCallback to + match command with response. This effect is global for all + clients of LocationAPI responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid + */ + virtual uint32_t configRobustLocation(bool enable, bool enableForE911) override; + + /** @brief + Config the minimal GPS week used by modem GNSS engine. + + @param + minGpsWeek: minimal GPS week to be used by modem GNSS engine. + + @return + A session id that will be returned in responseCallback to + match command with response. This effect is global for all + clients of LocationAPI responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid + */ + virtual uint32_t configMinGpsWeek(uint16_t minGpsWeek) override; + + /** @brief + Configure the vehicle body-to-Sensor mount parameters and + other parameters for dead reckoning position engine. + + @param + dreConfig: vehicle body-to-Sensor mount angles and other + parameters. + + @return + A session id that will be returned in responseCallback to + match command with response. This effect is global for all + clients of LocationAPI responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid + */ + virtual uint32_t configDeadReckoningEngineParams( + const DeadReckoningEngineConfig& dreConfig) override; + + /** @brief + This API is used to instruct the specified engine to be in + the pause/resume state.
+ + When the engine is placed in paused state, the engine will + stop. If there is an on-going session, engine will no longer + produce fixes. In the paused state, calling API to delete + aiding data from the paused engine may not have effect. + Request to delete Aiding data shall be issued after + engine resume.
+ + Currently, only DRE engine will support pause/resume + request. responseCb() will return not supported when request + is made to pause/resume none-DRE engine.
+ + Request to pause/resume DRE engine can be made with or + without an on-going session. With QDR engine, on resume, GNSS + position & heading re-acquisition is needed for DR engine to + engage. If DR engine is already in the requested state, the + request will be no-op.
+ + @param + engType: the engine that is instructed to change its run + state.
+ + engState: the new engine run state that the engine is + instructed to be in.
+ + @return + A session id that will be returned in responseCallback to + match command with response. This effect is global for all + clients of LocationAPI responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid + */ + virtual uint32_t configEngineRunState(PositioningEngineMask engType, + LocEngineRunState engState) override; + + /** @brief + Set the EULA opt-in status from system user. This is used as consent to + use network-based positioning. + + @param + userConsnt: user agrees to use GTP service or not. + + @return + A session id that will be returned in responseCallback to + match command with response. + */ + virtual uint32_t setOptInStatus(bool userConsent); +}; + +#endif /* LOCATIONAPI_H */ diff --git a/gps/location/LocationAPIClientBase.cpp b/gps/location/LocationAPIClientBase.cpp new file mode 100644 index 0000000..4865a16 --- /dev/null +++ b/gps/location/LocationAPIClientBase.cpp @@ -0,0 +1,977 @@ +/* Copyright (c) 2017, 2020 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_NDEBUG 0 +#define LOG_TAG "LocSvc_APIClientBase" + +#include +#include +#include +#include +#include "LocationAPIClientBase.h" + +#define GEOFENCE_SESSION_ID 0xFFFFFFFF +#define CONFIG_SESSION_ID 0xFFFFFFFF + +// LocationAPIControlClient +LocationAPIControlClient::LocationAPIControlClient() : + mEnabled(false) +{ + pthread_mutex_init(&mMutex, nullptr); + + for (int i = 0; i < CTRL_REQUEST_MAX; i++) { + mRequestQueues[i].reset((uint32_t)0); + } + + memset(&mConfig, 0, sizeof(GnssConfig)); + + LocationControlCallbacks locationControlCallbacks; + locationControlCallbacks.size = sizeof(LocationControlCallbacks); + + locationControlCallbacks.responseCb = + [this](LocationError error, uint32_t id) { + onCtrlResponseCb(error, id); + }; + locationControlCallbacks.collectiveResponseCb = + [this](size_t count, LocationError* errors, uint32_t* ids) { + onCtrlCollectiveResponseCb(count, errors, ids); + }; + + mLocationControlAPI = LocationControlAPI::createInstance(locationControlCallbacks); +} + +LocationAPIControlClient::~LocationAPIControlClient() +{ + pthread_mutex_lock(&mMutex); + + if (mLocationControlAPI) { + mLocationControlAPI->destroy(); + mLocationControlAPI = nullptr; + } + + for (int i = 0; i < CTRL_REQUEST_MAX; i++) { + mRequestQueues[i].reset((uint32_t)0); + } + + pthread_mutex_unlock(&mMutex); + + pthread_mutex_destroy(&mMutex); +} + +uint32_t LocationAPIControlClient::locAPIGnssDeleteAidingData(GnssAidingData& data) +{ + uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE; + pthread_mutex_lock(&mMutex); + if (mLocationControlAPI) { + uint32_t session = mLocationControlAPI->gnssDeleteAidingData(data); + LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, session); + mRequestQueues[CTRL_REQUEST_DELETEAIDINGDATA].reset(session); + mRequestQueues[CTRL_REQUEST_DELETEAIDINGDATA].push(new GnssDeleteAidingDataRequest(*this)); + + retVal = LOCATION_ERROR_SUCCESS; + } + pthread_mutex_unlock(&mMutex); + + return retVal; +} + +uint32_t LocationAPIControlClient::locAPIEnable(LocationTechnologyType techType) +{ + uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE; + pthread_mutex_lock(&mMutex); + if (mEnabled) { + // just return success if already enabled + retVal = LOCATION_ERROR_SUCCESS; + } else if (mLocationControlAPI) { + uint32_t session = mLocationControlAPI->enable(techType); + LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, session); + mRequestQueues[CTRL_REQUEST_CONTROL].reset(session); + mRequestQueues[CTRL_REQUEST_CONTROL].push(new EnableRequest(*this)); + retVal = LOCATION_ERROR_SUCCESS; + mEnabled = true; + } else { + LOC_LOGE("%s:%d] failed.", __FUNCTION__, __LINE__); + } + pthread_mutex_unlock(&mMutex); + + return retVal; +} + +void LocationAPIControlClient::locAPIDisable() +{ + pthread_mutex_lock(&mMutex); + if (mEnabled && mLocationControlAPI) { + uint32_t session = 0; + session = mRequestQueues[CTRL_REQUEST_CONTROL].getSession(); + if (session > 0) { + mRequestQueues[CTRL_REQUEST_CONTROL].push(new DisableRequest(*this)); + mLocationControlAPI->disable(session); + mEnabled = false; + } else { + LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__, session); + } + } + pthread_mutex_unlock(&mMutex); +} + +uint32_t LocationAPIControlClient::locAPIGnssUpdateConfig(GnssConfig config) +{ + uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE; + + pthread_mutex_lock(&mMutex); + if (mLocationControlAPI) { + if (mConfig.equals(config)) { + LOC_LOGv("GnssConfig is identical to previous call"); + retVal = LOCATION_ERROR_SUCCESS; + } else { + mConfig = config; + uint32_t* idArray = mLocationControlAPI->gnssUpdateConfig(config); + LOC_LOGv("gnssUpdateConfig return array: %p", idArray); + if (nullptr != idArray) { + if (nullptr != mRequestQueues[CTRL_REQUEST_CONFIG_UPDATE].getSessionArrayPtr()) { + mRequestQueues[CTRL_REQUEST_CONFIG_UPDATE].reset(idArray); + } + mRequestQueues[CTRL_REQUEST_CONFIG_UPDATE].push(new GnssUpdateConfigRequest(*this)); + retVal = LOCATION_ERROR_SUCCESS; + delete [] idArray; + } + } + } + pthread_mutex_unlock(&mMutex); + return retVal; +} + +uint32_t LocationAPIControlClient::locAPIGnssGetConfig(GnssConfigFlagsMask mask) +{ + uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE; + + pthread_mutex_lock(&mMutex); + if (mLocationControlAPI) { + + uint32_t* idArray = mLocationControlAPI->gnssGetConfig(mask); + LOC_LOGv("gnssGetConfig return array: %p", idArray); + if (nullptr != idArray) { + if (nullptr != mRequestQueues[CTRL_REQUEST_CONFIG_GET].getSessionArrayPtr()) { + mRequestQueues[CTRL_REQUEST_CONFIG_GET].reset(idArray); + } + mRequestQueues[CTRL_REQUEST_CONFIG_GET].push(new GnssGetConfigRequest(*this)); + retVal = LOCATION_ERROR_SUCCESS; + delete [] idArray; + } + } + pthread_mutex_unlock(&mMutex); + return retVal; +} + +void LocationAPIControlClient::onCtrlResponseCb(LocationError error, uint32_t id) +{ + if (error != LOCATION_ERROR_SUCCESS) { + LOC_LOGE("%s:%d] ERROR: %d ID: %d", __FUNCTION__, __LINE__, error, id); + } else { + LOC_LOGV("%s:%d] SUCCESS: %d id: %d", __FUNCTION__, __LINE__, error, id); + } + LocationAPIRequest* request = getRequestBySession(id); + if (request) { + request->onResponse(error, id); + delete request; + } +} + +void LocationAPIControlClient::onCtrlCollectiveResponseCb( + size_t count, LocationError* errors, uint32_t* ids) +{ + for (size_t i = 0; i < count; i++) { + if (errors[i] != LOCATION_ERROR_SUCCESS) { + LOC_LOGE("%s:%d] ERROR: %d ID: %d", __FUNCTION__, __LINE__, errors[i], ids[i]); + } else { + LOC_LOGV("%s:%d] SUCCESS: %d id: %d", __FUNCTION__, __LINE__, errors[i], ids[i]); + } + } + LocationAPIRequest* request = getRequestBySessionArrayPtr(ids); + if (request) { + request->onCollectiveResponse(count, errors, ids); + delete request; + } +} + +LocationAPIRequest* LocationAPIControlClient::getRequestBySession(uint32_t session) +{ + pthread_mutex_lock(&mMutex); + LocationAPIRequest* request = nullptr; + + if (mRequestQueues[CTRL_REQUEST_DELETEAIDINGDATA].getSession() == session) { + request = mRequestQueues[CTRL_REQUEST_DELETEAIDINGDATA].pop(); + } else if (mRequestQueues[CTRL_REQUEST_CONTROL].getSession() == session) { + request = mRequestQueues[CTRL_REQUEST_CONTROL].pop(); + } + + pthread_mutex_unlock(&mMutex); + return request; +} + +LocationAPIRequest* +LocationAPIControlClient::getRequestBySessionArrayPtr( + uint32_t* sessionArrayPtr) +{ + pthread_mutex_lock(&mMutex); + LocationAPIRequest* request = nullptr; + + if (mRequestQueues[CTRL_REQUEST_CONFIG_UPDATE].getSessionArrayPtr() == sessionArrayPtr) { + request = mRequestQueues[CTRL_REQUEST_CONFIG_UPDATE].pop(); + } else if (mRequestQueues[CTRL_REQUEST_CONFIG_GET].getSessionArrayPtr() == sessionArrayPtr) { + request = mRequestQueues[CTRL_REQUEST_CONFIG_GET].pop(); + } + + pthread_mutex_unlock(&mMutex); + return request; +} + +// LocationAPIClientBase +LocationAPIClientBase::LocationAPIClientBase() : + mGeofenceBreachCallback(nullptr), + mBatchingStatusCallback(nullptr), + mLocationAPI(nullptr), + mBatchSize(-1), + mTracking(false) +{ + + // use recursive mutex, in case callback come from the same thread + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&mMutex, &attr); + + for (int i = 0; i < REQUEST_MAX; i++) { + mRequestQueues[i].reset((uint32_t)0); + } +} + +void LocationAPIClientBase::locAPISetCallbacks(LocationCallbacks& locationCallbacks) +{ + pthread_mutex_lock(&mMutex); + + if (locationCallbacks.geofenceBreachCb != nullptr) { + mGeofenceBreachCallback = locationCallbacks.geofenceBreachCb; + locationCallbacks.geofenceBreachCb = + [this](GeofenceBreachNotification geofenceBreachNotification) { + beforeGeofenceBreachCb(geofenceBreachNotification); + }; + } + + locationCallbacks.capabilitiesCb = + [this](LocationCapabilitiesMask capabilitiesMask) { + onCapabilitiesCb(capabilitiesMask); + }; + locationCallbacks.responseCb = [this](LocationError error, uint32_t id) { + onResponseCb(error, id); + }; + locationCallbacks.collectiveResponseCb = + [this](size_t count, LocationError* errors, uint32_t* ids) { + onCollectiveResponseCb(count, errors, ids); + }; + + if (locationCallbacks.batchingStatusCb != nullptr) { + mBatchingStatusCallback = locationCallbacks.batchingStatusCb; + locationCallbacks.batchingStatusCb = + [this](BatchingStatusInfo batchStatus, std::list & tripCompletedList) { + beforeBatchingStatusCb(batchStatus, tripCompletedList); + }; + } + + if (mLocationAPI == nullptr ) { + mLocationAPI = LocationAPI::createInstance(locationCallbacks); + } else { + mLocationAPI->updateCallbacks(locationCallbacks); + } + + pthread_mutex_unlock(&mMutex); +} + +void LocationAPIClientBase::destroy() +{ + LOC_LOGD("LocationAPIClientBase::destroy()"); + + pthread_mutex_lock(&mMutex); + + mGeofenceBreachCallback = nullptr; + + for (int i = 0; i < REQUEST_MAX; i++) { + mRequestQueues[i].reset((uint32_t)0); + } + + LocationAPI* localHandle = nullptr; + if (nullptr != mLocationAPI) { + localHandle = mLocationAPI; + mLocationAPI = nullptr; + } + + pthread_mutex_unlock(&mMutex); + + // Invoking destroy has the possibility of destroy complete callback + // being invoked right away in the same context, hence no instance + // member must be accessed after the destroy call. + if (nullptr != localHandle) { + localHandle->destroy([this]() {onLocationApiDestroyCompleteCb();}); + } +} + +LocationAPIClientBase::~LocationAPIClientBase() +{ + pthread_mutex_destroy(&mMutex); +} + +void LocationAPIClientBase::onLocationApiDestroyCompleteCb() +{ + LOC_LOGD("LocationAPIClientBase::onLocationApiDestroyCompleteCb()"); + delete this; +} + +uint32_t LocationAPIClientBase::locAPIStartTracking(TrackingOptions& options) +{ + uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE; + pthread_mutex_lock(&mMutex); + if (mLocationAPI) { + if (mTracking) { + LOC_LOGW("%s:%d] Existing tracking session present", __FUNCTION__, __LINE__); + } else { + uint32_t session = mLocationAPI->startTracking(options); + LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, session); + // onResponseCb might be called from other thread immediately after + // startTracking returns, so we are not going to unlock mutex + // until StartTrackingRequest is pushed into mRequestQueues[REQUEST_TRACKING] + mRequestQueues[REQUEST_TRACKING].reset(session); + mRequestQueues[REQUEST_TRACKING].push(new StartTrackingRequest(*this)); + mTracking = true; + } + + retVal = LOCATION_ERROR_SUCCESS; + } + pthread_mutex_unlock(&mMutex); + + return retVal; +} + +void LocationAPIClientBase::locAPIStopTracking() +{ + pthread_mutex_lock(&mMutex); + if (mLocationAPI) { + uint32_t session = 0; + session = mRequestQueues[REQUEST_TRACKING].getSession(); + if (session > 0) { + mRequestQueues[REQUEST_TRACKING].push(new StopTrackingRequest(*this)); + mLocationAPI->stopTracking(session); + mTracking = false; + } else { + LOC_LOGD("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__, session); + } + } + pthread_mutex_unlock(&mMutex); +} + +void LocationAPIClientBase::locAPIUpdateTrackingOptions(TrackingOptions& options) +{ + pthread_mutex_lock(&mMutex); + if (mLocationAPI) { + uint32_t session = 0; + session = mRequestQueues[REQUEST_TRACKING].getSession(); + if (session > 0) { + mRequestQueues[REQUEST_TRACKING].push(new UpdateTrackingOptionsRequest(*this)); + mLocationAPI->updateTrackingOptions(session, options); + } else { + LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__, session); + } + } + pthread_mutex_unlock(&mMutex); +} + +int32_t LocationAPIClientBase::locAPIGetBatchSize() +{ + if (mBatchSize == -1) { + const loc_param_s_type flp_conf_param_table[] = + { + {"BATCH_SIZE", &mBatchSize, nullptr, 'n'}, + }; + UTIL_READ_CONF(LOC_PATH_FLP_CONF, flp_conf_param_table); + if (mBatchSize < 0) { + // set mBatchSize to 0 if we got an illegal value from config file + mBatchSize = 0; + } + } + return mBatchSize; +} + +uint32_t LocationAPIClientBase::locAPIStartSession( + uint32_t id, uint32_t sessionMode, TrackingOptions&& options) +{ + uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE; + pthread_mutex_lock(&mMutex); + if (mLocationAPI) { + + if (mSessionBiDict.hasId(id)) { + LOC_LOGE("%s:%d] session %d has already started.", __FUNCTION__, __LINE__, id); + retVal = LOCATION_ERROR_ALREADY_STARTED; + } else { + uint32_t trackingSession = 0; + uint32_t batchingSession = 0; + + if (sessionMode == SESSION_MODE_ON_FIX) { + trackingSession = mLocationAPI->startTracking(options); + LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, trackingSession); + mRequestQueues[REQUEST_SESSION].push(new StartTrackingRequest(*this)); + } else { + // Fill in the batch mode + BatchingOptions batchOptions = {}; + batchOptions.size = sizeof(BatchingOptions); + switch (sessionMode) { + case SESSION_MODE_ON_FULL: + batchOptions.batchingMode = BATCHING_MODE_ROUTINE; + break; + case SESSION_MODE_ON_TRIP_COMPLETED: + batchOptions.batchingMode = BATCHING_MODE_TRIP; + break; + default: + batchOptions.batchingMode = BATCHING_MODE_NO_AUTO_REPORT; + break; + } + + // Populate location option values + batchOptions.minDistance = options.minDistance; + batchOptions.minInterval = options.minInterval; + batchOptions.mode = options.mode; + + batchingSession = mLocationAPI->startBatching(batchOptions); + LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, batchingSession); + mRequestQueues[REQUEST_SESSION].setSession(batchingSession); + mRequestQueues[REQUEST_SESSION].push(new StartBatchingRequest(*this)); + } + + uint32_t session = ((sessionMode != SESSION_MODE_ON_FIX) ? + batchingSession : trackingSession); + + SessionEntity entity; + entity.id = id; + entity.trackingSession = trackingSession; + entity.batchingSession = batchingSession; + entity.sessionMode = sessionMode; + mSessionBiDict.set(id, session, entity); + + retVal = LOCATION_ERROR_SUCCESS; + } + + } + pthread_mutex_unlock(&mMutex); + + return retVal; +} + +uint32_t LocationAPIClientBase::locAPIStopSession(uint32_t id) +{ + uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE; + pthread_mutex_lock(&mMutex); + if (mLocationAPI) { + + if (mSessionBiDict.hasId(id)) { + SessionEntity entity = mSessionBiDict.getExtById(id); + + uint32_t trackingSession = entity.trackingSession; + uint32_t batchingSession = entity.batchingSession; + uint32_t sMode = entity.sessionMode; + + if (sMode == SESSION_MODE_ON_FIX) { + mRequestQueues[REQUEST_SESSION].push(new StopTrackingRequest(*this)); + mLocationAPI->stopTracking(trackingSession); + } else { + mRequestQueues[REQUEST_SESSION].push(new StopBatchingRequest(*this)); + mLocationAPI->stopBatching(batchingSession); + } + + retVal = LOCATION_ERROR_SUCCESS; + } else { + retVal = LOCATION_ERROR_ID_UNKNOWN; + LOC_LOGE("%s:%d] session %d is not exist.", __FUNCTION__, __LINE__, id); + } + + } + pthread_mutex_unlock(&mMutex); + return retVal; +} + +uint32_t LocationAPIClientBase::locAPIUpdateSessionOptions( + uint32_t id, uint32_t sessionMode, TrackingOptions&& options) +{ + uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE; + pthread_mutex_lock(&mMutex); + if (mLocationAPI) { + + if (mSessionBiDict.hasId(id)) { + SessionEntity entity = mSessionBiDict.getExtById(id); + + uint32_t trackingSession = entity.trackingSession; + uint32_t batchingSession = entity.batchingSession; + uint32_t sMode = entity.sessionMode; + + if (sessionMode == SESSION_MODE_ON_FIX) { + // we only add an UpdateTrackingOptionsRequest to mRequestQueues[REQUEST_SESSION], + // even if this update request will stop batching and then start tracking. + mRequestQueues[REQUEST_SESSION].push(new UpdateTrackingOptionsRequest(*this)); + if (sMode == SESSION_MODE_ON_FIX) { + mLocationAPI->updateTrackingOptions(trackingSession, options); + } else { + // stop batching + // batchingSession will be removed from mSessionBiDict soon, + // so we don't need to add a new request to mRequestQueues[REQUEST_SESSION]. + mLocationAPI->stopBatching(batchingSession); + batchingSession = 0; + mRequestQueues[REQUEST_SESSION].setSession(batchingSession); + + // start tracking + trackingSession = mLocationAPI->startTracking(options); + LOC_LOGI("%s:%d] start new session: %d", + __FUNCTION__, __LINE__, trackingSession); + } + } else { + // we only add an UpdateBatchingOptionsRequest to mRequestQueues[REQUEST_SESSION], + // even if this update request will stop tracking and then start batching. + mRequestQueues[REQUEST_SESSION].push(new UpdateBatchingOptionsRequest(*this)); + BatchingOptions batchOptions = {}; + batchOptions.size = sizeof(BatchingOptions); + switch (sessionMode) { + case SESSION_MODE_ON_FULL: + batchOptions.batchingMode = BATCHING_MODE_ROUTINE; + break; + case SESSION_MODE_ON_TRIP_COMPLETED: + batchOptions.batchingMode = BATCHING_MODE_TRIP; + break; + default: + batchOptions.batchingMode = BATCHING_MODE_NO_AUTO_REPORT; + break; + } + + if (sMode == SESSION_MODE_ON_FIX) { + // stop tracking + // trackingSession will be removed from mSessionBiDict soon, + // so we don't need to add a new request to mRequestQueues[REQUEST_SESSION]. + mLocationAPI->stopTracking(trackingSession); + trackingSession = 0; + + // Populate location option values + batchOptions.minDistance = options.minDistance; + batchOptions.minInterval = options.minInterval; + batchOptions.mode = options.mode; + + // start batching + batchingSession = mLocationAPI->startBatching(batchOptions); + LOC_LOGI("%s:%d] start new session: %d", + __FUNCTION__, __LINE__, batchingSession); + mRequestQueues[REQUEST_SESSION].setSession(batchingSession); + } else { + mLocationAPI->updateBatchingOptions(batchingSession, batchOptions); + } + + } + + uint32_t session = ((sessionMode != SESSION_MODE_ON_FIX) ? + batchingSession : trackingSession); + + entity.trackingSession = trackingSession; + entity.batchingSession = batchingSession; + entity.sessionMode = sessionMode; + // remove the old values from mSessionBiDict before we add a new one. + mSessionBiDict.rmById(id); + mSessionBiDict.set(id, session, entity); + + retVal = LOCATION_ERROR_SUCCESS; + } else { + retVal = LOCATION_ERROR_ID_UNKNOWN; + LOC_LOGE("%s:%d] session %d is not exist.", __FUNCTION__, __LINE__, id); + } + } + pthread_mutex_unlock(&mMutex); + return retVal; +} + +uint32_t LocationAPIClientBase::locAPIGetBatchedLocations(uint32_t id, size_t count) +{ + uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE; + pthread_mutex_lock(&mMutex); + if (mLocationAPI) { + if (mSessionBiDict.hasId(id)) { + SessionEntity entity = mSessionBiDict.getExtById(id); + if (entity.sessionMode != SESSION_MODE_ON_FIX) { + uint32_t batchingSession = entity.batchingSession; + mRequestQueues[REQUEST_SESSION].push(new GetBatchedLocationsRequest(*this)); + mLocationAPI->getBatchedLocations(batchingSession, count); + retVal = LOCATION_ERROR_SUCCESS; + } else { + LOC_LOGE("%s:%d] Unsupported for session id: %d, mode is SESSION_MODE_ON_FIX", + __FUNCTION__, __LINE__, id); + retVal = LOCATION_ERROR_NOT_SUPPORTED; + } + } else { + retVal = LOCATION_ERROR_ID_UNKNOWN; + LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__, id); + } + } + pthread_mutex_unlock(&mMutex); + + return retVal; +} + +uint32_t LocationAPIClientBase::locAPIAddGeofences( + size_t count, uint32_t* ids, GeofenceOption* options, GeofenceInfo* data) +{ + uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE; + pthread_mutex_lock(&mMutex); + if (mLocationAPI) { + if (mRequestQueues[REQUEST_GEOFENCE].getSession() != GEOFENCE_SESSION_ID) { + mRequestQueues[REQUEST_GEOFENCE].reset(GEOFENCE_SESSION_ID); + } + uint32_t* sessions = mLocationAPI->addGeofences(count, options, data); + if (sessions) { + LOC_LOGI("%s:%d] start new sessions: %p", __FUNCTION__, __LINE__, sessions); + mRequestQueues[REQUEST_GEOFENCE].push(new AddGeofencesRequest(*this)); + + for (size_t i = 0; i < count; i++) { + mGeofenceBiDict.set(ids[i], sessions[i], options[i].breachTypeMask); + } + retVal = LOCATION_ERROR_SUCCESS; + } + } + pthread_mutex_unlock(&mMutex); + + return retVal; +} + +void LocationAPIClientBase::locAPIRemoveGeofences(size_t count, uint32_t* ids) +{ + pthread_mutex_lock(&mMutex); + if (mLocationAPI) { + uint32_t* sessions = (uint32_t*)malloc(sizeof(uint32_t) * count); + if (sessions == NULL) { + LOC_LOGE("%s:%d] Failed to allocate %zu bytes !", + __FUNCTION__, __LINE__, sizeof(uint32_t) * count); + pthread_mutex_unlock(&mMutex); + return; + } + + if (mRequestQueues[REQUEST_GEOFENCE].getSession() == GEOFENCE_SESSION_ID) { + BiDict* removedGeofenceBiDict = + new BiDict(); + size_t j = 0; + for (size_t i = 0; i < count; i++) { + sessions[j] = mGeofenceBiDict.getSession(ids[i]); + if (sessions[j] > 0) { + GeofenceBreachTypeMask type = mGeofenceBiDict.getExtBySession(sessions[j]); + mGeofenceBiDict.rmBySession(sessions[j]); + removedGeofenceBiDict->set(ids[i], sessions[j], type); + j++; + } + } + if (j > 0) { + mRequestQueues[REQUEST_GEOFENCE].push(new RemoveGeofencesRequest(*this, + removedGeofenceBiDict)); + mLocationAPI->removeGeofences(j, sessions); + } else { + delete(removedGeofenceBiDict); + } + } else { + LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__, + mRequestQueues[REQUEST_GEOFENCE].getSession()); + } + + free(sessions); + } + pthread_mutex_unlock(&mMutex); +} + +void LocationAPIClientBase::locAPIModifyGeofences( + size_t count, uint32_t* ids, GeofenceOption* options) +{ + pthread_mutex_lock(&mMutex); + if (mLocationAPI) { + uint32_t* sessions = (uint32_t*)malloc(sizeof(uint32_t) * count); + if (sessions == NULL) { + LOC_LOGE("%s:%d] Failed to allocate %zu bytes !", + __FUNCTION__, __LINE__, sizeof(uint32_t) * count); + pthread_mutex_unlock(&mMutex); + return; + } + + if (mRequestQueues[REQUEST_GEOFENCE].getSession() == GEOFENCE_SESSION_ID) { + size_t j = 0; + for (size_t i = 0; i < count; i++) { + sessions[j] = mGeofenceBiDict.getSession(ids[i]); + if (sessions[j] > 0) { + mGeofenceBiDict.set(ids[i], sessions[j], options[i].breachTypeMask); + j++; + } + } + if (j > 0) { + mRequestQueues[REQUEST_GEOFENCE].push(new ModifyGeofencesRequest(*this)); + mLocationAPI->modifyGeofences(j, sessions, options); + } + } else { + LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__, + mRequestQueues[REQUEST_GEOFENCE].getSession()); + } + + free(sessions); + } + pthread_mutex_unlock(&mMutex); +} + +void LocationAPIClientBase::locAPIPauseGeofences(size_t count, uint32_t* ids) +{ + pthread_mutex_lock(&mMutex); + if (mLocationAPI) { + uint32_t* sessions = (uint32_t*)malloc(sizeof(uint32_t) * count); + if (sessions == NULL) { + LOC_LOGE("%s:%d] Failed to allocate %zu bytes !", + __FUNCTION__, __LINE__, sizeof(uint32_t) * count); + pthread_mutex_unlock(&mMutex); + return; + } + + if (mRequestQueues[REQUEST_GEOFENCE].getSession() == GEOFENCE_SESSION_ID) { + size_t j = 0; + for (size_t i = 0; i < count; i++) { + sessions[j] = mGeofenceBiDict.getSession(ids[i]); + if (sessions[j] > 0) { + j++; + } + } + if (j > 0) { + mRequestQueues[REQUEST_GEOFENCE].push(new PauseGeofencesRequest(*this)); + mLocationAPI->pauseGeofences(j, sessions); + } + } else { + LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__, + mRequestQueues[REQUEST_GEOFENCE].getSession()); + } + + free(sessions); + } + pthread_mutex_unlock(&mMutex); +} + +void LocationAPIClientBase::locAPIResumeGeofences( + size_t count, uint32_t* ids, GeofenceBreachTypeMask* mask) +{ + pthread_mutex_lock(&mMutex); + if (mLocationAPI) { + uint32_t* sessions = (uint32_t*)malloc(sizeof(uint32_t) * count); + if (sessions == NULL) { + LOC_LOGE("%s:%d] Failed to allocate %zu bytes !", + __FUNCTION__, __LINE__, sizeof(uint32_t) * count); + pthread_mutex_unlock(&mMutex); + return; + } + + if (mRequestQueues[REQUEST_GEOFENCE].getSession() == GEOFENCE_SESSION_ID) { + size_t j = 0; + for (size_t i = 0; i < count; i++) { + sessions[j] = mGeofenceBiDict.getSession(ids[i]); + if (sessions[j] > 0) { + if (mask) { + mGeofenceBiDict.set(ids[i], sessions[j], mask[i]); + } + j++; + } + } + if (j > 0) { + mRequestQueues[REQUEST_GEOFENCE].push(new ResumeGeofencesRequest(*this)); + mLocationAPI->resumeGeofences(j, sessions); + } + } else { + LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__, + mRequestQueues[REQUEST_GEOFENCE].getSession()); + } + + free(sessions); + } + pthread_mutex_unlock(&mMutex); +} + +void LocationAPIClientBase::locAPIRemoveAllGeofences() +{ + std::vector sessionsVec = mGeofenceBiDict.getAllSessions(); + if (sessionsVec.size() > 0) { + locAPIRemoveGeofences(sessionsVec.size(), &sessionsVec[0]); + } +} + +void LocationAPIClientBase::locAPIGnssNiResponse(uint32_t id, GnssNiResponse response) +{ + pthread_mutex_lock(&mMutex); + if (mLocationAPI) { + uint32_t session = id; + mLocationAPI->gnssNiResponse(id, response); + LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, session); + mRequestQueues[REQUEST_NIRESPONSE].reset(session); + mRequestQueues[REQUEST_NIRESPONSE].push(new GnssNiResponseRequest(*this)); + } + pthread_mutex_unlock(&mMutex); +} + +void LocationAPIClientBase::beforeGeofenceBreachCb( + GeofenceBreachNotification geofenceBreachNotification) +{ + uint32_t* ids = (uint32_t*)malloc(sizeof(uint32_t) * geofenceBreachNotification.count); + uint32_t* backup = geofenceBreachNotification.ids; + size_t n = geofenceBreachNotification.count; + geofenceBreachCallback genfenceCallback = nullptr; + + if (ids == NULL) { + LOC_LOGE("%s:%d] Failed to alloc %zu bytes", + __FUNCTION__, __LINE__, + sizeof(uint32_t) * geofenceBreachNotification.count); + return; + } + + pthread_mutex_lock(&mMutex); + if (mGeofenceBreachCallback != nullptr) { + size_t count = 0; + for (size_t i = 0; i < n; i++) { + uint32_t id = mGeofenceBiDict.getId(geofenceBreachNotification.ids[i]); + GeofenceBreachTypeMask type = + mGeofenceBiDict.getExtBySession(geofenceBreachNotification.ids[i]); + // if type == 0, we will not head into the fllowing block anyway. + // so we don't need to check id and type + if ((geofenceBreachNotification.type == GEOFENCE_BREACH_ENTER && + (type & GEOFENCE_BREACH_ENTER_BIT)) || + (geofenceBreachNotification.type == GEOFENCE_BREACH_EXIT && + (type & GEOFENCE_BREACH_EXIT_BIT)) + ) { + ids[count] = id; + count++; + } + } + geofenceBreachNotification.count = count; + geofenceBreachNotification.ids = ids; + + genfenceCallback = mGeofenceBreachCallback; + } + pthread_mutex_unlock(&mMutex); + + if (genfenceCallback != nullptr) { + genfenceCallback(geofenceBreachNotification); + } + + // restore ids + geofenceBreachNotification.ids = backup; + geofenceBreachNotification.count = n; + free(ids); +} + +void LocationAPIClientBase::beforeBatchingStatusCb(BatchingStatusInfo batchStatus, + std::list & tripCompletedList) { + + // map the trip ids to the client ids + std::list tripCompletedClientIdList; + tripCompletedClientIdList.clear(); + + if (batchStatus.batchingStatus == BATCHING_STATUS_TRIP_COMPLETED) { + for (auto itt = tripCompletedList.begin(); itt != tripCompletedList.end(); itt++) { + if (mSessionBiDict.hasSession(*itt)) { + SessionEntity sessEntity = mSessionBiDict.getExtBySession(*itt); + + if (sessEntity.sessionMode == SESSION_MODE_ON_TRIP_COMPLETED) { + tripCompletedClientIdList.push_back(sessEntity.id); + mSessionBiDict.rmBySession(*itt); + } + } + } + } + + mBatchingStatusCallback(batchStatus, tripCompletedClientIdList); +} + +void LocationAPIClientBase::onResponseCb(LocationError error, uint32_t id) +{ + if (error != LOCATION_ERROR_SUCCESS) { + LOC_LOGE("%s:%d] ERROR: %d ID: %d", __FUNCTION__, __LINE__, error, id); + } else { + LOC_LOGV("%s:%d] SUCCESS: %d id: %d", __FUNCTION__, __LINE__, error, id); + } + LocationAPIRequest* request = getRequestBySession(id); + if (request) { + request->onResponse(error, id); + delete request; + } +} + +void LocationAPIClientBase::onCollectiveResponseCb( + size_t count, LocationError* errors, uint32_t* ids) +{ + for (size_t i = 0; i < count; i++) { + if (errors[i] != LOCATION_ERROR_SUCCESS) { + LOC_LOGE("%s:%d] ERROR: %d ID: %d", __FUNCTION__, __LINE__, errors[i], ids[i]); + } else { + LOC_LOGV("%s:%d] SUCCESS: %d id: %d", __FUNCTION__, __LINE__, errors[i], ids[i]); + } + } + LocationAPIRequest* request = nullptr; + pthread_mutex_lock(&mMutex); + if (mRequestQueues[REQUEST_GEOFENCE].getSession() == GEOFENCE_SESSION_ID) { + request = mRequestQueues[REQUEST_GEOFENCE].pop(); + } + pthread_mutex_unlock(&mMutex); + if (request) { + request->onCollectiveResponse(count, errors, ids); + delete request; + } +} + +void LocationAPIClientBase::removeSession(uint32_t session) { + if (mSessionBiDict.hasSession(session)) { + mSessionBiDict.rmBySession(session); + } +} + +LocationAPIRequest* LocationAPIClientBase::getRequestBySession(uint32_t session) +{ + pthread_mutex_lock(&mMutex); + LocationAPIRequest* request = nullptr; + for (int i = 0; i < REQUEST_MAX; i++) { + if (i != REQUEST_GEOFENCE && + i != REQUEST_SESSION && + mRequestQueues[i].getSession() == session) { + request = mRequestQueues[i].pop(); + break; + } + } + if (request == nullptr) { + // Can't find a request with correct session, + // try to find it from mSessionBiDict + if (mSessionBiDict.hasSession(session)) { + request = mRequestQueues[REQUEST_SESSION].pop(); + } + } + pthread_mutex_unlock(&mMutex); + return request; +} diff --git a/gps/location/LocationAPIClientBase.h b/gps/location/LocationAPIClientBase.h new file mode 100644 index 0000000..ac1ebe6 --- /dev/null +++ b/gps/location/LocationAPIClientBase.h @@ -0,0 +1,592 @@ +/* Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LOCATION_API_CLINET_BASE_H +#define LOCATION_API_CLINET_BASE_H + +#include +#include +#include +#include +#include + +#include "LocationAPI.h" +#include +#include + +enum SESSION_MODE { + SESSION_MODE_NONE = 0, + SESSION_MODE_ON_FULL, + SESSION_MODE_ON_FIX, + SESSION_MODE_ON_TRIP_COMPLETED +}; + +enum REQUEST_TYPE { + REQUEST_TRACKING = 0, + REQUEST_SESSION, + REQUEST_GEOFENCE, + REQUEST_NIRESPONSE, + REQUEST_MAX, +}; + +enum CTRL_REQUEST_TYPE { + CTRL_REQUEST_DELETEAIDINGDATA = 0, + CTRL_REQUEST_CONTROL, + CTRL_REQUEST_CONFIG_UPDATE, + CTRL_REQUEST_CONFIG_GET, + CTRL_REQUEST_MAX, +}; + +class LocationAPIClientBase; + +class LocationAPIRequest { +public: + LocationAPIRequest() {} + virtual ~LocationAPIRequest() {} + virtual void onResponse(LocationError /*error*/, uint32_t /*id*/) {} + virtual void onCollectiveResponse( + size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {} +}; + +class RequestQueue { +public: + RequestQueue(): mSession(0), mSessionArrayPtr(nullptr) { + } + virtual ~RequestQueue() { + reset((uint32_t)0); + } + void inline setSession(uint32_t session) { mSession = session; } + void inline setSessionArrayPtr(uint32_t* ptr) { mSessionArrayPtr = ptr; } + void reset(uint32_t session) { + LocationAPIRequest* request = nullptr; + while (!mQueue.empty()) { + request = mQueue.front(); + mQueue.pop(); + delete request; + } + mSession = session; + } + void reset(uint32_t* sessionArrayPtr) { + reset((uint32_t)0); + mSessionArrayPtr = sessionArrayPtr; + } + void push(LocationAPIRequest* request) { + mQueue.push(request); + } + LocationAPIRequest* pop() { + LocationAPIRequest* request = nullptr; + if (!mQueue.empty()) { + request = mQueue.front(); + mQueue.pop(); + } + return request; + } + uint32_t getSession() { return mSession; } + uint32_t* getSessionArrayPtr() { return mSessionArrayPtr; } +private: + uint32_t mSession; + uint32_t* mSessionArrayPtr; + std::queue mQueue; +}; + +class LocationAPIControlClient { +public: + LocationAPIControlClient(); + virtual ~LocationAPIControlClient(); + LocationAPIControlClient(const LocationAPIControlClient&) = delete; + LocationAPIControlClient& operator=(const LocationAPIControlClient&) = delete; + + LocationAPIRequest* getRequestBySession(uint32_t session); + LocationAPIRequest* getRequestBySessionArrayPtr(uint32_t* sessionArrayPtr); + + // LocationControlAPI + uint32_t locAPIGnssDeleteAidingData(GnssAidingData& data); + uint32_t locAPIEnable(LocationTechnologyType techType); + void locAPIDisable(); + uint32_t locAPIGnssUpdateConfig(GnssConfig config); + uint32_t locAPIGnssGetConfig(GnssConfigFlagsMask config); + inline LocationControlAPI* getControlAPI() { return mLocationControlAPI; } + + // callbacks + void onCtrlResponseCb(LocationError error, uint32_t id); + void onCtrlCollectiveResponseCb(size_t count, LocationError* errors, uint32_t* ids); + + inline virtual void onGnssDeleteAidingDataCb(LocationError /*error*/) {} + inline virtual void onEnableCb(LocationError /*error*/) {} + inline virtual void onDisableCb(LocationError /*error*/) {} + inline virtual void onGnssUpdateConfigCb( + size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {} + inline virtual void onGnssGetConfigCb( + size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {} + + class GnssDeleteAidingDataRequest : public LocationAPIRequest { + public: + GnssDeleteAidingDataRequest(LocationAPIControlClient& API) : mAPI(API) {} + inline void onResponse(LocationError error, uint32_t /*id*/) { + mAPI.onGnssDeleteAidingDataCb(error); + } + LocationAPIControlClient& mAPI; + }; + + class EnableRequest : public LocationAPIRequest { + public: + EnableRequest(LocationAPIControlClient& API) : mAPI(API) {} + inline void onResponse(LocationError error, uint32_t /*id*/) { + mAPI.onEnableCb(error); + } + LocationAPIControlClient& mAPI; + }; + + class DisableRequest : public LocationAPIRequest { + public: + DisableRequest(LocationAPIControlClient& API) : mAPI(API) {} + inline void onResponse(LocationError error, uint32_t /*id*/) { + mAPI.onDisableCb(error); + } + LocationAPIControlClient& mAPI; + }; + + class GnssUpdateConfigRequest : public LocationAPIRequest { + public: + GnssUpdateConfigRequest(LocationAPIControlClient& API) : mAPI(API) {} + inline void onCollectiveResponse(size_t count, LocationError* errors, uint32_t* ids) { + mAPI.onGnssUpdateConfigCb(count, errors, ids); + } + LocationAPIControlClient& mAPI; + }; + + class GnssGetConfigRequest : public LocationAPIRequest { + public: + GnssGetConfigRequest(LocationAPIControlClient& API) : mAPI(API) {} + inline void onCollectiveResponse(size_t count, LocationError* errors, uint32_t* ids) { + mAPI.onGnssGetConfigCb(count, errors, ids); + } + LocationAPIControlClient& mAPI; + }; + +private: + pthread_mutex_t mMutex; + LocationControlAPI* mLocationControlAPI; + RequestQueue mRequestQueues[CTRL_REQUEST_MAX]; + bool mEnabled; + GnssConfig mConfig; +}; + +class LocationAPIClientBase { +public: + LocationAPIClientBase(); + LocationAPIClientBase(const LocationAPIClientBase&) = delete; + LocationAPIClientBase& operator=(const LocationAPIClientBase&) = delete; + + void destroy(); + void onLocationApiDestroyCompleteCb(); + + void locAPISetCallbacks(LocationCallbacks& locationCallbacks); + void removeSession(uint32_t session); + LocationAPIRequest* getRequestBySession(uint32_t session); + + // LocationAPI + uint32_t locAPIStartTracking(TrackingOptions& trackingOptions); + void locAPIStopTracking(); + void locAPIUpdateTrackingOptions(TrackingOptions& trackingOptions); + + int32_t locAPIGetBatchSize(); + uint32_t locAPIStartSession( + uint32_t id, uint32_t sessionMode, TrackingOptions&& trackingOptions); + uint32_t locAPIStopSession(uint32_t id); + uint32_t locAPIUpdateSessionOptions( + uint32_t id, uint32_t sessionMode, TrackingOptions&& trackingOptions); + uint32_t locAPIGetBatchedLocations(uint32_t id, size_t count); + + uint32_t locAPIAddGeofences(size_t count, uint32_t* ids, + GeofenceOption* options, GeofenceInfo* data); + void locAPIRemoveGeofences(size_t count, uint32_t* ids); + void locAPIModifyGeofences(size_t count, uint32_t* ids, GeofenceOption* options); + void locAPIPauseGeofences(size_t count, uint32_t* ids); + void locAPIResumeGeofences(size_t count, uint32_t* ids, GeofenceBreachTypeMask* mask); + void locAPIRemoveAllGeofences(); + + void locAPIGnssNiResponse(uint32_t id, GnssNiResponse response); + + // callbacks + void onResponseCb(LocationError error, uint32_t id); + void onCollectiveResponseCb(size_t count, LocationError* errors, uint32_t* ids); + + void beforeGeofenceBreachCb(GeofenceBreachNotification geofenceBreachNotification); + + inline virtual void onCapabilitiesCb(LocationCapabilitiesMask /*capabilitiesMask*/) {} + inline virtual void onGnssNmeaCb(GnssNmeaNotification /*gnssNmeaNotification*/) {} + inline virtual void onGnssDataCb(GnssDataNotification /*gnssDataNotification*/) {} + inline virtual void onGnssMeasurementsCb( + GnssMeasurementsNotification /*gnssMeasurementsNotification*/) {} + + inline virtual void onTrackingCb(Location /*location*/) {} + inline virtual void onGnssSvCb(GnssSvNotification /*gnssSvNotification*/) {} + inline virtual void onStartTrackingCb(LocationError /*error*/) {} + inline virtual void onStopTrackingCb(LocationError /*error*/) {} + inline virtual void onUpdateTrackingOptionsCb(LocationError /*error*/) {} + + inline virtual void onGnssLocationInfoCb( + GnssLocationInfoNotification /*gnssLocationInfoNotification*/) {} + + inline virtual void onBatchingCb(size_t /*count*/, Location* /*location*/, + BatchingOptions /*batchingOptions*/) {} + inline virtual void onBatchingStatusCb(BatchingStatusInfo /*batchingStatus*/, + std::list &/*listOfCompletedTrips*/) {} + void beforeBatchingStatusCb(BatchingStatusInfo batchStatus, + std::list & tripCompletedList); + inline virtual void onStartBatchingCb(LocationError /*error*/) {} + inline virtual void onStopBatchingCb(LocationError /*error*/) {} + inline virtual void onUpdateBatchingOptionsCb(LocationError /*error*/) {} + inline virtual void onGetBatchedLocationsCb(LocationError /*error*/) {} + + inline virtual void onGeofenceBreachCb( + GeofenceBreachNotification /*geofenceBreachNotification*/) {} + inline virtual void onGeofenceStatusCb( + GeofenceStatusNotification /*geofenceStatusNotification*/) {} + inline virtual void onAddGeofencesCb( + size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {} + inline virtual void onRemoveGeofencesCb( + size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {} + inline virtual void onModifyGeofencesCb( + size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {} + inline virtual void onPauseGeofencesCb( + size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {} + inline virtual void onResumeGeofencesCb( + size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {} + + inline virtual void onGnssNiCb(uint32_t /*id*/, GnssNiNotification /*gnssNiNotification*/) {} + inline virtual void onGnssNiResponseCb(LocationError /*error*/) {} + + inline virtual void onLocationSystemInfoCb(LocationSystemInfo /*locationSystemInfo*/) {} + +protected: + virtual ~LocationAPIClientBase(); + +private: + // private inner classes + typedef struct { + uint32_t id; + uint32_t trackingSession; + uint32_t batchingSession; + uint32_t sessionMode; + } SessionEntity; + + template + class BiDict { + public: + BiDict() { + pthread_mutex_init(&mBiDictMutex, nullptr); + } + virtual ~BiDict() { + pthread_mutex_destroy(&mBiDictMutex); + } + bool hasId(uint32_t id) { + pthread_mutex_lock(&mBiDictMutex); + bool ret = (mForwardMap.find(id) != mForwardMap.end()); + pthread_mutex_unlock(&mBiDictMutex); + return ret; + } + bool hasSession(uint32_t session) { + pthread_mutex_lock(&mBiDictMutex); + bool ret = (mBackwardMap.find(session) != mBackwardMap.end()); + pthread_mutex_unlock(&mBiDictMutex); + return ret; + } + void set(uint32_t id, uint32_t session, T& ext) { + pthread_mutex_lock(&mBiDictMutex); + mForwardMap[id] = session; + mBackwardMap[session] = id; + mExtMap[session] = ext; + pthread_mutex_unlock(&mBiDictMutex); + } + void clear() { + pthread_mutex_lock(&mBiDictMutex); + mForwardMap.clear(); + mBackwardMap.clear(); + mExtMap.clear(); + pthread_mutex_unlock(&mBiDictMutex); + } + void rmById(uint32_t id) { + pthread_mutex_lock(&mBiDictMutex); + mBackwardMap.erase(mForwardMap[id]); + mExtMap.erase(mForwardMap[id]); + mForwardMap.erase(id); + pthread_mutex_unlock(&mBiDictMutex); + } + void rmBySession(uint32_t session) { + pthread_mutex_lock(&mBiDictMutex); + mForwardMap.erase(mBackwardMap[session]); + mBackwardMap.erase(session); + mExtMap.erase(session); + pthread_mutex_unlock(&mBiDictMutex); + } + uint32_t getId(uint32_t session) { + pthread_mutex_lock(&mBiDictMutex); + uint32_t ret = 0; + auto it = mBackwardMap.find(session); + if (it != mBackwardMap.end()) { + ret = it->second; + } + pthread_mutex_unlock(&mBiDictMutex); + return ret; + } + uint32_t getSession(uint32_t id) { + pthread_mutex_lock(&mBiDictMutex); + uint32_t ret = 0; + auto it = mForwardMap.find(id); + if (it != mForwardMap.end()) { + ret = it->second; + } + pthread_mutex_unlock(&mBiDictMutex); + return ret; + } + T getExtById(uint32_t id) { + pthread_mutex_lock(&mBiDictMutex); + T ret; + memset(&ret, 0, sizeof(T)); + uint32_t session = mForwardMap[id]; + if (session > 0) { + auto it = mExtMap.find(session); + if (it != mExtMap.end()) { + ret = it->second; + } + } + pthread_mutex_unlock(&mBiDictMutex); + return ret; + } + T getExtBySession(uint32_t session) { + pthread_mutex_lock(&mBiDictMutex); + T ret; + memset(&ret, 0, sizeof(T)); + auto it = mExtMap.find(session); + if (it != mExtMap.end()) { + ret = it->second; + } + pthread_mutex_unlock(&mBiDictMutex); + return ret; + } + std::vector getAllSessions() { + std::vector ret; + pthread_mutex_lock(&mBiDictMutex); + for (auto it = mBackwardMap.begin(); it != mBackwardMap.end(); it++) { + ret.push_back(it->first); + } + pthread_mutex_unlock(&mBiDictMutex); + return ret; + } + private: + pthread_mutex_t mBiDictMutex; + // mForwarMap mapping id->session + std::map mForwardMap; + // mBackwardMap mapping session->id + std::map mBackwardMap; + // mExtMap mapping session->ext + std::map mExtMap; + }; + + class StartTrackingRequest : public LocationAPIRequest { + public: + StartTrackingRequest(LocationAPIClientBase& API) : mAPI(API) {} + inline void onResponse(LocationError error, uint32_t id) { + if (error != LOCATION_ERROR_SUCCESS) { + mAPI.removeSession(id); + } + mAPI.onStartTrackingCb(error); + } + LocationAPIClientBase& mAPI; + }; + + class StopTrackingRequest : public LocationAPIRequest { + public: + StopTrackingRequest(LocationAPIClientBase& API) : mAPI(API) {} + inline void onResponse(LocationError error, uint32_t id) { + mAPI.onStopTrackingCb(error); + if (error == LOCATION_ERROR_SUCCESS) { + mAPI.removeSession(id); + } + } + LocationAPIClientBase& mAPI; + }; + + class UpdateTrackingOptionsRequest : public LocationAPIRequest { + public: + UpdateTrackingOptionsRequest(LocationAPIClientBase& API) : mAPI(API) {} + inline void onResponse(LocationError error, uint32_t /*id*/) { + mAPI.onUpdateTrackingOptionsCb(error); + } + LocationAPIClientBase& mAPI; + }; + + class StartBatchingRequest : public LocationAPIRequest { + public: + StartBatchingRequest(LocationAPIClientBase& API) : mAPI(API) {} + inline void onResponse(LocationError error, uint32_t id) { + if (error != LOCATION_ERROR_SUCCESS) { + mAPI.removeSession(id); + } + mAPI.onStartBatchingCb(error); + } + LocationAPIClientBase& mAPI; + }; + + class StopBatchingRequest : public LocationAPIRequest { + public: + StopBatchingRequest(LocationAPIClientBase& API) : mAPI(API) {} + inline void onResponse(LocationError error, uint32_t id) { + mAPI.onStopBatchingCb(error); + if (error == LOCATION_ERROR_SUCCESS) { + mAPI.removeSession(id); + } + } + LocationAPIClientBase& mAPI; + }; + + class UpdateBatchingOptionsRequest : public LocationAPIRequest { + public: + UpdateBatchingOptionsRequest(LocationAPIClientBase& API) : mAPI(API) {} + inline void onResponse(LocationError error, uint32_t /*id*/) { + mAPI.onUpdateBatchingOptionsCb(error); + } + LocationAPIClientBase& mAPI; + }; + + class GetBatchedLocationsRequest : public LocationAPIRequest { + public: + GetBatchedLocationsRequest(LocationAPIClientBase& API) : mAPI(API) {} + inline void onResponse(LocationError error, uint32_t /*id*/) { + mAPI.onGetBatchedLocationsCb(error); + } + LocationAPIClientBase& mAPI; + }; + + class AddGeofencesRequest : public LocationAPIRequest { + public: + AddGeofencesRequest(LocationAPIClientBase& API) : mAPI(API) {} + inline void onCollectiveResponse(size_t count, LocationError* errors, uint32_t* sessions) { + uint32_t *ids = (uint32_t*)malloc(sizeof(uint32_t) * count); + for (size_t i = 0; i < count; i++) { + ids[i] = mAPI.mGeofenceBiDict.getId(sessions[i]); + } + LOC_LOGD("%s:]Returned geofence-id: %d in add geofence", __FUNCTION__, *ids); + mAPI.onAddGeofencesCb(count, errors, ids); + free(ids); + } + LocationAPIClientBase& mAPI; + }; + + class RemoveGeofencesRequest : public LocationAPIRequest { + public: + RemoveGeofencesRequest(LocationAPIClientBase& API, + BiDict* removedGeofenceBiDict) : + mAPI(API), mRemovedGeofenceBiDict(removedGeofenceBiDict) {} + inline void onCollectiveResponse(size_t count, LocationError* errors, uint32_t* sessions) { + if (nullptr != mRemovedGeofenceBiDict) { + uint32_t *ids = (uint32_t*)malloc(sizeof(uint32_t) * count); + for (size_t i = 0; i < count; i++) { + ids[i] = mRemovedGeofenceBiDict->getId(sessions[i]); + } + LOC_LOGD("%s:]Returned geofence-id: %d in remove geofence", __FUNCTION__, *ids); + mAPI.onRemoveGeofencesCb(count, errors, ids); + free(ids); + delete(mRemovedGeofenceBiDict); + } else { + LOC_LOGE("%s:%d] Unable to access removed geofences data.", __FUNCTION__, __LINE__); + } + } + LocationAPIClientBase& mAPI; + BiDict* mRemovedGeofenceBiDict; + }; + + class ModifyGeofencesRequest : public LocationAPIRequest { + public: + ModifyGeofencesRequest(LocationAPIClientBase& API) : mAPI(API) {} + inline void onCollectiveResponse(size_t count, LocationError* errors, uint32_t* sessions) { + uint32_t *ids = (uint32_t*)malloc(sizeof(uint32_t) * count); + for (size_t i = 0; i < count; i++) { + ids[i] = mAPI.mGeofenceBiDict.getId(sessions[i]); + } + mAPI.onModifyGeofencesCb(count, errors, ids); + free(ids); + } + LocationAPIClientBase& mAPI; + }; + + class PauseGeofencesRequest : public LocationAPIRequest { + public: + PauseGeofencesRequest(LocationAPIClientBase& API) : mAPI(API) {} + inline void onCollectiveResponse(size_t count, LocationError* errors, uint32_t* sessions) { + uint32_t *ids = (uint32_t*)malloc(sizeof(uint32_t) * count); + for (size_t i = 0; i < count; i++) { + ids[i] = mAPI.mGeofenceBiDict.getId(sessions[i]); + } + mAPI.onPauseGeofencesCb(count, errors, ids); + free(ids); + } + LocationAPIClientBase& mAPI; + }; + + class ResumeGeofencesRequest : public LocationAPIRequest { + public: + ResumeGeofencesRequest(LocationAPIClientBase& API) : mAPI(API) {} + inline void onCollectiveResponse(size_t count, LocationError* errors, uint32_t* sessions) { + uint32_t *ids = (uint32_t*)malloc(sizeof(uint32_t) * count); + for (size_t i = 0; i < count; i++) { + ids[i] = mAPI.mGeofenceBiDict.getId(sessions[i]); + } + mAPI.onResumeGeofencesCb(count, errors, ids); + free(ids); + } + LocationAPIClientBase& mAPI; + }; + + class GnssNiResponseRequest : public LocationAPIRequest { + public: + GnssNiResponseRequest(LocationAPIClientBase& API) : mAPI(API) {} + inline void onResponse(LocationError error, uint32_t /*id*/) { + mAPI.onGnssNiResponseCb(error); + } + LocationAPIClientBase& mAPI; + }; + +private: + pthread_mutex_t mMutex; + + geofenceBreachCallback mGeofenceBreachCallback; + batchingStatusCallback mBatchingStatusCallback; + + LocationAPI* mLocationAPI; + + RequestQueue mRequestQueues[REQUEST_MAX]; + BiDict mGeofenceBiDict; + BiDict mSessionBiDict; + int32_t mBatchSize; + bool mTracking; +}; + +#endif /* LOCATION_API_CLINET_BASE_H */ diff --git a/gps/location/LocationDataTypes.h b/gps/location/LocationDataTypes.h new file mode 100644 index 0000000..b85464a --- /dev/null +++ b/gps/location/LocationDataTypes.h @@ -0,0 +1,2070 @@ +/* Copyright (c) 2018-2020 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LOCATIONDATATYPES_H +#define LOCATIONDATATYPES_H + +#include +#include +#include +#include +#include +#include + +#define GNSS_NI_REQUESTOR_MAX (256) +#define GNSS_NI_MESSAGE_ID_MAX (2048) +#define GNSS_SV_MAX (128) +#define GNSS_MEASUREMENTS_MAX (128) +#define GNSS_UTC_TIME_OFFSET (3657) + +#define GNSS_BUGREPORT_GPS_MIN (1) +#define GNSS_BUGREPORT_SBAS_MIN (120) +#define GNSS_BUGREPORT_GLO_MIN (1) +#define GNSS_BUGREPORT_QZSS_MIN (193) +#define GNSS_BUGREPORT_BDS_MIN (1) +#define GNSS_BUGREPORT_GAL_MIN (1) +#define GNSS_BUGREPORT_NAVIC_MIN (1) + +#define GNSS_MAX_NAME_LENGTH (8) + +typedef enum { + LOCATION_ERROR_SUCCESS = 0, + LOCATION_ERROR_GENERAL_FAILURE, + LOCATION_ERROR_CALLBACK_MISSING, + LOCATION_ERROR_INVALID_PARAMETER, + LOCATION_ERROR_ID_EXISTS, + LOCATION_ERROR_ID_UNKNOWN, + LOCATION_ERROR_ALREADY_STARTED, + LOCATION_ERROR_GEOFENCES_AT_MAX, + LOCATION_ERROR_NOT_SUPPORTED, + LOCATION_ERROR_TIMEOUT, +} LocationError; + +// Flags to indicate which values are valid in a Location +typedef uint16_t LocationFlagsMask; +typedef enum { + LOCATION_HAS_LAT_LONG_BIT = (1<<0), // location has valid latitude and longitude + LOCATION_HAS_ALTITUDE_BIT = (1<<1), // location has valid altitude + LOCATION_HAS_SPEED_BIT = (1<<2), // location has valid speed + LOCATION_HAS_BEARING_BIT = (1<<3), // location has valid bearing + LOCATION_HAS_ACCURACY_BIT = (1<<4), // location has valid accuracy + LOCATION_HAS_VERTICAL_ACCURACY_BIT = (1<<5), // location has valid vertical accuracy + LOCATION_HAS_SPEED_ACCURACY_BIT = (1<<6), // location has valid speed accuracy + LOCATION_HAS_BEARING_ACCURACY_BIT = (1<<7), // location has valid bearing accuracy + LOCATION_HAS_SPOOF_MASK = (1<<8), // location has valid spoof mask + LOCATION_HAS_ELAPSED_REAL_TIME = (1<<9), // location has valid elapsed real time + LOCATION_HAS_CONFORMITY_INDEX_BIT = (1<<10), // location has valid conformity index +} LocationFlagsBits; + +typedef uint16_t LocationTechnologyMask; +// mask indicating location calculations including... +typedef enum { + LOCATION_TECHNOLOGY_GNSS_BIT = (1<<0), // using GNSS + LOCATION_TECHNOLOGY_CELL_BIT = (1<<1), // using Cell + LOCATION_TECHNOLOGY_WIFI_BIT = (1<<2), // using WiFi + LOCATION_TECHNOLOGY_SENSORS_BIT = (1<<3), // using Sensors + LOCATION_TECHNOLOGY_REFERENCE_LOCATION_BIT = (1<<4), // using reference location + LOCATION_TECHNOLOGY_INJECTED_COARSE_POSITION_BIT = (1<<5), // using CPI + LOCATION_TECHNOLOGY_AFLT_BIT = (1<<6), // AFLT + LOCATION_TECHNOLOGY_HYBRID_BIT = (1<<7), // HYBRID + LOCATION_TECHNOLOGY_PPE_BIT = (1<<8), // PPE + LOCATION_TECHNOLOGY_VEH_BIT = (1<<9), // using vehicular data + LOCATION_TECHNOLOGY_VIS_BIT = (1<<10), // using visual data + LOCATION_TECHNOLOGY_DGNSS_BIT = (1<<11), // DGNSS +} LocationTechnologyBits; + +typedef uint32_t LocationSpoofMask; +typedef enum { + LOCATION_POSTION_SPOOFED = (1<<0), // location position spoofed + LOCATION_TIME_SPOOFED = (1<<1), // location time spoofed + LOCATION_NAVIGATION_DATA_SPOOFED = (1<<2), // location navigation data spoofed +} LocationSpoofBits; + +typedef enum { + LOCATION_RELIABILITY_NOT_SET = 0, + LOCATION_RELIABILITY_VERY_LOW, + LOCATION_RELIABILITY_LOW, + LOCATION_RELIABILITY_MEDIUM, + LOCATION_RELIABILITY_HIGH, +} LocationReliability; + +typedef uint32_t GnssLocationNavSolutionMask; +typedef enum { + // SBAS ionospheric correction is used + LOCATION_SBAS_CORRECTION_IONO_BIT = (1<<0), + // SBAS fast correction is used + LOCATION_SBAS_CORRECTION_FAST_BIT = (1<<1), + // SBAS long-tem correction is used + LOCATION_SBAS_CORRECTION_LONG_BIT = (1<<2), + // SBAS integrity information is used + LOCATION_SBAS_INTEGRITY_BIT = (1<<3), + // Position Report is DGNSS corrected + LOCATION_NAV_CORRECTION_DGNSS_BIT = (1<<4), + // Position Report is RTK corrected + LOCATION_NAV_CORRECTION_RTK_BIT = (1<<5), + // Position Report is PPP corrected + LOCATION_NAV_CORRECTION_PPP_BIT = (1<<6), + // Posiiton Report is RTF fixed corrected + LOCATION_NAV_CORRECTION_RTK_FIXED_BIT = (1<<7), + // Position report is computed with only SBAS corrected SVs. + LOCATION_NAV_CORRECTION_ONLY_SBAS_CORRECTED_SV_USED_BIT = (1<<8) +} GnssLocationNavSolutionBits; + +typedef uint32_t GnssLocationPosDataMask; +typedef enum { + LOCATION_NAV_DATA_HAS_LONG_ACCEL_BIT = (1<<0), // Navigation data has Forward Acceleration + LOCATION_NAV_DATA_HAS_LAT_ACCEL_BIT = (1<<1), // Navigation data has Sideward Acceleration + LOCATION_NAV_DATA_HAS_VERT_ACCEL_BIT = (1<<2), // Navigation data has Vertical Acceleration + LOCATION_NAV_DATA_HAS_YAW_RATE_BIT = (1<<3), // Navigation data has Heading Rate + LOCATION_NAV_DATA_HAS_PITCH_BIT = (1<<4), // Navigation data has Body pitch + // Navigation data has Forward Acceleration uncertainty + LOCATION_NAV_DATA_HAS_LONG_ACCEL_UNC_BIT = (1<<5), + // Navigation data has Sideward Acceleration uncertainty + LOCATION_NAV_DATA_HAS_LAT_ACCEL_UNC_BIT = (1<<6), + // Navigation data has Vertical Acceleration uncertainty + LOCATION_NAV_DATA_HAS_VERT_ACCEL_UNC_BIT = (1<<7), + // Navigation data has Heading Rate uncertainty + LOCATION_NAV_DATA_HAS_YAW_RATE_UNC_BIT = (1<<8), + // Navigation data has Body pitch uncertainty + LOCATION_NAV_DATA_HAS_PITCH_UNC_BIT = (1<<9) +} GnssLocationPosDataBits; + +typedef uint32_t GnssLocationPosDataMaskExt; +typedef enum { + // Navigation data has pitch rate + LOCATION_NAV_DATA_HAS_PITCH_RATE_BIT = (1<<0), + // Navigation data has body pitch rate uncertainty + LOCATION_NAV_DATA_HAS_PITCH_RATE_UNC_BIT = (1<<1), + // Navigation data has body roll + LOCATION_NAV_DATA_HAS_ROLL_BIT = (1<<2), + // Navigation data has body roll uncertainty + LOCATION_NAV_DATA_HAS_ROLL_UNC_BIT = (1<<3), + // Navigation data has body rate roll + LOCATION_NAV_DATA_HAS_ROLL_RATE_BIT = (1<<4), + // Navigation data has body roll rate uncertainty + LOCATION_NAV_DATA_HAS_ROLL_RATE_UNC_BIT = (1<<5), + // Navigation data has body yaw + LOCATION_NAV_DATA_HAS_YAW_BIT = (1<<6), + // Navigation data has body roll uncertainty + LOCATION_NAV_DATA_HAS_YAW_UNC_BIT = (1<<7) +} GnssLocationPosDataBitsExt; + +typedef uint64_t GnssLocationInfoFlagMask; +typedef enum { + GNSS_LOCATION_INFO_ALTITUDE_MEAN_SEA_LEVEL_BIT = (1<<0), // altitude mean sea level + GNSS_LOCATION_INFO_DOP_BIT = (1<<1), // pdop, hdop, and vdop + GNSS_LOCATION_INFO_MAGNETIC_DEVIATION_BIT = (1<<2), // magnetic deviation + GNSS_LOCATION_INFO_HOR_RELIABILITY_BIT = (1<<3), // horizontal reliability + GNSS_LOCATION_INFO_VER_RELIABILITY_BIT = (1<<4), // vertical reliability + GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MAJOR_BIT = (1<<5), // elipsode semi major + GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MINOR_BIT = (1<<6), // elipsode semi minor + GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_AZIMUTH_BIT = (1<<7), // accuracy elipsode azimuth + GNSS_LOCATION_INFO_GNSS_SV_USED_DATA_BIT = (1<<8), // svUsedInPosition, + // numOfMeasReceived + // and measUsageInfo + GNSS_LOCATION_INFO_NAV_SOLUTION_MASK_BIT = (1<<9), // navSolutionMask + GNSS_LOCATION_INFO_SV_SOURCE_INFO_BIT = (1<<10), // LocSvInfoSource + GNSS_LOCATION_INFO_POS_DYNAMICS_DATA_BIT = (1<<11), // position dynamics data & + // Position Dynamics Ext + GNSS_LOCATION_INFO_EXT_DOP_BIT = (1<<12), // gdop, tdop + GNSS_LOCATION_INFO_NORTH_STD_DEV_BIT = (1<<13), // North standard deviation + GNSS_LOCATION_INFO_EAST_STD_DEV_BIT = (1<<14), // East standard deviation + GNSS_LOCATION_INFO_NORTH_VEL_BIT = (1<<15), // North Velocity + GNSS_LOCATION_INFO_EAST_VEL_BIT = (1<<16), // East Velocity + GNSS_LOCATION_INFO_UP_VEL_BIT = (1<<17), // Up Velocity + GNSS_LOCATION_INFO_NORTH_VEL_UNC_BIT = (1<<18), // North Velocity Uncertainty + GNSS_LOCATION_INFO_EAST_VEL_UNC_BIT = (1<<19), // East Velocity Uncertainty + GNSS_LOCATION_INFO_UP_VEL_UNC_BIT = (1<<20), // Up Velocity Uncertainty + GNSS_LOCATION_INFO_LEAP_SECONDS_BIT = (1<<21), // leap seconds + GNSS_LOCATION_INFO_TIME_UNC_BIT = (1<<22), // time uncertainty + GNSS_LOCATION_INFO_NUM_SV_USED_IN_POSITION_BIT = (1<<23), // number of SV used in position + GNSS_LOCATION_INFO_CALIBRATION_CONFIDENCE_BIT = (1<<24), // sensor cal confidence + GNSS_LOCATION_INFO_CALIBRATION_STATUS_BIT = (1<<25), // sensor cal status + GNSS_LOCATION_INFO_OUTPUT_ENG_TYPE_BIT = (1<<26), // output engine type + GNSS_LOCATION_INFO_OUTPUT_ENG_MASK_BIT = (1<<27), // output engine mask + GNSS_LOCATION_INFO_CONFORMITY_INDEX_BIT = (1<<28), // conformity index + GNSS_LOCATION_INFO_LLA_VRP_BASED_BIT = (1<<29), // VRP-based lat/long/alt + GNSS_LOCATION_INFO_ENU_VELOCITY_VRP_BASED_BIT = (1<<30), // VRP-based east/north/up vel + GNSS_LOCATION_INFO_DR_SOLUTION_STATUS_MASK_BIT = (1ULL<<31), // Valid DR solution status + GNSS_LOCATION_INFO_ALTITUDE_ASSUMED_BIT = (1ULL<<32), // Valid altitude assumed + GNSS_LOCATION_INFO_SESSION_STATUS_BIT = (1ULL<<33), // session status +} GnssLocationInfoFlagBits; + +typedef enum { + GEOFENCE_BREACH_ENTER = 0, + GEOFENCE_BREACH_EXIT, + GEOFENCE_BREACH_DWELL_IN, + GEOFENCE_BREACH_DWELL_OUT, + GEOFENCE_BREACH_UNKNOWN, +} GeofenceBreachType; + +typedef uint16_t GeofenceBreachTypeMask; +typedef enum { + GEOFENCE_BREACH_ENTER_BIT = (1<<0), + GEOFENCE_BREACH_EXIT_BIT = (1<<1), + GEOFENCE_BREACH_DWELL_IN_BIT = (1<<2), + GEOFENCE_BREACH_DWELL_OUT_BIT = (1<<3), +} GeofenceBreachTypeBits; + +typedef enum { + GEOFENCE_STATUS_AVAILABILE_NO = 0, + GEOFENCE_STATUS_AVAILABILE_YES, +} GeofenceStatusAvailable; + +// Set of masks for Modem and QWES capabilities. +typedef uint64_t LocationCapabilitiesMask; +typedef enum { + // supports startTracking API with minInterval param + LOCATION_CAPABILITIES_TIME_BASED_TRACKING_BIT = (1<<0), + // supports startBatching API with minInterval param + LOCATION_CAPABILITIES_TIME_BASED_BATCHING_BIT = (1<<1), + // supports startTracking API with minDistance param + LOCATION_CAPABILITIES_DISTANCE_BASED_TRACKING_BIT = (1<<2), + // supports startBatching API with minDistance param + LOCATION_CAPABILITIES_DISTANCE_BASED_BATCHING_BIT = (1<<3), + // supports addGeofences API + LOCATION_CAPABILITIES_GEOFENCE_BIT = (1<<4), + // supports GnssMeasurementsCallback + LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT = (1<<5), + // supports startTracking/startBatching API with LocationOptions.mode of MSB (Ms Based) + LOCATION_CAPABILITIES_GNSS_MSB_BIT = (1<<6), + // supports startTracking/startBatching API with LocationOptions.mode of MSA (MS Assisted) + LOCATION_CAPABILITIES_GNSS_MSA_BIT = (1<<7), + // supports debug nmea sentences in the debugNmeaCallback + LOCATION_CAPABILITIES_DEBUG_NMEA_BIT = (1<<8), + // support outdoor trip batching + LOCATION_CAPABILITIES_OUTDOOR_TRIP_BATCHING_BIT = (1<<9), + // support constellation enablement + LOCATION_CAPABILITIES_CONSTELLATION_ENABLEMENT_BIT = (1<<10), + // support agpm + LOCATION_CAPABILITIES_AGPM_BIT = (1<<11), + // support location privacy + LOCATION_CAPABILITIES_PRIVACY_BIT = (1<<12), + // support measurement corrections + LOCATION_CAPABILITIES_MEASUREMENTS_CORRECTION_BIT = (1<<13), + // support Robust Location + LOCATION_CAPABILITIES_CONFORMITY_INDEX_BIT = (1<<14), + // support precise location edgnss + LOCATION_CAPABILITIES_EDGNSS_BIT = (1<<15), + // Modem supports Carrier Phase for Precise Positioning + // Measurement Engine (PPME). + LOCATION_CAPABILITIES_QWES_CARRIER_PHASE_BIT = (1<<16), + // Modem supports SV Polynomial for tightly coupled external + // DR support. This is a Standalone Feature. + LOCATION_CAPABILITIES_QWES_SV_POLYNOMIAL_BIT = (1<<17), + // Modem supports SV Ephemeris for tightly coupled external + // PPE engines. This is a Standalone Feature. + LOCATION_CAPABILITIES_QWES_SV_EPHEMERIS_BIT = (1<<18), + // Modem supports GNSS Single Frequency feature. This is a + // Standalone Feature. + LOCATION_CAPABILITIES_QWES_GNSS_SINGLE_FREQUENCY = (1<<19), + // Modem supports GNSS Multi Frequency feature. Multi Frequency + // enables Single frequency also. + LOCATION_CAPABILITIES_QWES_GNSS_MULTI_FREQUENCY = (1<<20), + // This mask indicates VPe license bundle is enabled. VEPP + // bundle include Carrier Phase and SV Polynomial features. + LOCATION_CAPABILITIES_QWES_VPE = (1<<21), + // This mask indicates support for CV2X Location basic features. + // This bundle includes features for GTS Time & Freq, C-TUNC + // (Constrained Time uncertainity. + LOCATION_CAPABILITIES_QWES_CV2X_LOCATION_BASIC = (1<<22), + // This mask indicates support for CV2X Location premium features. + // This bundle includes features for CV2X Location Basic features, + // QDR3 feature, and PACE. (Position Assisted Clock Estimator. + LOCATION_CAPABILITIES_QWES_CV2X_LOCATION_PREMIUM = (1<<23), + // This mask indicates that PPE (Precise Positioning Engine) + // library is enabled or Precise Positioning Framework (PPF) + // is available. This bundle includes features for Carrier + // Phase and SV Ephermeris. + LOCATION_CAPABILITIES_QWES_PPE = (1<<24), + // This mask indicates QDR2_C license bundle is enabled. This + // bundle includes features for SV Polynomial. + LOCATION_CAPABILITIES_QWES_QDR2 = (1<<25), + // This mask indicates QDR3_C license bundle is enabled. This + // bundle includes features for SV Polynomial. + LOCATION_CAPABILITIES_QWES_QDR3 = (1<<26), +} LocationCapabilitiesBits; + +typedef uint8_t LocationQwesFeatureType; +typedef enum { + // Modem supports Carrier Phase for Precise Positioning + // Measurement Engine (PPME). + LOCATION_QWES_FEATURE_TYPE_CARRIER_PHASE = 1, + // Modem supports SV Polynomial for tightly coupled external + // DR support. This is a Standalone Feature. + LOCATION_QWES_FEATURE_TYPE_SV_POLYNOMIAL, + // Modem supports SV Ephemeris for tightly coupled external + // PPE support. This is a Standalone Feature. + LOCATION_QWES_FEATURE_TYPE_SV_EPH, + // Modem supports GNSS Single Frequency feature. This is a + // Standalone Feature. + LOCATION_QWES_FEATURE_TYPE_GNSS_SINGLE_FREQUENCY, + // Modem supports GNSS Multi Frequency feature. Multi Frequency + // enables Single frequency also. + LOCATION_QWES_FEATURE_TYPE_GNSS_MULTI_FREQUENCY, + // This indicates Time and Frequency status. + LOCATION_QWES_FEATURE_TYPE_TIME_FREQUENCY, + // This indicates Time Uncertainty status. + LOCATION_QWES_FEATURE_TYPE_TIME_UNCERTAINTY, + // This indicates Clock Estimate status. + LOCATION_QWES_FEATURE_TYPE_CLOCK_ESTIMATE, + // This mask indicates that PPE (Precise Positioning Engine) + // library is enabled or Precise Positioning Framework (PPF) + // is available. This bundle includes features for Carrier + // Phase and SV Ephermeris. + LOCATION_QWES_FEATURE_TYPE_PPE, + // This indicates QDR2_C license bundle is enabled. This + // bundle includes features for SV Polynomial. + LOCATION_QWES_FEATURE_TYPE_QDR2, + // This indicates QDR3_C license bundle is enabled. This + // bundle includes features for SV Polynomial. + LOCATION_QWES_FEATURE_TYPE_QDR3, + // This indicates VEPP license bundle is enabled. VEPP + // bundle include Carrier Phase and SV Polynomial features. + LOCATION_QWES_FEATURE_TYPE_VPE, + // Max value + LOCATION_QWES_FEATURE_TYPE_MAX +} LocationQwesFeatureTypes; + +typedef enum { + LOCATION_TECHNOLOGY_TYPE_GNSS = 0, +} LocationTechnologyType; + +// Configures how GPS is locked when GPS is disabled (through GnssDisable) +enum { + GNSS_CONFIG_GPS_LOCK_NONE = 0, // gps is not locked when GPS is disabled (GnssDisable) + GNSS_CONFIG_GPS_LOCK_MO, // gps mobile originated (MO) is locked when GPS is disabled + GNSS_CONFIG_GPS_LOCK_NI, // gps network initiated (NI) is locked when GPS is disabled + GNSS_CONFIG_GPS_LOCK_MO_AND_NI,// gps MO and NI is locked when GPS is disabled +}; +typedef int32_t GnssConfigGpsLock; + +// SUPL version +typedef enum { + GNSS_CONFIG_SUPL_VERSION_1_0_0 = 1, + GNSS_CONFIG_SUPL_VERSION_2_0_0, + GNSS_CONFIG_SUPL_VERSION_2_0_2, + GNSS_CONFIG_SUPL_VERSION_2_0_4, +} GnssConfigSuplVersion; + +// LTE Positioning Profile +typedef uint16_t GnssConfigLppProfileMask; +typedef enum { + GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE = 0, // RRLP on LTE (Default) + GNSS_CONFIG_LPP_PROFILE_USER_PLANE_BIT = (1<<0), // LPP User Plane (UP) on LTE + GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE_BIT = (1<<1), // LPP_Control_Plane (CP) + GNSS_CONFIG_LPP_PROFILE_USER_PLANE_OVER_NR5G_SA_BIT = (1<<2), // LPP User Plane (UP) on LTE + GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE_OVER_NR5G_SA_BIT = (1<<3), // LPP_Control_Plane (CP) +} GnssConfigLppProfileBits; + +// Technology for LPPe Control Plane +typedef uint16_t GnssConfigLppeControlPlaneMask; +typedef enum { + GNSS_CONFIG_LPPE_CONTROL_PLANE_DBH_BIT = (1<<0), // DBH + GNSS_CONFIG_LPPE_CONTROL_PLANE_WLAN_AP_MEASUREMENTS_BIT = (1<<1), // WLAN_AP_MEASUREMENTS + GNSS_CONFIG_LPPE_CONTROL_PLANE_SRN_AP_MEASUREMENTS_BIT = (1<<2), // SRN_AP_MEASUREMENTS + GNSS_CONFIG_LPPE_CONTROL_PLANE_SENSOR_BARO_MEASUREMENTS_BIT = (1<<3), + // SENSOR_BARO_MEASUREMENTS +} GnssConfigLppeControlPlaneBits; + +// Technology for LPPe User Plane +typedef uint16_t GnssConfigLppeUserPlaneMask; +typedef enum { + GNSS_CONFIG_LPPE_USER_PLANE_DBH_BIT = (1<<0), // DBH + GNSS_CONFIG_LPPE_USER_PLANE_WLAN_AP_MEASUREMENTS_BIT = (1<<1), // WLAN_AP_MEASUREMENTS + GNSS_CONFIG_LPPE_USER_PLANE_SRN_AP_MEASUREMENTS_BIT = (1<<2), // SRN_AP_MEASUREMENTS + GNSS_CONFIG_LPPE_USER_PLANE_SENSOR_BARO_MEASUREMENTS_BIT = (1<<3), + // SENSOR_BARO_MEASUREMENTS +} GnssConfigLppeUserPlaneBits; + +// Positioning Protocol on A-GLONASS system +typedef uint16_t GnssConfigAGlonassPositionProtocolMask; +typedef enum { + GNSS_CONFIG_RRC_CONTROL_PLANE_BIT = (1<<0), // RRC Control Plane + GNSS_CONFIG_RRLP_USER_PLANE_BIT = (1<<1), // RRLP User Plane + GNSS_CONFIG_LLP_USER_PLANE_BIT = (1<<2), // LPP User Plane + GNSS_CONFIG_LLP_CONTROL_PLANE_BIT = (1<<3), // LPP Control Plane +} GnssConfigAGlonassPositionProtocolBits; + +typedef enum { + GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_NO = 0, + GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_YES, +} GnssConfigEmergencyPdnForEmergencySupl; + +typedef enum { + GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_NO = 0, + GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_YES, +} GnssConfigSuplEmergencyServices; + +typedef uint16_t GnssConfigSuplModeMask; +typedef enum { + GNSS_CONFIG_SUPL_MODE_MSB_BIT = (1<<0), + GNSS_CONFIG_SUPL_MODE_MSA_BIT = (1<<1), +} GnssConfigSuplModeBits; + +typedef uint32_t GnssConfigFlagsMask; +typedef enum { + GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT = (1<<0), + GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT = (1<<1), + GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT = (1<<2), + GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT = (1<<3), + GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT = (1<<4), + GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT = (1<<5), + GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT = (1<<6), + GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT = (1<<7), + GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT = (1<<8), + GNSS_CONFIG_FLAGS_SUPL_MODE_BIT = (1<<9), + GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT = (1<<10), + GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT = (1<<11), + GNSS_CONFIG_FLAGS_ROBUST_LOCATION_BIT = (1<<12), + GNSS_CONFIG_FLAGS_MIN_GPS_WEEK_BIT = (1<<13), + GNSS_CONFIG_FLAGS_MIN_SV_ELEVATION_BIT = (1<<14), + GNSS_CONFIG_FLAGS_CONSTELLATION_SECONDARY_BAND_BIT = (1<<15), +} GnssConfigFlagsBits; + +typedef enum { + GNSS_NI_ENCODING_TYPE_NONE = 0, + GNSS_NI_ENCODING_TYPE_GSM_DEFAULT, + GNSS_NI_ENCODING_TYPE_UTF8, + GNSS_NI_ENCODING_TYPE_UCS2, +} GnssNiEncodingType; + +typedef enum { + GNSS_NI_TYPE_VOICE = 0, + GNSS_NI_TYPE_SUPL, + GNSS_NI_TYPE_CONTROL_PLANE, + GNSS_NI_TYPE_EMERGENCY_SUPL +} GnssNiType; + +typedef uint16_t GnssNiOptionsMask; +typedef enum { + GNSS_NI_OPTIONS_NOTIFICATION_BIT = (1<<0), + GNSS_NI_OPTIONS_VERIFICATION_BIT = (1<<1), + GNSS_NI_OPTIONS_PRIVACY_OVERRIDE_BIT = (1<<2), +} GnssNiOptionsBits; + +typedef enum { + GNSS_NI_RESPONSE_ACCEPT = 1, + GNSS_NI_RESPONSE_DENY, + GNSS_NI_RESPONSE_NO_RESPONSE, + GNSS_NI_RESPONSE_IGNORE, +} GnssNiResponse; + +typedef enum { + GNSS_SV_TYPE_UNKNOWN = 0, + GNSS_SV_TYPE_GPS, + GNSS_SV_TYPE_SBAS, + GNSS_SV_TYPE_GLONASS, + GNSS_SV_TYPE_QZSS, + GNSS_SV_TYPE_BEIDOU, + GNSS_SV_TYPE_GALILEO, + GNSS_SV_TYPE_NAVIC, +} GnssSvType; + +typedef enum { + GNSS_EPH_TYPE_UNKNOWN = 0, + GNSS_EPH_TYPE_EPHEMERIS, + GNSS_EPH_TYPE_ALMANAC, +} GnssEphemerisType; + +typedef enum { + GNSS_EPH_SOURCE_UNKNOWN = 0, + GNSS_EPH_SOURCE_DEMODULATED, + GNSS_EPH_SOURCE_SUPL_PROVIDED, + GNSS_EPH_SOURCE_OTHER_SERVER_PROVIDED, + GNSS_EPH_SOURCE_LOCAL, +} GnssEphemerisSource; + +typedef enum { + GNSS_EPH_HEALTH_UNKNOWN = 0, + GNSS_EPH_HEALTH_GOOD, + GNSS_EPH_HEALTH_BAD, +} GnssEphemerisHealth; + +typedef uint16_t GnssSvOptionsMask; +typedef enum { + GNSS_SV_OPTIONS_HAS_EPHEMER_BIT = (1<<0), + GNSS_SV_OPTIONS_HAS_ALMANAC_BIT = (1<<1), + GNSS_SV_OPTIONS_USED_IN_FIX_BIT = (1<<2), + GNSS_SV_OPTIONS_HAS_CARRIER_FREQUENCY_BIT = (1<<3), + GNSS_SV_OPTIONS_HAS_GNSS_SIGNAL_TYPE_BIT = (1<<4) +} GnssSvOptionsBits; + +typedef enum { + GNSS_ASSISTANCE_TYPE_SUPL = 0, + GNSS_ASSISTANCE_TYPE_C2K, + GNSS_ASSISTANCE_TYPE_SUPL_EIMS, + GNSS_ASSISTANCE_TYPE_SUPL_IMS, +} GnssAssistanceType; + +typedef enum { + GNSS_SUPL_MODE_STANDALONE = 0, + GNSS_SUPL_MODE_MSB, + GNSS_SUPL_MODE_MSA, +} GnssSuplMode; + +typedef enum { + BATCHING_MODE_ROUTINE = 0, // positions are reported when batched positions memory is full + BATCHING_MODE_TRIP, // positions are reported when a certain distance is covered + BATCHING_MODE_NO_AUTO_REPORT // no report of positions automatically, instead queried on demand +} BatchingMode; + +typedef enum { + BATCHING_STATUS_TRIP_COMPLETED = 0, + BATCHING_STATUS_POSITION_AVAILABE, + BATCHING_STATUS_POSITION_UNAVAILABLE +} BatchingStatus; + +typedef uint16_t GnssMeasurementsAdrStateMask; +typedef enum { + GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_UNKNOWN = 0, + GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_VALID_BIT = (1<<0), + GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_RESET_BIT = (1<<1), + GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_CYCLE_SLIP_BIT = (1<<2), + GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_HALF_CYCLE_RESOLVED_BIT = (1<<3), +} GnssMeasurementsAdrStateBits; + +typedef enum { + GNSS_MEASUREMENTS_CODE_TYPE_A = 0, + GNSS_MEASUREMENTS_CODE_TYPE_B = 1, + GNSS_MEASUREMENTS_CODE_TYPE_C = 2, + GNSS_MEASUREMENTS_CODE_TYPE_I = 3, + GNSS_MEASUREMENTS_CODE_TYPE_L = 4, + GNSS_MEASUREMENTS_CODE_TYPE_M = 5, + GNSS_MEASUREMENTS_CODE_TYPE_P = 6, + GNSS_MEASUREMENTS_CODE_TYPE_Q = 7, + GNSS_MEASUREMENTS_CODE_TYPE_S = 8, + GNSS_MEASUREMENTS_CODE_TYPE_W = 9, + GNSS_MEASUREMENTS_CODE_TYPE_X = 10, + GNSS_MEASUREMENTS_CODE_TYPE_Y = 11, + GNSS_MEASUREMENTS_CODE_TYPE_Z = 12, + GNSS_MEASUREMENTS_CODE_TYPE_N = 13, + GNSS_MEASUREMENTS_CODE_TYPE_OTHER = 255, +} GnssMeasurementsCodeType; + +typedef uint32_t GnssMeasurementsDataFlagsMask; +typedef enum { + GNSS_MEASUREMENTS_DATA_SV_ID_BIT = (1<<0), + GNSS_MEASUREMENTS_DATA_SV_TYPE_BIT = (1<<1), + GNSS_MEASUREMENTS_DATA_STATE_BIT = (1<<2), + GNSS_MEASUREMENTS_DATA_RECEIVED_SV_TIME_BIT = (1<<3), + GNSS_MEASUREMENTS_DATA_RECEIVED_SV_TIME_UNCERTAINTY_BIT = (1<<4), + GNSS_MEASUREMENTS_DATA_CARRIER_TO_NOISE_BIT = (1<<5), + GNSS_MEASUREMENTS_DATA_PSEUDORANGE_RATE_BIT = (1<<6), + GNSS_MEASUREMENTS_DATA_PSEUDORANGE_RATE_UNCERTAINTY_BIT = (1<<7), + GNSS_MEASUREMENTS_DATA_ADR_STATE_BIT = (1<<8), + GNSS_MEASUREMENTS_DATA_ADR_BIT = (1<<9), + GNSS_MEASUREMENTS_DATA_ADR_UNCERTAINTY_BIT = (1<<10), + GNSS_MEASUREMENTS_DATA_CARRIER_FREQUENCY_BIT = (1<<11), + GNSS_MEASUREMENTS_DATA_CARRIER_CYCLES_BIT = (1<<12), + GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_BIT = (1<<13), + GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_UNCERTAINTY_BIT = (1<<14), + GNSS_MEASUREMENTS_DATA_MULTIPATH_INDICATOR_BIT = (1<<15), + GNSS_MEASUREMENTS_DATA_SIGNAL_TO_NOISE_RATIO_BIT = (1<<16), + GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT = (1<<17), + GNSS_MEASUREMENTS_DATA_FULL_ISB_BIT = (1<<18), + GNSS_MEASUREMENTS_DATA_FULL_ISB_UNCERTAINTY_BIT = (1<<19), + GNSS_MEASUREMENTS_DATA_SATELLITE_ISB_BIT = (1<<20), + GNSS_MEASUREMENTS_DATA_SATELLITE_ISB_UNCERTAINTY_BIT = (1<<21), + GNSS_MEASUREMENTS_DATA_CYCLE_SLIP_COUNT_BIT = (1<<22), +} GnssMeasurementsDataFlagsBits; + +typedef uint32_t GnssMeasurementsStateMask; +typedef enum { + GNSS_MEASUREMENTS_STATE_UNKNOWN_BIT = 0, + GNSS_MEASUREMENTS_STATE_CODE_LOCK_BIT = (1<<0), + GNSS_MEASUREMENTS_STATE_BIT_SYNC_BIT = (1<<1), + GNSS_MEASUREMENTS_STATE_SUBFRAME_SYNC_BIT = (1<<2), + GNSS_MEASUREMENTS_STATE_TOW_DECODED_BIT = (1<<3), + GNSS_MEASUREMENTS_STATE_MSEC_AMBIGUOUS_BIT = (1<<4), + GNSS_MEASUREMENTS_STATE_SYMBOL_SYNC_BIT = (1<<5), + GNSS_MEASUREMENTS_STATE_GLO_STRING_SYNC_BIT = (1<<6), + GNSS_MEASUREMENTS_STATE_GLO_TOD_DECODED_BIT = (1<<7), + GNSS_MEASUREMENTS_STATE_BDS_D2_BIT_SYNC_BIT = (1<<8), + GNSS_MEASUREMENTS_STATE_BDS_D2_SUBFRAME_SYNC_BIT = (1<<9), + GNSS_MEASUREMENTS_STATE_GAL_E1BC_CODE_LOCK_BIT = (1<<10), + GNSS_MEASUREMENTS_STATE_GAL_E1C_2ND_CODE_LOCK_BIT = (1<<11), + GNSS_MEASUREMENTS_STATE_GAL_E1B_PAGE_SYNC_BIT = (1<<12), + GNSS_MEASUREMENTS_STATE_SBAS_SYNC_BIT = (1<<13), + GNSS_MEASUREMENTS_STATE_TOW_KNOWN_BIT = (1<<14), + GNSS_MEASUREMENTS_STATE_GLO_TOD_KNOWN_BIT = (1<<15), + GNSS_MEASUREMENTS_STATE_2ND_CODE_LOCK_BIT = (1<<16), +} GnssMeasurementsStateBits; + +typedef uint16_t GnssSingleSatCorrectionMask; +typedef enum { + GNSS_MEAS_CORR_UNKNOWN_BIT = 0, + GNSS_MEAS_CORR_HAS_SAT_IS_LOS_PROBABILITY_BIT = (1 << 0), + GNSS_MEAS_CORR_HAS_EXCESS_PATH_LENGTH_BIT = (1 << 1), + GNSS_MEAS_CORR_HAS_EXCESS_PATH_LENGTH_UNC_BIT = (1 << 2), + GNSS_MEAS_CORR_HAS_REFLECTING_PLANE_BIT = (1 << 3), +} GnssSingleSatCorrectionBits; + +typedef enum { + GNSS_MEASUREMENTS_MULTIPATH_INDICATOR_UNKNOWN = 0, + GNSS_MEASUREMENTS_MULTIPATH_INDICATOR_PRESENT, + GNSS_MEASUREMENTS_MULTIPATH_INDICATOR_NOT_PRESENT, +} GnssMeasurementsMultipathIndicator; + +typedef uint32_t GnssMeasurementsClockFlagsMask; +typedef enum { + GNSS_MEASUREMENTS_CLOCK_FLAGS_LEAP_SECOND_BIT = (1<<0), + GNSS_MEASUREMENTS_CLOCK_FLAGS_TIME_BIT = (1<<1), + GNSS_MEASUREMENTS_CLOCK_FLAGS_TIME_UNCERTAINTY_BIT = (1<<2), + GNSS_MEASUREMENTS_CLOCK_FLAGS_FULL_BIAS_BIT = (1<<3), + GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_BIT = (1<<4), + GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_UNCERTAINTY_BIT = (1<<5), + GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_BIT = (1<<6), + GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_UNCERTAINTY_BIT = (1<<7), + GNSS_MEASUREMENTS_CLOCK_FLAGS_HW_CLOCK_DISCONTINUITY_COUNT_BIT = (1<<8), + GNSS_MEASUREMENTS_CLOCK_FLAGS_ELAPSED_REAL_TIME_BIT = (1<<9), +} GnssMeasurementsClockFlagsBits; + +typedef uint32_t GnssAidingDataSvMask; +typedef enum { + GNSS_AIDING_DATA_SV_EPHEMERIS_BIT = (1<<0), // ephemeris + GNSS_AIDING_DATA_SV_ALMANAC_BIT = (1<<1), // almanac + GNSS_AIDING_DATA_SV_HEALTH_BIT = (1<<2), // health + GNSS_AIDING_DATA_SV_DIRECTION_BIT = (1<<3), // direction + GNSS_AIDING_DATA_SV_STEER_BIT = (1<<4), // steer + GNSS_AIDING_DATA_SV_ALMANAC_CORR_BIT = (1<<5), // almanac correction + GNSS_AIDING_DATA_SV_BLACKLIST_BIT = (1<<6), // blacklist SVs + GNSS_AIDING_DATA_SV_SA_DATA_BIT = (1<<7), // sensitivity assistance data + GNSS_AIDING_DATA_SV_NO_EXIST_BIT = (1<<8), // SV does not exist + GNSS_AIDING_DATA_SV_IONOSPHERE_BIT = (1<<9), // ionosphere correction + GNSS_AIDING_DATA_SV_TIME_BIT = (1<<10),// reset satellite time + GNSS_AIDING_DATA_SV_MB_DATA = (1<<11),// delete multiband data + GNSS_AIDING_DATA_SV_POLY_BIT = (1<<12),// poly +} GnssAidingDataSvBits; + +typedef uint32_t GnssAidingDataSvTypeMask; +typedef enum { + GNSS_AIDING_DATA_SV_TYPE_GPS_BIT = (1<<0), + GNSS_AIDING_DATA_SV_TYPE_GLONASS_BIT = (1<<1), + GNSS_AIDING_DATA_SV_TYPE_QZSS_BIT = (1<<2), + GNSS_AIDING_DATA_SV_TYPE_BEIDOU_BIT = (1<<3), + GNSS_AIDING_DATA_SV_TYPE_GALILEO_BIT = (1<<4), + GNSS_AIDING_DATA_SV_TYPE_NAVIC_BIT = (1<<5), + GNSS_AIDING_DATA_SV_TYPE_MAX = (1<<6), +} GnssAidingDataSvTypeBits; +#define GNSS_AIDING_DATA_SV_TYPE_MASK_ALL (GNSS_AIDING_DATA_SV_TYPE_MAX-1) + +/* Gnss constellation type mask */ +typedef uint16_t GnssConstellationTypeMask; +typedef enum { + GNSS_CONSTELLATION_TYPE_GPS_BIT = (1<<0), + GNSS_CONSTELLATION_TYPE_GLONASS_BIT = (1<<1), + GNSS_CONSTELLATION_TYPE_QZSS_BIT = (1<<2), + GNSS_CONSTELLATION_TYPE_BEIDOU_BIT = (1<<3), + GNSS_CONSTELLATION_TYPE_GALILEO_BIT = (1<<4), + GNSS_CONSTELLATION_TYPE_SBAS_BIT = (1<<5), + GNSS_CONSTELLATION_TYPE_NAVIC_BIT = (1<<6), +} GnssConstellationTypeBits; + +#define GNSS_CONSTELLATION_TYPE_MASK_ALL\ + (GNSS_CONSTELLATION_TYPE_GPS_BIT | GNSS_CONSTELLATION_TYPE_GLONASS_BIT |\ + GNSS_CONSTELLATION_TYPE_QZSS_BIT | GNSS_CONSTELLATION_TYPE_BEIDOU_BIT |\ + GNSS_CONSTELLATION_TYPE_GALILEO_BIT | GNSS_CONSTELLATION_TYPE_SBAS_BIT |\ + GNSS_CONSTELLATION_TYPE_NAVIC_BIT) + +/** GNSS Signal Type and RF Band */ +typedef uint32_t GnssSignalTypeMask; +typedef enum { + /** GPS L1CA Signal */ + GNSS_SIGNAL_GPS_L1CA = (1<<0), + /** GPS L1C Signal */ + GNSS_SIGNAL_GPS_L1C = (1<<1), + /** GPS L2 RF Band */ + GNSS_SIGNAL_GPS_L2 = (1<<2), + /** GPS L5 RF Band */ + GNSS_SIGNAL_GPS_L5 = (1<<3), + /** GLONASS G1 (L1OF) RF Band */ + GNSS_SIGNAL_GLONASS_G1 = (1<<4), + /** GLONASS G2 (L2OF) RF Band */ + GNSS_SIGNAL_GLONASS_G2 = (1<<5), + /** GALILEO E1 RF Band */ + GNSS_SIGNAL_GALILEO_E1 = (1<<6), + /** GALILEO E5A RF Band */ + GNSS_SIGNAL_GALILEO_E5A = (1<<7), + /** GALILEO E5B RF Band */ + GNSS_SIGNAL_GALILEO_E5B = (1<<8), + /** BEIDOU B1 RF Band */ + GNSS_SIGNAL_BEIDOU_B1 = (1<<9), + /** BEIDOU B2 RF Band */ + GNSS_SIGNAL_BEIDOU_B2 = (1<<10), + /** QZSS L1CA RF Band */ + GNSS_SIGNAL_QZSS_L1CA = (1<<11), + /** QZSS L1S RF Band */ + GNSS_SIGNAL_QZSS_L1S = (1<<12), + /** QZSS L2 RF Band */ + GNSS_SIGNAL_QZSS_L2 = (1<<13), + /** QZSS L5 RF Band */ + GNSS_SIGNAL_QZSS_L5 = (1<<14), + /** SBAS L1 RF Band */ + GNSS_SIGNAL_SBAS_L1 = (1<<15), + /** BEIDOU B1I RF Band */ + GNSS_SIGNAL_BEIDOU_B1I = (1<<16), + /** BEIDOU B1C RF Band */ + GNSS_SIGNAL_BEIDOU_B1C = (1<<17), + /** BEIDOU B2I RF Band */ + GNSS_SIGNAL_BEIDOU_B2I = (1<<18), + /** BEIDOU B2AI RF Band */ + GNSS_SIGNAL_BEIDOU_B2AI = (1<<19), + /** NAVIC L5 RF Band */ + GNSS_SIGNAL_NAVIC_L5 = (1<<20), + /** BEIDOU B2A_Q RF Band */ + GNSS_SIGNAL_BEIDOU_B2AQ = (1<<21), +} GnssSignalTypeBits; + +#define GNSS_SIGNAL_TYPE_MASK_ALL\ + (GNSS_SIGNAL_GPS_L1CA | GNSS_SIGNAL_GPS_L1C | GNSS_SIGNAL_GPS_L2 |\ + GNSS_SIGNAL_GPS_L5| GNSS_SIGNAL_GLONASS_G1 | GNSS_SIGNAL_GLONASS_G2 |\ + GNSS_SIGNAL_GALILEO_E1 | GNSS_SIGNAL_GALILEO_E5A | GNSS_SIGNAL_GALILEO_E5B |\ + GNSS_SIGNAL_BEIDOU_B1I | GNSS_SIGNAL_BEIDOU_B1C | GNSS_SIGNAL_BEIDOU_B2I|\ + GNSS_SIGNAL_BEIDOU_B2AI | GNSS_SIGNAL_QZSS_L1CA | GNSS_SIGNAL_QZSS_L1S |\ + GNSS_SIGNAL_QZSS_L2| GNSS_SIGNAL_QZSS_L5 | GNSS_SIGNAL_SBAS_L1 |\ + GNSS_SIGNAL_NAVIC_L5 | GNSS_SIGNAL_BEIDOU_B2AQ) + +typedef enum +{ + GNSS_LOC_SV_SYSTEM_UNKNOWN = 0, + /** unknown sv system. */ + GNSS_LOC_SV_SYSTEM_MIN = 1, + /**< Min enum of valid SV system. */ + GNSS_LOC_SV_SYSTEM_GPS = 1, + /**< GPS satellite. */ + GNSS_LOC_SV_SYSTEM_GALILEO = 2, + /**< GALILEO satellite. */ + GNSS_LOC_SV_SYSTEM_SBAS = 3, + /**< SBAS satellite. */ + GNSS_LOC_SV_SYSTEM_GLONASS = 4, + /**< GLONASS satellite. */ + GNSS_LOC_SV_SYSTEM_BDS = 5, + /**< BDS satellite. */ + GNSS_LOC_SV_SYSTEM_QZSS = 6, + /**< QZSS satellite. */ + GNSS_LOC_SV_SYSTEM_NAVIC = 7, + /**< NAVIC satellite. */ + GNSS_LOC_SV_SYSTEM_MAX = 7, + /**< Max enum of valid SV system. */ +} Gnss_LocSvSystemEnumType; + +typedef enum { + GNSS_LOC_SIGNAL_TYPE_GPS_L1CA = 0, /**< GPS L1CA Signal */ + GNSS_LOC_SIGNAL_TYPE_GPS_L1C = 1, /**< GPS L1C Signal */ + GNSS_LOC_SIGNAL_TYPE_GPS_L2C_L = 2, /**< GPS L2C_L RF Band */ + GNSS_LOC_SIGNAL_TYPE_GPS_L5_Q = 3, /**< GPS L5_Q RF Band */ + GNSS_LOC_SIGNAL_TYPE_GLONASS_G1 = 4, /**< GLONASS G1 (L1OF) RF Band */ + GNSS_LOC_SIGNAL_TYPE_GLONASS_G2 = 5, /**< GLONASS G2 (L2OF) RF Band */ + GNSS_LOC_SIGNAL_TYPE_GALILEO_E1_C = 6, /**< GALILEO E1_C RF Band */ + GNSS_LOC_SIGNAL_TYPE_GALILEO_E5A_Q = 7, /**< GALILEO E5A_Q RF Band */ + GNSS_LOC_SIGNAL_TYPE_GALILEO_E5B_Q = 8, /**< GALILEO E5B_Q RF Band */ + GNSS_LOC_SIGNAL_TYPE_BEIDOU_B1_I = 9, /**< BEIDOU B1_I RF Band */ + GNSS_LOC_SIGNAL_TYPE_BEIDOU_B1C = 10, /**< BEIDOU B1C RF Band */ + GNSS_LOC_SIGNAL_TYPE_BEIDOU_B2_I = 11, /**< BEIDOU B2_I RF Band */ + GNSS_LOC_SIGNAL_TYPE_BEIDOU_B2A_I = 12, /**< BEIDOU B2A_I RF Band */ + GNSS_LOC_SIGNAL_TYPE_QZSS_L1CA = 13, /**< QZSS L1CA RF Band */ + GNSS_LOC_SIGNAL_TYPE_QZSS_L1S = 14, /**< QZSS L1S RF Band */ + GNSS_LOC_SIGNAL_TYPE_QZSS_L2C_L = 15, /**< QZSS L2C_L RF Band */ + GNSS_LOC_SIGNAL_TYPE_QZSS_L5_Q = 16, /**< QZSS L5_Q RF Band */ + GNSS_LOC_SIGNAL_TYPE_SBAS_L1_CA = 17, /**< SBAS L1_CA RF Band */ + GNSS_LOC_SIGNAL_TYPE_NAVIC_L5 = 18, /**< NAVIC L5 RF Band */ + GNSS_LOC_SIGNAL_TYPE_BEIDOU_B2A_Q = 19, /**< BEIDOU B2A_Q RF Band */ + GNSS_LOC_MAX_NUMBER_OF_SIGNAL_TYPES = 20 /**< Maximum number of signal types */ +} Gnss_LocSignalEnumType; + +typedef uint32_t PositioningEngineMask; +typedef enum { + STANDARD_POSITIONING_ENGINE = (1 << 0), + DEAD_RECKONING_ENGINE = (1 << 1), + PRECISE_POSITIONING_ENGINE = (1 << 2), + VP_POSITIONING_ENGINE = (1 << 3) +} PositioningEngineBits; +#define POSITION_ENGINE_MASK_ALL \ + (STANDARD_POSITIONING_ENGINE|DEAD_RECKONING_ENGINE| \ + PRECISE_POSITIONING_ENGINE|VP_POSITIONING_ENGINE) + +/** Specify the position engine running state.
*/ +enum LocEngineRunState { + /** Request the position engine to be put into resume state. + *
*/ + LOC_ENGINE_RUN_STATE_PAUSE = 1, + /** Request the position engine to be put into resume state. + *
*/ + LOC_ENGINE_RUN_STATE_RESUME = 2, +}; + +typedef uint64_t GnssDataMask; +typedef enum { + // Jammer Indicator is available + GNSS_LOC_DATA_JAMMER_IND_BIT = (1ULL << 0), + // AGC is available + GNSS_LOC_DATA_AGC_BIT = (1ULL << 1) +} GnssDataBits; + +typedef uint32_t GnssSystemTimeStructTypeFlags; +typedef enum { + GNSS_SYSTEM_TIME_WEEK_VALID = (1 << 0), + GNSS_SYSTEM_TIME_WEEK_MS_VALID = (1 << 1), + GNSS_SYSTEM_CLK_TIME_BIAS_VALID = (1 << 2), + GNSS_SYSTEM_CLK_TIME_BIAS_UNC_VALID = (1 << 3), + GNSS_SYSTEM_REF_FCOUNT_VALID = (1 << 4), + GNSS_SYSTEM_NUM_CLOCK_RESETS_VALID = (1 << 5) +} GnssSystemTimeTypeBits; + +typedef uint32_t GnssGloTimeStructTypeFlags; +typedef enum { + GNSS_CLO_DAYS_VALID = (1 << 0), + GNSS_GLO_MSEC_VALID = (1 << 1), + GNSS_GLO_CLK_TIME_BIAS_VALID = (1 << 2), + GNSS_GLO_CLK_TIME_BIAS_UNC_VALID = (1 << 3), + GNSS_GLO_REF_FCOUNT_VALID = (1 << 4), + GNSS_GLO_NUM_CLOCK_RESETS_VALID = (1 << 5), + GNSS_GLO_FOUR_YEAR_VALID = (1 << 6) +} GnssGloTimeTypeBits; + +typedef struct { + GnssAidingDataSvMask svMask; // bitwise OR of GnssAidingDataSvBits + GnssAidingDataSvTypeMask svTypeMask; // bitwise OR of GnssAidingDataSvTypeBits +} GnssAidingDataSv; + +typedef uint32_t GnssAidingDataCommonMask; +typedef enum { + GNSS_AIDING_DATA_COMMON_POSITION_BIT = (1<<0), // position estimate + GNSS_AIDING_DATA_COMMON_TIME_BIT = (1<<1), // reset all clock values + GNSS_AIDING_DATA_COMMON_UTC_BIT = (1<<2), // UTC estimate + GNSS_AIDING_DATA_COMMON_RTI_BIT = (1<<3), // RTI + GNSS_AIDING_DATA_COMMON_FREQ_BIAS_EST_BIT = (1<<4), // frequency bias estimate + GNSS_AIDING_DATA_COMMON_CELLDB_BIT = (1<<5), // all celldb info +} GnssAidingDataCommonBits; + +typedef struct { + GnssAidingDataCommonMask mask; // bitwise OR of GnssAidingDataCommonBits +} GnssAidingDataCommon; + +typedef uint32_t DrEngineAidingDataMask; +typedef enum { + DR_ENGINE_AIDING_DATA_CALIBRATION_BIT = (1<<0), // Calibration data for DRE engine +} DrEngineAidingDataBits; + +typedef struct { + bool deleteAll; // if true, delete all aiding data and ignore other params + GnssAidingDataSv sv; // SV specific aiding data + GnssAidingDataCommon common; // common aiding data + DrEngineAidingDataMask dreAidingDataMask;// aiding data mask for dr engine + PositioningEngineMask posEngineMask; // engines to perform the delete operation on. +} GnssAidingData; + +typedef uint16_t DrCalibrationStatusMask; +typedef enum { + // Indicate that roll calibration is needed. Need to take more turns on level ground + DR_ROLL_CALIBRATION_NEEDED = (1<<0), + // Indicate that pitch calibration is needed. Need to take more turns on level ground + DR_PITCH_CALIBRATION_NEEDED = (1<<1), + // Indicate that yaw calibration is needed. Need to accelerate in a straight line + DR_YAW_CALIBRATION_NEEDED = (1<<2), + // Indicate that odo calibration is needed. Need to accelerate in a straight line + DR_ODO_CALIBRATION_NEEDED = (1<<3), + // Indicate that gyro calibration is needed. Need to take more turns on level ground + DR_GYRO_CALIBRATION_NEEDED = (1<<4) +} DrCalibrationStatusBits; + +typedef struct { + uint32_t size; // set to sizeof(Location) + LocationFlagsMask flags; // bitwise OR of LocationFlagsBits to mark which params are valid + uint64_t timestamp; // UTC timestamp for location fix, milliseconds since January 1, 1970 + double latitude; // in degrees + double longitude; // in degrees + double altitude; // in meters above the WGS 84 reference ellipsoid + float speed; // in meters per second + float bearing; // in degrees; range [0, 360) + float accuracy; // in meters + float verticalAccuracy; // in meters + float speedAccuracy; // in meters/second + float bearingAccuracy; // in degrees (0 to 359.999) + float conformityIndex; // in range [0, 1] + LocationTechnologyMask techMask; + LocationSpoofMask spoofMask; + uint64_t elapsedRealTime; // in ns + uint64_t elapsedRealTimeUnc; // in ns +} Location; + +typedef enum { + LOC_REQ_ENGINE_FUSED_BIT = (1<<0), + LOC_REQ_ENGINE_SPE_BIT = (1<<1), + LOC_REQ_ENGINE_PPE_BIT = (1<<2), + LOC_REQ_ENGINE_VPE_BIT = (1<<3) +} LocReqEngineTypeMask; + +typedef enum { + LOC_OUTPUT_ENGINE_FUSED = 0, + /** This is the GNSS fix from modem */ + LOC_OUTPUT_ENGINE_SPE = 1, + /** This is the GNSS fix with correction PPP/RTK correction */ + LOC_OUTPUT_ENGINE_PPE = 2, + LOC_OUTPUT_ENGINE_VPE = 3, + LOC_OUTPUT_ENGINE_COUNT, +} LocOutputEngineType; + +struct LocationOptions { + uint32_t size; // set to sizeof(LocationOptions) + uint32_t minInterval; // in milliseconds + uint32_t minDistance; // in meters. if minDistance > 0, gnssSvCallback/gnssNmeaCallback/ + // gnssMeasurementsCallback may not be called + GnssSuplMode mode; // Standalone/MS-Based/MS-Assisted + // behavior when this field is 0: + // if engine hub is running, this will be fused fix, + // if engine hub is not running, this will be SPE fix + LocReqEngineTypeMask locReqEngTypeMask; + + inline LocationOptions() : + size(0), minInterval(0), minDistance(0), mode(GNSS_SUPL_MODE_STANDALONE), + locReqEngTypeMask((LocReqEngineTypeMask)0) {} +}; + +typedef enum { + GNSS_POWER_MODE_INVALID = 0, + GNSS_POWER_MODE_M1, /* Improved Accuracy Mode */ + GNSS_POWER_MODE_M2, /* Normal Mode */ + GNSS_POWER_MODE_M3, /* Background Mode */ + GNSS_POWER_MODE_M4, /* Background Mode */ + GNSS_POWER_MODE_M5 /* Background Mode */ +} GnssPowerMode; + +struct TrackingOptions : LocationOptions { + GnssPowerMode powerMode; /* Power Mode to be used for time based tracking + sessions */ + uint32_t tbm; /* Time interval between measurements specified in millis. + Applicable to background power modes */ + + inline TrackingOptions() : + LocationOptions(), powerMode(GNSS_POWER_MODE_INVALID), tbm(0) {} + inline TrackingOptions(uint32_t s, GnssPowerMode m, uint32_t t) : + LocationOptions(), powerMode(m), tbm(t) { LocationOptions::size = s; } + inline TrackingOptions(const LocationOptions& options) : + LocationOptions(options), powerMode(GNSS_POWER_MODE_INVALID), tbm(0) {} + inline void setLocationOptions(const LocationOptions& options) { + size = sizeof(TrackingOptions); + minInterval = options.minInterval; + minDistance = options.minDistance; + mode = options.mode; + locReqEngTypeMask = options.locReqEngTypeMask; + } + inline LocationOptions getLocationOptions() { + LocationOptions locOption; + locOption.size = sizeof(locOption); + locOption.minDistance = minDistance; + locOption.minInterval = minInterval; + locOption.mode = mode; + locOption.locReqEngTypeMask = locReqEngTypeMask; + return locOption; + } +}; + +struct BatchingOptions : LocationOptions { + BatchingMode batchingMode; + + inline BatchingOptions() : + LocationOptions(), batchingMode(BATCHING_MODE_ROUTINE) {} + inline BatchingOptions(uint32_t s, BatchingMode m) : + LocationOptions(), batchingMode(m) { LocationOptions::size = s; } + inline BatchingOptions(const LocationOptions& options) : + LocationOptions(options), batchingMode(BATCHING_MODE_ROUTINE) {} + inline void setLocationOptions(const LocationOptions& options) { + minInterval = options.minInterval; + minDistance = options.minDistance; + mode = options.mode; + } +}; + +typedef struct { + uint32_t size; + BatchingStatus batchingStatus; +} BatchingStatusInfo; + +typedef struct { + uint32_t size; // set to sizeof(GeofenceOption) + GeofenceBreachTypeMask breachTypeMask; // bitwise OR of GeofenceBreachTypeBits + uint32_t responsiveness; // in milliseconds + uint32_t dwellTime; // in seconds +} GeofenceOption; + +typedef struct { + uint32_t size; // set to sizeof(GeofenceInfo) + double latitude; // in degrees + double longitude; // in degrees + double radius; // in meters +} GeofenceInfo; + +typedef struct { + uint32_t size; // set to sizeof(GeofenceBreachNotification) + uint32_t count; // number of ids in array + uint32_t* ids; // array of ids that have breached + Location location; // location associated with breach + GeofenceBreachType type; // type of breach + uint64_t timestamp; // timestamp of breach +} GeofenceBreachNotification; + +typedef struct { + uint32_t size; // set to sizeof(GeofenceBreachNotification) + GeofenceStatusAvailable available; // GEOFENCE_STATUS_AVAILABILE_NO/_YES + LocationTechnologyType techType; // GNSS +} GeofenceStatusNotification; + +typedef struct { + uint64_t gpsSvUsedIdsMask; + uint64_t gloSvUsedIdsMask; + uint64_t galSvUsedIdsMask; + uint64_t bdsSvUsedIdsMask; + uint64_t qzssSvUsedIdsMask; + uint64_t navicSvUsedIdsMask; +} GnssLocationSvUsedInPosition; + +typedef struct { + /** GnssSignalType mask */ + GnssSignalTypeMask gnssSignalType; + /** Specifies GNSS Constellation Type */ + Gnss_LocSvSystemEnumType gnssConstellation; + /** Unique SV Identifier. + * For SV Range of supported constellation, please refer to + * the comment section of svId in GnssSv. + * For GLONASS: When slot-number to SV ID mapping is unknown, set as 255. + */ + uint16_t gnssSvId; +} GnssMeasUsageInfo; + +/** @struct + Body Frame parameters +*/ +typedef struct { + GnssLocationPosDataMask bodyFrameDataMask; // Contains Body frame LocPosDataMask bits + float longAccel; // Forward Acceleration in body frame (m/s2) + float latAccel; // Sideward Acceleration in body frame (m/s2) + float vertAccel; // Vertical Acceleration in body frame (m/s2) + float yawRate; // Heading Rate (Radians/second) + float pitch; // Body pitch (Radians) + float longAccelUnc; // Uncertainty of Forward Acceleration in body frame + float latAccelUnc; // Uncertainty of Side-ward Acceleration in body frame + float vertAccelUnc; // Uncertainty of Vertical Acceleration in body frame + float yawRateUnc; // Uncertainty of Heading Rate + float pitchUnc; // Uncertainty of Body pitch +} GnssLocationPositionDynamics; + +typedef struct { + GnssLocationPosDataMaskExt bodyFrameDataMask; // Contains Ext Body frame LocPosDataMask bits + float pitchRate; // Body pitch rate (Radians/second) + float pitchRateUnc; // Uncertainty of pitch rate (Radians/second) + float roll; // Roll of body frame. Clockwise positive. (radian + float rollUnc; // Uncertainty of Roll, 68% confidence level (radian) + float rollRate; // Roll rate of body frame. Clockwise positive. (radian/second) + float rollRateUnc; // Uncertainty of Roll rate, 68% confidence level (radian/second) + float yaw; // Yaw of body frame. Clockwise positive (radian) + float yawUnc; // Uncertainty of Yaw, 68% confidence level (radian) +} GnssLocationPositionDynamicsExt; + +typedef struct { + /** Validity mask for below fields */ + GnssSystemTimeStructTypeFlags validityMask; + /** Extended week number at reference tick. + Unit: Week. + Set to 65535 if week number is unknown. + For GPS: + Calculated from midnight, Jan. 6, 1980. + OTA decoded 10 bit GPS week is extended to map between: + [NV6264 to (NV6264 + 1023)]. + NV6264: Minimum GPS week number configuration. + Default value of NV6264: 1738 + For BDS: + Calculated from 00:00:00 on January 1, 2006 of Coordinated Universal Time (UTC). + For GAL: + Calculated from 00:00 UT on Sunday August 22, 1999 (midnight between August 21 and August 22). + */ + uint16_t systemWeek; + /** Time in to the current week at reference tick. + Unit: Millisecond. Range: 0 to 604799999. + Check for systemClkTimeUncMs before use */ + uint32_t systemMsec; + /** System clock time bias (sub-millisecond) + Units: Millisecond + Note: System time (TOW Millisecond) = systemMsec - systemClkTimeBias. + Check for systemClkTimeUncMs before use. */ + float systemClkTimeBias; + /** Single sided maximum time bias uncertainty + Units: Millisecond */ + float systemClkTimeUncMs; + /** FCount (free running HW timer) value. Don't use for relative time purpose + due to possible discontinuities. + Unit: Millisecond */ + uint32_t refFCount; + /** Number of clock resets/discontinuities detected, affecting the local hardware counter value. */ + uint32_t numClockResets; +} GnssSystemTimeStructType; + +typedef struct { + /** GLONASS day number in four years. Refer to GLONASS ICD. + Applicable only for GLONASS and shall be ignored for other constellations. + If unknown shall be set to 65535 */ + uint16_t gloDays; + /** Validity mask for below fields */ + GnssGloTimeStructTypeFlags validityMask; + /** GLONASS time of day in Millisecond. Refer to GLONASS ICD. + Units: Millisecond + Check for gloClkTimeUncMs before use */ + uint32_t gloMsec; + /** GLONASS clock time bias (sub-millisecond) + Units: Millisecond + Note: GLO time (TOD Millisecond) = gloMsec - gloClkTimeBias. + Check for gloClkTimeUncMs before use. */ + float gloClkTimeBias; + /** Single sided maximum time bias uncertainty + Units: Millisecond */ + float gloClkTimeUncMs; + /** FCount (free running HW timer) value. Don't use for relative time purpose + due to possible discontinuities. + Unit: Millisecond */ + uint32_t refFCount; + /** Number of clock resets/discontinuities detected, affecting the local hardware counter value. */ + uint32_t numClockResets; + /** GLONASS four year number from 1996. Refer to GLONASS ICD. + Applicable only for GLONASS and shall be ignored for other constellations. + If unknown shall be set to 255 */ + uint8_t gloFourYear; +} GnssGloTimeStructType; + +typedef union { + GnssSystemTimeStructType gpsSystemTime; + GnssSystemTimeStructType galSystemTime; + GnssSystemTimeStructType bdsSystemTime; + GnssSystemTimeStructType qzssSystemTime; + GnssGloTimeStructType gloSystemTime; + GnssSystemTimeStructType navicSystemTime; +} SystemTimeStructUnion; + /** Time applicability of PVT report */ +typedef struct { + /** Specifies GNSS system time reported. Mandatory field */ + Gnss_LocSvSystemEnumType gnssSystemTimeSrc; + /** Reporting of GPS system time is recommended. + If GPS time is unknown & other satellite system time is known, + it should be reported. + Mandatory field + */ + SystemTimeStructUnion u; +} GnssSystemTime; + +typedef uint32_t DrSolutionStatusMask; +#define VEHICLE_SENSOR_SPEED_INPUT_DETECTED (1<<0) +#define VEHICLE_SENSOR_SPEED_INPUT_USED (1<<1) + +typedef struct { + double latitude; // in degree + double longitude; // in degree + float altitude; // altitude wrt to ellipsoid +} LLAInfo; + +enum loc_sess_status { + LOC_SESS_SUCCESS, + LOC_SESS_INTERMEDIATE, + LOC_SESS_FAILURE +}; + +typedef struct { + uint32_t size; // set to sizeof(GnssLocationInfo) + Location location; // basic locaiton info, latitude, longitude, and etc + GnssLocationInfoFlagMask flags; // bitwise OR of GnssLocationInfoBits for param validity + float altitudeMeanSeaLevel; // altitude wrt mean sea level + float pdop; // position dilusion of precision + float hdop; // horizontal dilusion of precision + float vdop; // vertical dilusion of precision + float gdop; // geometric dilution of precision + float tdop; // time dilution of precision + float magneticDeviation; // magnetic deviation + LocationReliability horReliability; // horizontal reliability + LocationReliability verReliability; // vertical reliability + float horUncEllipseSemiMajor; // horizontal elliptical accuracy semi-major axis + float horUncEllipseSemiMinor; // horizontal elliptical accuracy semi-minor axis + float horUncEllipseOrientAzimuth; // horizontal elliptical accuracy azimuth + float northStdDeviation; // North standard deviation Unit: Meters + float eastStdDeviation; // East standard deviation. Unit: Meters + float northVelocity; // North Velocity.Unit: Meters/sec + float eastVelocity; // East Velocity Unit Meters/sec + float upVelocity; // Up Velocity. Unit Meters/sec + float northVelocityStdDeviation; + float eastVelocityStdDeviation; + float upVelocityStdDeviation; + uint16_t numSvUsedInPosition; + GnssLocationSvUsedInPosition svUsedInPosition;// Gnss sv used in position data + GnssLocationNavSolutionMask navSolutionMask; // Nav solution mask to indicate sbas corrections + GnssLocationPositionDynamics bodyFrameData; // Body Frame Dynamics: 4wayAcceleration and + // pitch set with validity + GnssSystemTime gnssSystemTime; // GNSS System Time + uint8_t numOfMeasReceived; // Number of measurements received for use in fix. + GnssMeasUsageInfo measUsageInfo[GNSS_SV_MAX]; // GNSS Measurement Usage info + uint8_t leapSeconds; // leap second + float timeUncMs; // Time uncertainty in milliseconds + uint8_t calibrationConfidence; // Sensor calibration confidence percent, + // in range of [0, 100] + DrCalibrationStatusMask calibrationStatus; // Sensor calibration status + // location engine type. When the fix. when the type is set to + // LOC_ENGINE_SRC_FUSED, the fix is the propagated/aggregated + // reports from all engines running on the system (e.g.: + // DR/SPE/PPE/VPE). To check which location engine contributes to + // the fused output, check for locOutputEngMask. + LocOutputEngineType locOutputEngType; + // when loc output eng type is set to fused, this field + // indicates the set of engines contribute to the fix. + PositioningEngineMask locOutputEngMask; + // When robust location is enabled, this field + // will how well the various input data considered for + // navigation solution conform to expectations. + // Range: 0 (least conforming) to 1 (most conforming) + float conformityIndex; + GnssLocationPositionDynamicsExt bodyFrameDataExt; // Additional Body Frame Dynamics + // VRR-based latitude/longitude/altitude + LLAInfo llaVRPBased; + // VRR-based east, north, and up velocity + float enuVelocityVRPBased[3]; + DrSolutionStatusMask drSolutionStatusMask; + // true: altitude is assumed, false: altitude is calculated + bool altitudeAssumed; + // location session status + loc_sess_status sessionStatus; +} GnssLocationInfoNotification; + +typedef struct { + uint32_t size; // set to sizeof(GnssNiNotification) + GnssNiType type; // type of NI (Voice, SUPL, Control Plane) + GnssNiOptionsMask options; // bitwise OR of GnssNiOptionsBits + uint32_t timeout; // time (seconds) to wait for user input + GnssNiResponse timeoutResponse; // the response that should be sent when timeout expires + char requestor[GNSS_NI_REQUESTOR_MAX]; // the requestor that is making the request + GnssNiEncodingType requestorEncoding; // the encoding type for requestor + char message[GNSS_NI_MESSAGE_ID_MAX]; // the message to show user + GnssNiEncodingType messageEncoding; // the encoding type for message + char extras[GNSS_NI_MESSAGE_ID_MAX]; +} GnssNiNotification; + +// carrier frequency of the signal tracked +#define GPS_L1CA_CARRIER_FREQUENCY (1575420000.0) +#define GPS_L1C_CARRIER_FREQUENCY (1575420000.0) +#define GPS_L2C_L_CARRIER_FREQUENCY (1227600000.0) +#define GPS_L5_Q_CARRIER_FREQUENCY (1176450000.0) +#define GLONASS_G1_CARRIER_FREQUENCY (1602000000.0) +#define GLONASS_G2_CARRIER_FREQUENCY (1246000000.0) +#define GALILEO_E1_C_CARRIER_FREQUENCY (1575420000.0) +#define GALILEO_E5A_Q_CARRIER_FREQUENCY (1176450000.0) +#define GALILEO_E5B_Q_CARRIER_FREQUENCY (1207140000.0) +#define BEIDOU_B1_I_CARRIER_FREQUENCY (1561098000.0) +#define BEIDOU_B1C_CARRIER_FREQUENCY (1575420000.0) +#define BEIDOU_B2_I_CARRIER_FREQUENCY (1207140000.0) +#define BEIDOU_B2A_I_CARRIER_FREQUENCY (1176450000.0) +#define BEIDOU_B2A_Q_CARRIER_FREQUENCY (1176450000.0) +#define QZSS_L1CA_CARRIER_FREQUENCY (1575420000.0) +#define QZSS_L1S_CARRIER_FREQUENCY (1575420000.0) +#define QZSS_L2C_L_CARRIER_FREQUENCY (1227600000.0) +#define QZSS_L5_Q_CARRIER_FREQUENCY (1176450000.0) +#define SBAS_L1_CA_CARRIER_FREQUENCY (1575420000.0) +#define NAVIC_L5_CARRIER_FREQUENCY (1176450000.0) + +typedef struct { + uint32_t size; // set to sizeof(GnssSv) + // Unique SV Identifier. + // SV Range for supported constellation is specified as below: + // - For GPS: 1 to 32 + // - For GLONASS: 65 to 96 + // - For SBAS: 120 to 158 and 183 to 191 + // - For QZSS: 193 to 197 + // - For BDS: 201 to 263 + // - For GAL: 301 to 336 + // - For NAVIC: 401 to 414 + uint16_t svId; + GnssSvType type; // type of SV (GPS, SBAS, GLONASS, QZSS, BEIDOU, GALILEO, NAVIC) + float cN0Dbhz; // signal strength + float elevation; // elevation of SV (in degrees) + float azimuth; // azimuth of SV (in degrees) + GnssSvOptionsMask gnssSvOptionsMask; // Bitwise OR of GnssSvOptionsBits + float carrierFrequencyHz; // carrier frequency of the signal tracked + GnssSignalTypeMask gnssSignalTypeMask; // Specifies GNSS signal type + double basebandCarrierToNoiseDbHz; // baseband signal strength + uint16_t gloFrequency; // GLONASS Frequency channel number +} GnssSv; + +struct GnssConfigSetAssistanceServer { + uint32_t size; // set to sizeof(GnssConfigSetAssistanceServer) + GnssAssistanceType type; // SUPL or C2K + const char* hostName; // null terminated string + uint32_t port; // port of server + + inline bool equals(const GnssConfigSetAssistanceServer& config) { + if (config.type == type && config.port == port && + ((NULL == config.hostName && NULL == hostName) || + (NULL != config.hostName && NULL != hostName && + 0 == strcmp(config.hostName, hostName)))) { + return true; + } + return false; + } +}; + +typedef struct { + // set to sizeof(GnssMeasurementsData) + uint32_t size; + // bitwise OR of GnssMeasurementsDataFlagsBits + GnssMeasurementsDataFlagsMask flags; + // Unique SV Identifier + // For SV Range of supported constellation, + // please refer to the comment section of svId in GnssSv. + int16_t svId; + GnssSvType svType; + double timeOffsetNs; + GnssMeasurementsStateMask stateMask; // bitwise OR of GnssMeasurementsStateBits + int64_t receivedSvTimeNs; + int64_t receivedSvTimeUncertaintyNs; + double carrierToNoiseDbHz; + double pseudorangeRateMps; + double pseudorangeRateUncertaintyMps; + GnssMeasurementsAdrStateMask adrStateMask; // bitwise OR of GnssMeasurementsAdrStateBits + double adrMeters; + double adrUncertaintyMeters; + float carrierFrequencyHz; + int64_t carrierCycles; + double carrierPhase; + double carrierPhaseUncertainty; + GnssMeasurementsMultipathIndicator multipathIndicator; + double signalToNoiseRatioDb; + double agcLevelDb; + GnssMeasurementsCodeType codeType; + char otherCodeTypeName[GNSS_MAX_NAME_LENGTH]; + double basebandCarrierToNoiseDbHz; + GnssSignalTypeMask gnssSignalType; + double fullInterSignalBiasNs; + double fullInterSignalBiasUncertaintyNs; + double satelliteInterSignalBiasNs; + double satelliteInterSignalBiasUncertaintyNs; + int16_t gloFrequency; + uint8_t cycleSlipCount; +} GnssMeasurementsData; + +typedef struct { + GnssSvType svType; + float carrierFrequencyHz; + GnssMeasurementsCodeType codeType; + char otherCodeTypeName[GNSS_MAX_NAME_LENGTH]; +} GnssMeasurementsSignalType; + +typedef struct { + uint32_t size; // set to sizeof(GnssReflectingPlane) + double latitudeDegrees; + double longitudeDegrees; + double altitudeMeters; + double azimuthDegrees; +} GnssReflectingPlane; + +typedef struct { + uint32_t size; // set to sizeof(GnssSingleSatCorrection) + GnssSingleSatCorrectionMask flags; + GnssSvType svType; + uint16_t svId; + float carrierFrequencyHz; + float probSatIsLos; + float excessPathLengthMeters; + float excessPathLengthUncertaintyMeters; + GnssReflectingPlane reflectingPlane; +} GnssSingleSatCorrection; + +typedef struct { + uint32_t size; // set to sizeof(GnssMeasurementCorrections) + double latitudeDegrees; + double longitudeDegrees; + double altitudeMeters; + double horizontalPositionUncertaintyMeters; + double verticalPositionUncertaintyMeters; + uint64_t toaGpsNanosecondsOfWeek; + std::vector satCorrections; + bool hasEnvironmentBearing; + float environmentBearingDegrees; + float environmentBearingUncertaintyDegrees; +} GnssMeasurementCorrections; + +typedef struct { + uint32_t size; // set to sizeof(GnssMeasurementsClock) + GnssMeasurementsClockFlagsMask flags; // bitwise OR of GnssMeasurementsClockFlagsBits + int16_t leapSecond; + int64_t timeNs; + double timeUncertaintyNs; + int64_t fullBiasNs; + double biasNs; + double biasUncertaintyNs; + double driftNsps; + double driftUncertaintyNsps; + uint32_t hwClockDiscontinuityCount; + GnssMeasurementsSignalType referenceSignalTypeForIsb; + uint64_t elapsedRealTime; // in ns + uint64_t elapsedRealTimeUnc; // in ns +} GnssMeasurementsClock; + +typedef struct { + uint32_t size; // set to sizeof(GnssSvNotification) + uint32_t count; // number of SVs in the GnssSv array + bool gnssSignalTypeMaskValid; + GnssSv gnssSvs[GNSS_SV_MAX]; // information on a number of SVs +} GnssSvNotification; + +typedef struct { + uint32_t size; // set to sizeof(GnssNmeaNotification) + uint64_t timestamp; // timestamp + const char* nmea; // nmea text + uint32_t length; // length of the nmea text +} GnssNmeaNotification; + +typedef struct { + uint32_t size; // set to sizeof(GnssDataNotification) + GnssDataMask gnssDataMask[GNSS_LOC_MAX_NUMBER_OF_SIGNAL_TYPES]; // bitwise OR of GnssDataBits + double jammerInd[GNSS_LOC_MAX_NUMBER_OF_SIGNAL_TYPES]; // Jammer Indication + double agc[GNSS_LOC_MAX_NUMBER_OF_SIGNAL_TYPES]; // Automatic gain control +} GnssDataNotification; + +typedef struct { + uint32_t size; // set to sizeof(GnssMeasurementsNotification) + uint32_t count; // number of items in GnssMeasurements array + GnssMeasurementsData measurements[GNSS_MEASUREMENTS_MAX]; + GnssMeasurementsClock clock; // clock +} GnssMeasurementsNotification; + +typedef uint32_t GnssSvId; + +struct GnssSvIdSource{ + uint32_t size; // set to sizeof(GnssSvIdSource) + GnssSvType constellation; // constellation for the sv to blacklist + GnssSvId svId; // Unique SV Identifier, + // For SV Range of supported constellation, + // please refer to the comment section of svId in GnssSv. +}; +inline bool operator ==(GnssSvIdSource const& left, GnssSvIdSource const& right) { + return left.size == right.size && + left.constellation == right.constellation && left.svId == right.svId; +} + +#define GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK ((uint64_t)0xFFFFFFFFFFFFFFFF) +struct GnssSvIdConfig { + uint32_t size; // set to sizeof(GnssSvIdConfig) + + // GLONASS - SV 65 maps to bit 0 +#define GNSS_SV_CONFIG_GLO_INITIAL_SV_ID 65 + uint64_t gloBlacklistSvMask; + + // BEIDOU - SV 201 maps to bit 0 +#define GNSS_SV_CONFIG_BDS_INITIAL_SV_ID 201 + uint64_t bdsBlacklistSvMask; + + // QZSS - SV 193 maps to bit 0 +#define GNSS_SV_CONFIG_QZSS_INITIAL_SV_ID 193 + uint64_t qzssBlacklistSvMask; + + // GAL - SV 301 maps to bit 0 +#define GNSS_SV_CONFIG_GAL_INITIAL_SV_ID 301 + uint64_t galBlacklistSvMask; + + // SBAS - SV 120 to 158, maps to 0 to 38 + // SV 183 to 191, maps to 39 to 47 +#define GNSS_SV_CONFIG_SBAS_INITIAL_SV_ID 120 +#define GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH 39 +#define GNSS_SV_CONFIG_SBAS_INITIAL2_SV_ID 183 + uint64_t sbasBlacklistSvMask; + + //Navic - SV 401 maps to bit 0 +#define GNSS_SV_CONFIG_NAVIC_INITIAL_SV_ID 401 + uint64_t navicBlacklistSvMask; + + inline bool equals(const GnssSvIdConfig& inConfig) { + if ((inConfig.size == size) && + (inConfig.gloBlacklistSvMask == gloBlacklistSvMask) && + (inConfig.bdsBlacklistSvMask == bdsBlacklistSvMask) && + (inConfig.qzssBlacklistSvMask == qzssBlacklistSvMask) && + (inConfig.galBlacklistSvMask == galBlacklistSvMask) && + (inConfig.sbasBlacklistSvMask == sbasBlacklistSvMask) && + (inConfig.navicBlacklistSvMask == navicBlacklistSvMask)) { + return true; + } else { + return false; + } + } +}; + +// Specify the valid mask for robust location configure +// defined in GnssConfigRobustLocation. +enum GnssConfigRobustLocationValidMask { + // GnssConfigRobustLocation has valid enabled field. + GNSS_CONFIG_ROBUST_LOCATION_ENABLED_VALID_BIT = (1<<0), + // GnssConfigRobustLocation has valid enabledForE911 field. + GNSS_CONFIG_ROBUST_LOCATION_ENABLED_FOR_E911_VALID_BIT = (1<<1), + // GnssConfigRobustLocation has valid version field. + GNSS_CONFIG_ROBUST_LOCATION_VERSION_VALID_BIT = (1<<2), +}; + +struct GnssConfigRobustLocationVersion { + // Major version number + uint8_t major; + // Minor version number + uint16_t minor; + inline bool equals(const GnssConfigRobustLocationVersion& version) const { + return (version.major == major && version.minor == minor); + } +}; + +// specify the robust location configuration used by modem GNSS engine +struct GnssConfigRobustLocation { + GnssConfigRobustLocationValidMask validMask; + bool enabled; + bool enabledForE911; + GnssConfigRobustLocationVersion version; + + inline bool equals(const GnssConfigRobustLocation& config) const { + if (config.validMask == validMask && + config.enabled == enabled && + config.enabledForE911 == enabledForE911 && + config.version.equals(version)) { + return true; + } + return false; + } +}; + +/* Mask indicating enabled or disabled constellations and + secondary frequency.*/ +typedef uint64_t GnssSvTypesMask; +typedef enum { + GNSS_SV_TYPES_MASK_GLO_BIT = (1<<0), + GNSS_SV_TYPES_MASK_BDS_BIT = (1<<1), + GNSS_SV_TYPES_MASK_QZSS_BIT = (1<<2), + GNSS_SV_TYPES_MASK_GAL_BIT = (1<<3), + GNSS_SV_TYPES_MASK_NAVIC_BIT = (1<<4), + GNSS_SV_TYPES_MASK_GPS_BIT = (1<<5), +} GnssSvTypesMaskBits; +#define GNSS_SV_TYPES_MASK_ALL \ + (GNSS_SV_TYPES_MASK_GPS_BIT|GNSS_SV_TYPES_MASK_GLO_BIT|GNSS_SV_TYPES_MASK_BDS_BIT|\ + GNSS_SV_TYPES_MASK_QZSS_BIT|GNSS_SV_TYPES_MASK_GAL_BIT|GNSS_SV_TYPES_MASK_NAVIC_BIT) + +/* This SV Type config is injected directly to GNSS Adapter + * bypassing Location API */ +struct GnssSvTypeConfig{ + uint32_t size; // set to sizeof(GnssSvTypeConfig) + // Enabled Constellations + GnssSvTypesMask enabledSvTypesMask; + // Disabled Constellations + GnssSvTypesMask blacklistedSvTypesMask; + + inline bool equals (const GnssSvTypeConfig& inConfig) const { + return ((inConfig.size == size) && + (inConfig.enabledSvTypesMask == enabledSvTypesMask) && + (inConfig.blacklistedSvTypesMask == blacklistedSvTypesMask)); + } +}; + +struct GnssConfig{ + uint32_t size; // set to sizeof(GnssConfig) + GnssConfigFlagsMask flags; // bitwise OR of GnssConfigFlagsBits to mark which params are valid + GnssConfigGpsLock gpsLock; + GnssConfigSuplVersion suplVersion; + GnssConfigSetAssistanceServer assistanceServer; + GnssConfigLppProfileMask lppProfileMask; + GnssConfigLppeControlPlaneMask lppeControlPlaneMask; + GnssConfigLppeUserPlaneMask lppeUserPlaneMask; + GnssConfigAGlonassPositionProtocolMask aGlonassPositionProtocolMask; + GnssConfigEmergencyPdnForEmergencySupl emergencyPdnForEmergencySupl; + GnssConfigSuplEmergencyServices suplEmergencyServices; + GnssConfigSuplModeMask suplModeMask; //bitwise OR of GnssConfigSuplModeBits + std::vector blacklistedSvIds; + uint32_t emergencyExtensionSeconds; + GnssConfigRobustLocation robustLocationConfig; + uint16_t minGpsWeek; + uint8_t minSvElevation; + GnssSvTypeConfig secondaryBandConfig; + + inline bool equals(const GnssConfig& config) { + if (flags == config.flags && + gpsLock == config.gpsLock && + suplVersion == config.suplVersion && + assistanceServer.equals(config.assistanceServer) && + lppProfileMask == config.lppProfileMask && + lppeControlPlaneMask == config.lppeControlPlaneMask && + lppeUserPlaneMask == config.lppeUserPlaneMask && + aGlonassPositionProtocolMask == config.aGlonassPositionProtocolMask && + emergencyPdnForEmergencySupl == config.emergencyPdnForEmergencySupl && + suplEmergencyServices == config.suplEmergencyServices && + suplModeMask == config.suplModeMask && + blacklistedSvIds == config.blacklistedSvIds && + emergencyExtensionSeconds == config.emergencyExtensionSeconds && + robustLocationConfig.equals(config.robustLocationConfig) && + minGpsWeek == config.minGpsWeek && + minSvElevation == config.minSvElevation && + secondaryBandConfig.equals(config.secondaryBandConfig)) { + return true; + } + return false; + } +}; + +typedef struct { + uint32_t size; // set to sizeof + bool mValid; + Location mLocation; + double verticalAccuracyMeters; + double speedAccuracyMetersPerSecond; + double bearingAccuracyDegrees; + timespec mUtcReported; +} GnssDebugLocation; + +typedef struct { + uint32_t size; // set to sizeof + bool mValid; + int64_t timeEstimate; + float timeUncertaintyNs; + float frequencyUncertaintyNsPerSec; +} GnssDebugTime; + +typedef struct { + // set to sizeof + uint32_t size; + // Unique SV Identifier + // For SV Range of supported constellation, + // please refer to the comment section of svId in GnssSv. + uint32_t svid; + GnssSvType constellation; + GnssEphemerisType mEphemerisType; + GnssEphemerisSource mEphemerisSource; + GnssEphemerisHealth mEphemerisHealth; + float ephemerisAgeSeconds; + bool serverPredictionIsAvailable; + float serverPredictionAgeSeconds; +} GnssDebugSatelliteInfo; + +typedef struct { + uint32_t size; // set to sizeof + GnssDebugLocation mLocation; + GnssDebugTime mTime; + std::vector mSatelliteInfo; +} GnssDebugReport; + +typedef uint32_t LeapSecondSysInfoMask; +typedef enum { + // current leap second info is available. This info will only + // be available if the leap second change info is not available. + // + // If leap second change info is avaiable, to figure out + // the current leap second info, compare current gps time with + // the gps timestamp of leap second change to know whether to choose + // leapSecondBefore or leapSecondAfter as current leap second. + LEAP_SECOND_SYS_INFO_CURRENT_LEAP_SECONDS_BIT = (1ULL << 0), + // the last known leap change event is available. + // The info can be available on two scenario: + // 1: this leap second change event has been scheduled and yet to happen + // 2: this leap second change event has already happened and next + // leap second change event has not yet been scheduled. + LEAP_SECOND_SYS_INFO_LEAP_SECOND_CHANGE_BIT = (1ULL << 1), +} LeapSecondSysInfoDataBits; + +struct LeapSecondChangeInfo { + // GPS timestamp that corrresponds to the last known + // leap second change event. + // + // The info can be available on two scenario: + // 1: this leap second change event has been scheduled and yet to happen + // 2: this leap second change event has already happened and next + // leap second change event has not yet been scheduled. + GnssSystemTimeStructType gpsTimestampLsChange; + // Number of leap seconds prior to the leap second change event + // that corresponds to the timestamp at gpsTimestampLsChange. + uint8_t leapSecondsBeforeChange; + // Number of leap seconds after the leap second change event + // that corresponds to the timestamp at gpsTimestampLsChange. + uint8_t leapSecondsAfterChange; +}; + +struct LeapSecondSystemInfo { + LeapSecondSysInfoMask leapSecondInfoMask; + uint8_t leapSecondCurrent; + LeapSecondChangeInfo leapSecondChangeInfo; +}; + +typedef uint32_t LocationSystemInfoMask; +typedef enum { + // contains current leap second or leap second change info + LOCATION_SYS_INFO_LEAP_SECOND = (1ULL << 0), +} LocationSystemInfoDataBits; + +struct LocationSystemInfo { + LocationSystemInfoMask systemInfoMask; + LeapSecondSystemInfo leapSecondSysInfo; +}; + +// Specify the set of terrestrial technologies +enum TerrestrialTechMask { + TERRESTRIAL_TECH_GTP_WWAN = 1 << 0, +}; + +// Specify parameters related to lever arm +struct LeverArmParams { + // Offset along the vehicle forward axis + float forwardOffsetMeters; + // Offset along the vehicle starboard axis + float sidewaysOffsetMeters; + // Offset along the vehicle up axis + float upOffsetMeters; +}; + +typedef uint32_t LeverArmTypeMask; + +enum LeverArmTypeBits { + // Lever arm regarding the VRP (Vehicle Reference Point) w.r.t + // the origin (at the GPS Antenna) + LEVER_ARM_TYPE_GNSS_TO_VRP_BIT = (1<<0), + // Lever arm regarding GNSS Antenna w.r.t the origin at the IMU + // e.g.: inertial measurement unit for DR (dead reckoning + // engine) + LEVER_ARM_TYPE_DR_IMU_TO_GNSS_BIT = (1<<1), + // Lever arm regarding GNSS Antenna w.r.t the origin at the + // IMU (inertial measurement unit) for VEPP (vision enhanced + // precise positioning engine) + LEVER_ARM_TYPE_VEPP_IMU_TO_GNSS_BIT = (1<<2) +}; + +struct LeverArmConfigInfo { + // Valid mask for the types of lever arm parameters provided + LeverArmTypeMask leverArmValidMask; + // Lever arm regarding the VRP (Vehicle Reference Point) w.r.t the origin + // (at the GPS Antenna) + LeverArmParams gnssToVRP; + // Lever arm parameters regarding GNSS Antenna w.r.t the origin at the IMU + // (inertial measurement unit) for DR (dead reckoning engine) + LeverArmParams drImuToGnss; + // Lever arm regarding GNSS Antenna w.r.t the origin at the IMU + // (inertial measurement unit) for VEPP (vision enhanced precise position engine) + LeverArmParams veppImuToGnss; +}; + +// Specify vehicle body-to-Sensor mount parameters to be used +// by dead reckoning positioning engine. +struct BodyToSensorMountParams { + // The misalignment of the sensor board along the + // horizontal plane of the vehicle chassis measured looking + // from the vehicle to forward direction. In unit of degree. + float rollOffset; + // The misalignment along the horizontal plane of the vehicle + // chassis measured looking from the vehicle to the right + // side. Positive pitch indicates vehicle is inclined such + // that forward wheels are at higher elevation than rear + // wheels. In unit of degree. + float yawOffset; + // The angle between the vehicle forward direction and the + // sensor axis as seen from the top of the vehicle, and + // measured in counterclockwise direction. In unit of degree. + float pitchOffset; + // Single uncertainty number that may be the largest of the + // roll, pitch and yaw offset uncertainties. + float offsetUnc; +}; + +typedef uint64_t DeadReckoningEngineConfigValidMask; +// Specify the valid mask for the configuration paramters of +// dead reckoning position engine. +enum DeadReckoningEngineConfigValidBit { + // DeadReckoningEngineConfig has valid + // DeadReckoningEngineConfig::DeadReckoningEngineConfig. + BODY_TO_SENSOR_MOUNT_PARAMS_BIT = (1<<0), + // DeadReckoningEngineConfig has valid + // DeadReckoningEngineConfig::vehicleSpeedScaleFactor. + VEHICLE_SPEED_SCALE_FACTOR_BIT = (1<<1), + // DeadReckoningEngineConfig has valid + // DeadReckoningEngineConfig::vehicleSpeedScaleFactorUnc. + VEHICLE_SPEED_SCALE_FACTOR_UNC_BIT = (1<<2), + // DeadReckoningEngineConfig has valid + // DeadReckoningEngineConfig::gyroScaleFactor. + GYRO_SCALE_FACTOR_BIT = (1<<3), + // DeadReckoningEngineConfig has valid + // DeadReckoningEngineConfig::gyroScaleFactorUnc. + GYRO_SCALE_FACTOR_UNC_BIT = (1<<4), +}; + +// Specify the configuration parameters for the dead reckoning +// position engine +struct DeadReckoningEngineConfig{ + // Specify the valid fields in the config. + DeadReckoningEngineConfigValidMask validMask; + // Body to sensor mount parameters for use by dead reckoning + // positioning engine + BodyToSensorMountParams bodyToSensorMountParams; + + // Vehicle Speed Scale Factor configuration input for the dead + // reckoning positioning engine. The multiplicative scale + // factor is applied to received Vehicle Speed value (in m/s) + // to obtain the true Vehicle Speed. + // + // Range is [0.9 to 1.1]. + // + // Note: The scale factor is specific to a given vehicle + // make & model. + float vehicleSpeedScaleFactor; + // Vehicle Speed Scale Factor Uncertainty (68% confidence) + // configuration input for the dead reckoning positioning + // engine. + // + // Range is [0.0 to 0.1]. + // + // Note: The scale factor unc is specific to a given vehicle + // make & model. + float vehicleSpeedScaleFactorUnc; + + // Gyroscope Scale Factor configuration input for the dead + // reckoning positioning engine. The multiplicative scale + // factor is applied to received gyroscope value to obtain the + // true value. + // + // Range is [0.9 to 1.1]. + // + // Note: The scale factor is specific to the Gyroscope sensor + // and typically derived from either sensor data-sheet or + // from actual calibration. + float gyroScaleFactor; + + // Gyroscope Scale Factor uncertainty (68% confidence) + // configuration input for the dead reckoning positioning + // engine. + // + // Range is [0.0 to 0.1]. + // engine. + // + // Note: The scale factor unc is specific to the make & model + // of Gyroscope sensor and typically derived from either + // sensor data-sheet or from actual calibration. + float gyroScaleFactorUnc; +}; + +/* Provides the capabilities of the system + capabilities callback is called once soon after createInstance is called */ +typedef std::function capabilitiesCallback; + +/* Used by tracking, batching, and miscellanous APIs + responseCallback is called for every Tracking, Batching API, and Miscellanous API */ +typedef std::function responseCallback; + +/* Used by APIs that gets more than one LocationError in it's response + collectiveResponseCallback is called for every geofence API call. + ids array and LocationError array are only valid until collectiveResponseCallback returns. */ +typedef std::function collectiveResponseCallback; + +/* Used for startTracking API, optional can be NULL + trackingCallback is called when delivering a location in a tracking session + broadcasted to all clients, no matter if a session has started by client */ +typedef std::function trackingCallback; + +/* Used for startBatching API, optional can be NULL + batchingCallback is called when delivering locations in a batching session. + broadcasted to all clients, no matter if a session has started by client */ +typedef std::function batchingCallback; + +typedef std::function & listOfCompletedTrips +)> batchingStatusCallback; + +/* Gives GNSS Location information, optional can be NULL + gnssLocationInfoCallback is called only during a tracking session + broadcasted to all clients, no matter if a session has started by client */ +typedef std::function gnssLocationInfoCallback; + +/* Gives default combined location information from all engines and + location information individually from selected engines. + This callback is only used when there are multiple engines + running in the system. + + optional can be NULL + + engineLocationsInfoCallback is called only during a tracking session + broadcasted to all clients, no matter if a session has started by client */ +typedef std::function engineLocationsInfoCallback; + +/* Used for addGeofences API, optional can be NULL + geofenceBreachCallback is called when any number of geofences have a state change */ +typedef std::function geofenceBreachCallback; + +/* Used for addGeofences API, optional can be NULL + geofenceStatusCallback is called when any number of geofences have a status change */ +typedef std::function geofenceStatusCallback; + +/* Network Initiated request, optional can be NULL + This callback should be responded to by calling gnssNiResponse */ +typedef std::function gnssNiCallback; + +/* Gives GNSS SV information, optional can be NULL + gnssSvCallback is called only during a tracking session + broadcasted to all clients, no matter if a session has started by client */ +typedef std::function gnssSvCallback; + +/* Gives GNSS NMEA data, optional can be NULL + gnssNmeaCallback is called only during a tracking session + broadcasted to all clients, no matter if a session has started by client */ +typedef std::function gnssNmeaCallback; + +/* Gives GNSS data, optional can be NULL + gnssDataCallback is called only during a tracking session + broadcasted to all clients, no matter if a session has started by client */ +typedef std::function gnssDataCallback; + +/* Gives GNSS Measurements information, optional can be NULL + gnssMeasurementsCallback is called only during a tracking session + broadcasted to all clients, no matter if a session has started by client */ +typedef std::function gnssMeasurementsCallback; + +/* Provides the current GNSS configuration to the client */ +typedef std::function gnssConfigCallback; + +/* LocationSystemInfoCb is for receiving rare occuring location + system information update. optional, can be NULL. +*/ +typedef std::function locationSystemInfoCallback; + +typedef std::function locationApiDestroyCompleteCallback; + +typedef uint16_t LocationAdapterTypeMask; +typedef enum { + LOCATION_ADAPTER_GNSS_TYPE_BIT = (1<<0), // adapter type is GNSS + LOCATION_ADAPTER_BATCHING_TYPE_BIT = (1<<1), // adapter type is BATCHING + LOCATION_ADAPTER_GEOFENCE_TYPE_BIT = (1<<2) // adapter type is geo fence +} LocationAdapterTypeBits; + +typedef struct { + uint32_t size; // set to sizeof(LocationCallbacks) + capabilitiesCallback capabilitiesCb; // mandatory + responseCallback responseCb; // mandatory + collectiveResponseCallback collectiveResponseCb; // mandatory + trackingCallback trackingCb; // optional + batchingCallback batchingCb; // optional + geofenceBreachCallback geofenceBreachCb; // optional + geofenceStatusCallback geofenceStatusCb; // optional + gnssLocationInfoCallback gnssLocationInfoCb; // optional + gnssNiCallback gnssNiCb; // optional + gnssSvCallback gnssSvCb; // optional + gnssNmeaCallback gnssNmeaCb; // optional + gnssDataCallback gnssDataCb; // optional + gnssMeasurementsCallback gnssMeasurementsCb; // optional + batchingStatusCallback batchingStatusCb; // optional + locationSystemInfoCallback locationSystemInfoCb; // optional + engineLocationsInfoCallback engineLocationsInfoCb; // optional +} LocationCallbacks; + +typedef struct { + uint32_t size; // set to sizeof + double x; + double xUncertainty; + double y; + double yUncertainty; + double z; + double zUncertainty; +} GnssCoordinate; + +typedef struct { + uint32_t size; // set to sizeof + double carrierFrequencyMHz; + GnssCoordinate phaseCenterOffsetCoordinateMillimeters; + std::vector> phaseCenterVariationCorrectionMillimeters; + std::vector> phaseCenterVariationCorrectionUncertaintyMillimeters; + std::vector> signalGainCorrectionDbi; + std::vector> signalGainCorrectionUncertaintyDbi; +} GnssAntennaInformation; + +typedef struct { + uint32_t size; // set to sizeof + bool requiresNmeaLocation; + std::string hostNameOrIp; // null terminated string + std::string mountPoint; // null terminated string + std::string username; // null terminated string + std::string password; // null terminated string + uint32_t port; + bool useSSL; +} GnssNtripConnectionParams; + +typedef struct { + uint64_t meQtimer1; + uint64_t meQtimer2; + uint64_t meQtimer3; + uint64_t peQtimer1; + uint64_t peQtimer2; + uint64_t peQtimer3; + uint64_t smQtimer1; + uint64_t smQtimer2; + uint64_t smQtimer3; + uint64_t locMwQtimer; + uint64_t hlosQtimer1; + uint64_t hlosQtimer2; + uint64_t hlosQtimer3; + uint64_t hlosQtimer4; + uint64_t hlosQtimer5; +} GnssLatencyInfo; + +#endif /* LOCATIONDATATYPES_H */ diff --git a/gps/location/Makefile.am b/gps/location/Makefile.am new file mode 100644 index 0000000..6a5a750 --- /dev/null +++ b/gps/location/Makefile.am @@ -0,0 +1,44 @@ +ACLOCAL_AMFLAGS = -I m4 + +AM_CFLAGS = \ + -I./ \ + -I../utils \ + $(LOCPLA_CFLAGS) \ + $(GPSUTILS_CFLAGS) \ + -std=c++11 + +liblocation_api_la_SOURCES = \ + LocationAPI.cpp \ + LocationAPIClientBase.cpp + +if USE_EXTERNAL_AP +AM_CFLAGS += -DFEATURE_EXTERNAL_AP +endif + +if USE_GLIB +liblocation_api_la_CFLAGS = -DUSE_GLIB $(AM_CFLAGS) @GLIB_CFLAGS@ +liblocation_api_la_LDFLAGS = -lstdc++ -Wl,-z,defs -lpthread @GLIB_LIBS@ -shared -version-info 1:0:0 +liblocation_api_la_CPPFLAGS = -DUSE_GLIB $(AM_CFLAGS) $(AM_CPPFLAGS) @GLIB_CFLAGS@ +else +liblocation_api_la_CFLAGS = $(AM_CFLAGS) +liblocation_api_la_LDFLAGS = -Wl,-z,defs -lpthread -shared -version-info 1:0:0 +liblocation_api_la_CPPFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS) +endif + +liblocation_api_la_LIBADD = -lstdc++ -ldl $(GPSUTILS_LIBS) + +library_include_HEADERS = \ + LocationAPI.h \ + LocationAPIClientBase.h \ + location_interface.h \ + LocationDataTypes.h \ + ILocationAPI.h + +#Create and Install libraries +lib_LTLIBRARIES = liblocation_api.la + +library_includedir = $(pkgincludedir) + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = location-api.pc +EXTRA_DIST = $(pkgconfig_DATA) diff --git a/gps/location/configure.ac b/gps/location/configure.ac new file mode 100644 index 0000000..f8376f5 --- /dev/null +++ b/gps/location/configure.ac @@ -0,0 +1,95 @@ +# configure.ac -- Autoconf script for gps location-api-iface +# +# Process this file with autoconf to produce a configure script + +# Requires autoconf tool later than 2.61 +AC_PREREQ(2.61) +# Initialize the gps location-api-iface package version 1.0.0 +AC_INIT([location-api-iface],1.0.0) +# Does not strictly follow GNU Coding standards +AM_INIT_AUTOMAKE([foreign subdir-objects]) +# Disables auto rebuilding of configure, Makefile.ins +AM_MAINTAINER_MODE +# Verifies the --srcdir is correct by checking for the path +AC_CONFIG_SRCDIR([location-api.pc.in]) +# defines some macros variable to be included by source +AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_MACRO_DIR([m4]) + +# Checks for programs. +AC_PROG_LIBTOOL +AC_PROG_CXX +AC_PROG_CC +AM_PROG_CC_C_O +AC_PROG_AWK +AC_PROG_CPP +AC_PROG_INSTALL +AC_PROG_LN_S +AC_PROG_MAKE_SET +PKG_PROG_PKG_CONFIG + +# Checks for libraries. +PKG_CHECK_MODULES([GPSUTILS], [gps-utils]) +AC_SUBST([GPSUTILS_CFLAGS]) +AC_SUBST([GPSUTILS_LIBS]) + +AC_ARG_WITH([core_includes], + AC_HELP_STRING([--with-core-includes=@<:@dir@:>@], + [Specify the location of the core headers]), + [core_incdir=$withval], + with_core_includes=no) + +if test "x$with_core_includes" != "xno"; then + CPPFLAGS="${CPPFLAGS} -I${core_incdir}" +fi + +AC_ARG_WITH([locpla_includes], + AC_HELP_STRING([--with-locpla-includes=@<:@dir@:>@], + [Specify the path to locpla-includes in loc-pla_git.bb]), + [locpla_incdir=$withval], + with_locpla_includes=no) + +if test "x${with_locpla_includes}" != "xno"; then + AC_SUBST(LOCPLA_CFLAGS, "-I${locpla_incdir}") +fi + +AC_SUBST([CPPFLAGS]) + +AC_ARG_WITH([glib], + AC_HELP_STRING([--with-glib], + [enable glib, building HLOS systems which use glib])) + +if (test "x${with_glib}" = "xyes"); then + AC_DEFINE(ENABLE_USEGLIB, 1, [Define if HLOS systems uses glib]) + PKG_CHECK_MODULES(GTHREAD, gthread-2.0 >= 2.16, dummy=yes, + AC_MSG_ERROR(GThread >= 2.16 is required)) + PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.16, dummy=yes, + AC_MSG_ERROR(GLib >= 2.16 is required)) + GLIB_CFLAGS="$GLIB_CFLAGS $GTHREAD_CFLAGS" + GLIB_LIBS="$GLIB_LIBS $GTHREAD_LIBS" + + AC_SUBST(GLIB_CFLAGS) + AC_SUBST(GLIB_LIBS) +fi + +AM_CONDITIONAL(USE_GLIB, test "x${with_glib}" = "xyes") + +# External AP +AC_ARG_WITH([external_ap], + AC_HELP_STRING([--with-external_ap=@<:@dir@:>@], + [Using External Application Processor]), + [], + with_external_ap=no) + +if test "x$with_external_ap" != "xno"; then + CPPFLAGS="${CPPFLAGS} -DFEATURE_EXTERNAL_AP" +fi + +AM_CONDITIONAL(USE_EXTERNAL_AP, test "x${with_external_ap}" = "xyes") + +AC_CONFIG_FILES([ \ + Makefile \ + location-api.pc \ + ]) + +AC_OUTPUT diff --git a/gps/location/location-api.pc.in b/gps/location/location-api.pc.in new file mode 100644 index 0000000..c7b146a --- /dev/null +++ b/gps/location/location-api.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: location-api +Description: Location API +Version: @VERSION +Libs: -L${libdir} -llocation_api +Cflags: -I${includedir}/location-api diff --git a/gps/location/location_interface.h b/gps/location/location_interface.h new file mode 100644 index 0000000..69d4f0c --- /dev/null +++ b/gps/location/location_interface.h @@ -0,0 +1,144 @@ +/* Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LOCATION_INTERFACE_H +#define LOCATION_INTERFACE_H + +#include +#include +#include + +/* Used for callback to deliver GNSS energy consumed */ +/** @fn + @brief Used by query API that retrieves energy consumed by + modem GNSS engine. + + @param gnssEnergyConsumedFromFirstBoot: + Energy consumed by the GNSS engine since the first bootup + in units of 0.1 milli watt seconds. + A value of 0xffffffffffffffff indicates an invalid reading. +*/ +typedef std::function GnssEnergyConsumedCallback; + +typedef void (*removeClientCompleteCallback)(LocationAPI* client); + +struct GnssInterface { + size_t size; + void (*initialize)(void); + void (*deinitialize)(void); + void (*addClient)(LocationAPI* client, const LocationCallbacks& callbacks); + void (*removeClient)(LocationAPI* client, removeClientCompleteCallback rmClientCb); + void (*requestCapabilities)(LocationAPI* client); + uint32_t (*startTracking)(LocationAPI* client, TrackingOptions&); + void (*updateTrackingOptions)(LocationAPI* client, uint32_t id, TrackingOptions&); + void (*stopTracking)(LocationAPI* client, uint32_t id); + void (*gnssNiResponse)(LocationAPI* client, uint32_t id, GnssNiResponse response); + void (*setControlCallbacks)(LocationControlCallbacks& controlCallbacks); + uint32_t (*enable)(LocationTechnologyType techType); + void (*disable)(uint32_t id); + uint32_t* (*gnssUpdateConfig)(const GnssConfig& config); + uint32_t* (*gnssGetConfig)(GnssConfigFlagsMask config); + void (*gnssUpdateSvTypeConfig)(GnssSvTypeConfig& config); + void (*gnssGetSvTypeConfig)(GnssSvTypeConfigCallback& callback); + void (*gnssResetSvTypeConfig)(); + uint32_t (*gnssDeleteAidingData)(GnssAidingData& data); + void (*gnssUpdateXtraThrottle)(const bool enabled); + void (*injectLocation)(double latitude, double longitude, float accuracy); + void (*injectTime)(int64_t time, int64_t timeReference, int32_t uncertainty); + void (*agpsInit)(const AgpsCbInfo& cbInfo); + void (*agpsDataConnOpen)(AGpsExtType agpsType, const char* apnName, int apnLen, int ipType); + void (*agpsDataConnClosed)(AGpsExtType agpsType); + void (*agpsDataConnFailed)(AGpsExtType agpsType); + void (*getDebugReport)(GnssDebugReport& report); + void (*updateConnectionStatus)(bool connected, int8_t type, bool roaming, + NetworkHandle networkHandle, std::string& apn); + void (*odcpiInit)(const OdcpiRequestCallback& callback, OdcpiPrioritytype priority); + void (*odcpiInject)(const Location& location); + void (*blockCPI)(double latitude, double longitude, float accuracy, + int blockDurationMsec, double latLonDiffThreshold); + void (*getGnssEnergyConsumed)(GnssEnergyConsumedCallback energyConsumedCb); + void (*enableNfwLocationAccess)(bool enable); + void (*nfwInit)(const NfwCbInfo& cbInfo); + void (*getPowerStateChanges)(std::function powerStateCb); + void (*injectLocationExt)(const GnssLocationInfoNotification &locationInfo); + void (*updateBatteryStatus)(bool charging); + void (*updateSystemPowerState)(PowerStateType systemPowerState); + uint32_t (*setConstrainedTunc) (bool enable, float tuncConstraint, uint32_t energyBudget); + uint32_t (*setPositionAssistedClockEstimator) (bool enable); + uint32_t (*gnssUpdateSvConfig)(const GnssSvTypeConfig& constellationEnablementConfig, + const GnssSvIdConfig& blacklistSvConfig); + uint32_t (*configLeverArm)(const LeverArmConfigInfo& configInfo); + bool (*measCorrInit)(const measCorrSetCapabilitiesCb setCapabilitiesCb); + bool (*measCorrSetCorrections)(const GnssMeasurementCorrections gnssMeasCorr); + void (*measCorrClose)(); + uint32_t (*antennaInfoInit)(const antennaInfoCb antennaInfoCallback); + void (*antennaInfoClose) (); + uint32_t (*configRobustLocation)(bool enable, bool enableForE911); + uint32_t (*configMinGpsWeek)(uint16_t minGpsWeek); + uint32_t (*configDeadReckoningEngineParams)(const DeadReckoningEngineConfig& dreConfig); + void (*updateNTRIPGGAConsent)(bool consentAccepted); + void (*enablePPENtripStream)(const GnssNtripConnectionParams& params, bool enableRTKEngine); + void (*disablePPENtripStream)(); + uint32_t (*gnssUpdateSecondaryBandConfig)(const GnssSvTypeConfig& secondaryBandConfig); + uint32_t (*gnssGetSecondaryBandConfig)(); + void (*resetNetworkInfo)(); + uint32_t (*configEngineRunState)(PositioningEngineMask engType, + LocEngineRunState engState); +}; + +struct BatchingInterface { + size_t size; + void (*initialize)(void); + void (*deinitialize)(void); + void (*addClient)(LocationAPI* client, const LocationCallbacks& callbacks); + void (*removeClient)(LocationAPI* client, removeClientCompleteCallback rmClientCb); + void (*requestCapabilities)(LocationAPI* client); + uint32_t (*startBatching)(LocationAPI* client, BatchingOptions&); + void (*stopBatching)(LocationAPI* client, uint32_t id); + void (*updateBatchingOptions)(LocationAPI* client, uint32_t id, BatchingOptions&); + void (*getBatchedLocations)(LocationAPI* client, uint32_t id, size_t count); +}; + +struct GeofenceInterface { + size_t size; + void (*initialize)(void); + void (*deinitialize)(void); + void (*addClient)(LocationAPI* client, const LocationCallbacks& callbacks); + void (*removeClient)(LocationAPI* client, removeClientCompleteCallback rmClientCb); + void (*requestCapabilities)(LocationAPI* client); + uint32_t* (*addGeofences)(LocationAPI* client, size_t count, GeofenceOption*, GeofenceInfo*); + void (*removeGeofences)(LocationAPI* client, size_t count, uint32_t* ids); + void (*modifyGeofences)(LocationAPI* client, size_t count, uint32_t* ids, + GeofenceOption* options); + void (*pauseGeofences)(LocationAPI* client, size_t count, uint32_t* ids); + void (*resumeGeofences)(LocationAPI* client, size_t count, uint32_t* ids); +}; + +#endif /* LOCATION_INTERFACE_H */ -- cgit v1.2.3