diff options
Diffstat (limited to 'location')
-rw-r--r-- | location/Android.mk | 41 | ||||
-rw-r--r-- | location/ILocationAPI.h | 194 | ||||
-rw-r--r-- | location/LocationAPI.cpp | 725 | ||||
-rw-r--r-- | location/LocationAPI.h | 266 | ||||
-rw-r--r-- | location/LocationAPIClientBase.cpp | 954 | ||||
-rw-r--r-- | location/LocationAPIClientBase.h | 587 | ||||
-rw-r--r-- | location/LocationDataTypes.h | 1465 | ||||
-rw-r--r-- | location/Makefile.am | 40 | ||||
-rw-r--r-- | location/configure.ac | 82 | ||||
-rw-r--r-- | location/location-api.pc.in | 10 | ||||
-rw-r--r-- | location/location_interface.h | 121 |
11 files changed, 4485 insertions, 0 deletions
diff --git a/location/Android.mk b/location/Android.mk new file mode 100644 index 0000000..bbd6fbd --- /dev/null +++ b/location/Android.mk @@ -0,0 +1,41 @@ +ifneq ($(BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE),) +ifneq ($(BUILD_TINY_ANDROID),true) + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := liblocation_api +LOCAL_VENDOR_MODULE := true +LOCAL_MODULE_TAGS := optional + +LOCAL_SHARED_LIBRARIES := \ + libutils \ + libcutils \ + libgps.utils \ + libdl \ + liblog + +LOCAL_SRC_FILES += \ + LocationAPI.cpp \ + LocationAPIClientBase.cpp + +LOCAL_CFLAGS += \ + -fno-short-enums + +LOCAL_HEADER_LIBRARIES := \ + libloc_pla_headers \ + libgps.utils_headers + +LOCAL_PRELINK_MODULE := false + +LOCAL_CFLAGS += $(GNSS_CFLAGS) +include $(BUILD_SHARED_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := liblocation_api_headers +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH) +include $(BUILD_HEADER_LIBRARY) + +endif # not BUILD_TINY_ANDROID +endif # BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE diff --git a/location/ILocationAPI.h b/location/ILocationAPI.h new file mode 100644 index 0000000..3df6f79 --- /dev/null +++ b/location/ILocationAPI.h @@ -0,0 +1,194 @@ +/* Copyright (c) 2018 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(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; +}; + +#endif /* ILOCATIONAPI_H */ diff --git a/location/LocationAPI.cpp b/location/LocationAPI.cpp new file mode 100644 index 0000000..4348c27 --- /dev/null +++ b/location/LocationAPI.cpp @@ -0,0 +1,725 @@ +/* Copyright (c) 2017-2019 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 <location_interface.h> +#include <dlfcn.h> +#include <loc_pla.h> +#include <log_util.h> +#include <pthread.h> +#include <map> +#include <loc_misc_utils.h> + +typedef const GnssInterface* (getGnssInterface)(); +typedef const GeofenceInterface* (getGeofenceInterface)(); +typedef const BatchingInterface* (getBatchingInterface)(); + +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<LocationAPI*, LocationAPIDestroyCbData> + LocationClientDestroyCbMap; + +typedef std::map<LocationAPI*, LocationCallbacks> 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; + +template <typename T1, typename T2> +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 bool isGnssClient(LocationCallbacks& locationCallbacks) +{ + return (locationCallbacks.gnssNiCb != nullptr || + locationCallbacks.trackingCb != nullptr || + locationCallbacks.gnssLocationInfoCb != nullptr || + locationCallbacks.engineLocationsInfoCb != nullptr || + locationCallbacks.gnssMeasurementsCb != 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 ((true == invokeCallback) && (nullptr != destroyCompleteCb)) { + LOC_LOGd("invoke client destroy cb"); + (destroyCompleteCb) (); + LOC_LOGd("finish invoke client destroy cb"); + + 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) { + return NULL; + } + + LocationAPI* newLocationAPI = new LocationAPI(); + bool requestedCapabilities = false; + + pthread_mutex_lock(&gDataMutex); + + if (isGnssClient(locationCallbacks)) { + if (NULL == gData.gnssInterface && !gGnssLoadFailed) { + gData.gnssInterface = + (GnssInterface*)loadLocationInterface<GnssInterface, + getGnssInterface>("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<BatchingInterface, + getBatchingInterface>("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<GeofenceInterface, + getGeofenceInterface>("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 = + (isGnssClient(it->second) && NULL != gData.gnssInterface); + bool removeFromBatchingInf = + (isBatchingClient(it->second) && NULL != gData.batchingInterface); + bool removeFromGeofenceInf = + (isGeofenceClient(it->second) && NULL != gData.geofenceInterface); + bool needToWait = (removeFromGnssInf || removeFromBatchingInf || removeFromGeofenceInf); + LOC_LOGe("removeFromGnssInf: %d, removeFromBatchingInf: %d, removeFromGeofenceInf: %d," + "need %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_LOGe("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 ((NULL != destroyCompleteCb) && (false == needToWait)) { + invokeDestroyCb = true; + } + } else { + LOC_LOGE("%s:%d]: Location API client %p not found in client data", + __func__, __LINE__, this); + } + + pthread_mutex_unlock(&gDataMutex); + if (invokeDestroyCb == true) { + (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<GnssInterface, + getGnssInterface>("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<BatchingInterface, + getBatchingInterface>("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<GeofenceInterface, + getGeofenceInterface>("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); +} + +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<GnssInterface, + getGnssInterface>("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(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; +} diff --git a/location/LocationAPI.h b/location/LocationAPI.h new file mode 100644 index 0000000..6f5987c --- /dev/null +++ b/location/LocationAPI.h @@ -0,0 +1,266 @@ +/* Copyright (c) 2017-2018 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; +}; + +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 */ + virtual uint32_t* gnssUpdateConfig(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 */ + 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; +}; + +#endif /* LOCATIONAPI_H */ diff --git a/location/LocationAPIClientBase.cpp b/location/LocationAPIClientBase.cpp new file mode 100644 index 0000000..5a09712 --- /dev/null +++ b/location/LocationAPIClientBase.cpp @@ -0,0 +1,954 @@ +/* Copyright (c) 2017 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 <loc_pla.h> +#include <log_util.h> +#include <inttypes.h> +#include <loc_cfg.h> +#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; + } + } + } + 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; + } + } + 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<uint32_t> & tripCompletedList) { + beforeBatchingStatusCb(batchStatus, tripCompletedList); + }; + } + + if (mLocationAPI == nullptr ) { + mLocationAPI = LocationAPI::createInstance(locationCallbacks); + } else { + mLocationAPI->updateCallbacks(locationCallbacks); + } + + pthread_mutex_unlock(&mMutex); +} + +LocationAPIClientBase::~LocationAPIClientBase() +{ + pthread_mutex_lock(&mMutex); + + mGeofenceBreachCallback = nullptr; + + if (mLocationAPI) { + mLocationAPI->destroy(); + mLocationAPI = nullptr; + } + + for (int i = 0; i < REQUEST_MAX; i++) { + mRequestQueues[i].reset((uint32_t)0); + } + + pthread_mutex_unlock(&mMutex); + + pthread_mutex_destroy(&mMutex); +} + +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<GeofenceBreachTypeMask>* removedGeofenceBiDict = + new BiDict<GeofenceBreachTypeMask>(); + 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<uint32_t> sessionsVec = mGeofenceBiDict.getAllSessions(); + 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<uint32_t> & tripCompletedList) { + + // map the trip ids to the client ids + std::list<uint32_t> 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/location/LocationAPIClientBase.h b/location/LocationAPIClientBase.h new file mode 100644 index 0000000..098000c --- /dev/null +++ b/location/LocationAPIClientBase.h @@ -0,0 +1,587 @@ +/* Copyright (c) 2017-2019 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 <stdint.h> +#include <stdlib.h> +#include <pthread.h> +#include <queue> +#include <map> + +#include "LocationAPI.h" +#include <loc_pla.h> +#include <log_util.h> + +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<LocationAPIRequest*> 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(); + virtual ~LocationAPIClientBase(); + LocationAPIClientBase(const LocationAPIClientBase&) = delete; + LocationAPIClientBase& operator=(const LocationAPIClientBase&) = delete; + + 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<uint32_t> &/*listOfCompletedTrips*/) {} + void beforeBatchingStatusCb(BatchingStatusInfo batchStatus, + std::list<uint32_t> & 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*/) {} + +private: + // private inner classes + typedef struct { + uint32_t id; + uint32_t trackingSession; + uint32_t batchingSession; + uint32_t sessionMode; + } SessionEntity; + + template<typename T> + 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<uint32_t> getAllSessions() { + std::vector<uint32_t> 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<uint32_t, uint32_t> mForwardMap; + // mBackwardMap mapping session->id + std::map<uint32_t, uint32_t> mBackwardMap; + // mExtMap mapping session->ext + std::map<uint32_t, T> 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<GeofenceBreachTypeMask>* 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<GeofenceBreachTypeMask>* 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<GeofenceBreachTypeMask> mGeofenceBiDict; + BiDict<SessionEntity> mSessionBiDict; + int32_t mBatchSize; + bool mTracking; +}; + +#endif /* LOCATION_API_CLINET_BASE_H */ diff --git a/location/LocationDataTypes.h b/location/LocationDataTypes.h new file mode 100644 index 0000000..17094ab --- /dev/null +++ b/location/LocationDataTypes.h @@ -0,0 +1,1465 @@ +/* Copyright (c) 2018-2019 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 <vector> +#include <stdint.h> +#include <functional> +#include <list> +#include <string.h> + +#define GNSS_NI_REQUESTOR_MAX (256) +#define GNSS_NI_MESSAGE_ID_MAX (2048) +#define GNSS_SV_MAX (176) +#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 +} 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 +} LocationFlagsBits; + +typedef uint16_t LocationTechnologyMask; +typedef enum { + LOCATION_TECHNOLOGY_GNSS_BIT = (1<<0), // location was calculated using GNSS + LOCATION_TECHNOLOGY_CELL_BIT = (1<<1), // location was calculated using Cell + LOCATION_TECHNOLOGY_WIFI_BIT = (1<<2), // location was calculated using WiFi + LOCATION_TECHNOLOGY_SENSORS_BIT = (1<<3), // location was calculated using Sensors +} 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 { + LOCATION_SBAS_CORRECTION_IONO_BIT = (1<<0), // SBAS ionospheric correction is used + LOCATION_SBAS_CORRECTION_FAST_BIT = (1<<1), // SBAS fast correction is used + LOCATION_SBAS_CORRECTION_LONG_BIT = (1<<2), // SBAS long-tem correction is used + LOCATION_SBAS_INTEGRITY_BIT = (1<<3), // SBAS integrity information is used + LOCATION_NAV_CORRECTION_DGNSS_BIT = (1<<4), // Position Report is DGNSS corrected + LOCATION_NAV_CORRECTION_RTK_BIT = (1<<5), // Position Report is RTK corrected + LOCATION_NAV_CORRECTION_PPP_BIT = (1<<6) // Position Report is PPP corrected +} GnssLocationNavSolutionBits; + +typedef uint32_t GnssLocationPosTechMask; +typedef enum { + LOCATION_POS_TECH_DEFAULT_BIT = 0, + LOCATION_POS_TECH_SATELLITE_BIT = (1<<0), + LOCATION_POS_TECH_CELLID_BIT = (1<<1), + LOCATION_POS_TECH_WIFI_BIT = (1<<2), + LOCATION_POS_TECH_SENSORS_BIT = (1<<3), + LOCATION_POS_TECH_REFERENCE_LOCATION_BIT = (1<<4), + LOCATION_POS_TECH_INJECTED_COARSE_POSITION_BIT = (1<<5), + LOCATION_POS_TECH_AFLT_BIT = (1<<6), + LOCATION_POS_TECH_HYBRID_BIT = (1<<7), + LOCATION_POS_TECH_PPE_BIT = (1<<8) +} GnssLocationPosTechBits; + +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 GnssLocationInfoFlagMask; +typedef enum { + GNSS_LOCATION_INFO_ALTITUDE_MEAN_SEA_LEVEL_BIT = (1<<0), // valid altitude mean sea level + GNSS_LOCATION_INFO_DOP_BIT = (1<<1), // valid pdop, hdop, and vdop + GNSS_LOCATION_INFO_MAGNETIC_DEVIATION_BIT = (1<<2), // valid magnetic deviation + GNSS_LOCATION_INFO_HOR_RELIABILITY_BIT = (1<<3), // valid horizontal reliability + GNSS_LOCATION_INFO_VER_RELIABILITY_BIT = (1<<4), // valid vertical reliability + GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MAJOR_BIT = (1<<5), // valid elipsode semi major + GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MINOR_BIT = (1<<6), // valid elipsode semi minor + GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_AZIMUTH_BIT = (1<<7), // valid accuracy elipsode azimuth + GNSS_LOCATION_INFO_GNSS_SV_USED_DATA_BIT = (1<<8), // valid svUsedInPosition, + // numOfMeasReceived + // and measUsageInfo + GNSS_LOCATION_INFO_NAV_SOLUTION_MASK_BIT = (1<<9), // valid navSolutionMask + GNSS_LOCATION_INFO_POS_TECH_MASK_BIT = (1<<10),// valid LocPosTechMask + GNSS_LOCATION_INFO_SV_SOURCE_INFO_BIT = (1<<11),// valid LocSvInfoSource + GNSS_LOCATION_INFO_POS_DYNAMICS_DATA_BIT = (1<<12),// valid position dynamics data + GNSS_LOCATION_INFO_EXT_DOP_BIT = (1<<13),// valid gdop, tdop + GNSS_LOCATION_INFO_NORTH_STD_DEV_BIT = (1<<14),// valid North standard deviation + GNSS_LOCATION_INFO_EAST_STD_DEV_BIT = (1<<15),// valid East standard deviation + GNSS_LOCATION_INFO_NORTH_VEL_BIT = (1<<16),// valid North Velocity + GNSS_LOCATION_INFO_EAST_VEL_BIT = (1<<17),// valid East Velocity + GNSS_LOCATION_INFO_UP_VEL_BIT = (1<<18),// valid Up Velocity + GNSS_LOCATION_INFO_NORTH_VEL_UNC_BIT = (1<<19),// valid North Velocity Uncertainty + GNSS_LOCATION_INFO_EAST_VEL_UNC_BIT = (1<<20),// valid East Velocity Uncertainty + GNSS_LOCATION_INFO_UP_VEL_UNC_BIT = (1<<21),// valid Up Velocity Uncertainty + GNSS_LOCATION_INFO_LEAP_SECONDS_BIT = (1<<22),// valid leap seconds + GNSS_LOCATION_INFO_TIME_UNC_BIT = (1<<23),// valid time uncertainty + GNSS_LOCATION_INFO_NUM_SV_USED_IN_POSITION_BIT = (1<<24), // number of SV used in position + GNSS_LOCATION_INFO_CALIBRATION_CONFIDENCE_BIT = (1<<25), // valid sensor cal confidence + GNSS_LOCATION_INFO_CALIBRATION_STATUS_BIT = (1<<26), // valid sensor cal status + GNSS_LOCATION_INFO_OUTPUT_ENG_TYPE_BIT = (1<<27), // valid output engine type + GNSS_LOCATION_INFO_OUTPUT_ENG_MASK_BIT = (1<<28), // valid output engine mask +} 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; + +typedef uint32_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), +} LocationCapabilitiesBits; + +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, +} GnssConfigSuplVersion; + +// LTE Positioning Profile +typedef enum { + GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE = 0, // RRLP on LTE (Default) + GNSS_CONFIG_LPP_PROFILE_USER_PLANE, // LPP User Plane (UP) on LTE + GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE, // LPP_Control_Plane (CP) + GNSS_CONFIG_LPP_PROFILE_USER_PLANE_AND_CONTROL_PLANE, // Both LPP UP and CP +} GnssConfigLppProfile; + +// 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), +} 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), +} 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), +} 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 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), +} 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), +} GnssAidingDataSvTypeBits; + +/* 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_I RF Band */ + GNSS_SIGNAL_BEIDOU_B1I = (1<<9), + /** BEIDOU B1C RF Band */ + GNSS_SIGNAL_BEIDOU_B1C = (1<<10), + /** BEIDOU B2_I RF Band */ + GNSS_SIGNAL_BEIDOU_B2I = (1<<11), + /** BEIDOU B2A_I RF Band */ + GNSS_SIGNAL_BEIDOU_B2AI = (1<<12), + /** QZSS L1CA RF Band */ + GNSS_SIGNAL_QZSS_L1CA = (1<<13), + /** QZSS L1S RF Band */ + GNSS_SIGNAL_QZSS_L1S = (1<<14), + /** QZSS L2 RF Band */ + GNSS_SIGNAL_QZSS_L2 = (1<<15), + /** QZSS L5 RF Band */ + GNSS_SIGNAL_QZSS_L5 = (1<<16), + /** SBAS L1 RF Band */ + GNSS_SIGNAL_SBAS_L1 = (1<<17), + /** NAVIC L5 RF Band */ + GNSS_SIGNAL_NAVIC_L5 = (1<<18), + /** BEIDOU B2A_Q RF Band */ + GNSS_SIGNAL_BEIDOU_B2AQ = (1<<19) +} 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, + /**< QZSS 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) +} PositioningEngineBits; + +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 struct { + bool deleteAll; // if true, delete all aiding data and ignore other params + GnssAidingDataSv sv; // SV specific aiding data + GnssAidingDataCommon common; // common aiding data + 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) + LocationTechnologyMask techMask; + LocationSpoofMask spoofMask; +} Location; + +typedef enum { + LOC_REQ_ENGINE_FUSED_BIT = (1<<0), + LOC_REQ_ENGINE_SPE_BIT = (1<<1), + LOC_REQ_ENGINE_PPE_BIT = (1<<2), +} 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_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; + /** GNSS SV ID. + For GPS: 1 to 32 + For GLONASS: 65 to 96. When slot-number to SV ID mapping is unknown, set as 255. + For SBAS: 120 to 151 + For QZSS-L1CA:193 to 197 + For BDS: 201 to 237 + For GAL: 301 to 336 + For NAVIC: 401 to 414 */ + 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 { + /** 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 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 + GnssLocationPosTechMask posTechMask; // Position technology used in computing this fix + 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). 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; +} 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; + +typedef struct { + uint32_t size; // set to sizeof(GnssSv) + uint16_t svId; // Unique Identifier + GnssSvType type; // type of SV (GPS, SBAS, GLONASS, QZSS, BEIDOU, GALILEO) + 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 +} 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 { + uint32_t size; // set to sizeof(GnssMeasurementsData) + GnssMeasurementsDataFlagsMask flags; // bitwise OR of GnssMeasurementsDataFlagsBits + 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]; +} GnssMeasurementsData; + +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; +} 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; // sv id to blacklist +}; +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) +typedef struct { + 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; +} GnssSvIdConfig; + +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; + GnssConfigLppProfile lppProfile; + GnssConfigLppeControlPlaneMask lppeControlPlaneMask; + GnssConfigLppeUserPlaneMask lppeUserPlaneMask; + GnssConfigAGlonassPositionProtocolMask aGlonassPositionProtocolMask; + GnssConfigEmergencyPdnForEmergencySupl emergencyPdnForEmergencySupl; + GnssConfigSuplEmergencyServices suplEmergencyServices; + GnssConfigSuplModeMask suplModeMask; //bitwise OR of GnssConfigSuplModeBits + std::vector<GnssSvIdSource> blacklistedSvIds; + uint32_t emergencyExtensionSeconds; + + inline bool equals(const GnssConfig& config) { + if (flags == config.flags && + gpsLock == config.gpsLock && + suplVersion == config.suplVersion && + assistanceServer.equals(config.assistanceServer) && + lppProfile == config.lppProfile && + lppeControlPlaneMask == config.lppeControlPlaneMask && + lppeUserPlaneMask == config.lppeUserPlaneMask && + aGlonassPositionProtocolMask == config.aGlonassPositionProtocolMask && + emergencyPdnForEmergencySupl == config.emergencyPdnForEmergencySupl && + suplEmergencyServices == config.suplEmergencyServices && + suplModeMask == config.suplModeMask && + blacklistedSvIds == config.blacklistedSvIds && + emergencyExtensionSeconds == config.emergencyExtensionSeconds) { + 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 { + uint32_t size; // set to sizeof + 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<GnssDebugSatelliteInfo> 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; +}; + +/* Provides the capabilities of the system + capabilities callback is called once soon after createInstance is called */ +typedef std::function<void( + LocationCapabilitiesMask capabilitiesMask // bitwise OR of LocationCapabilitiesBits +)> capabilitiesCallback; + +/* Used by tracking, batching, and miscellanous APIs + responseCallback is called for every Tracking, Batching API, and Miscellanous API */ +typedef std::function<void( + LocationError err, // if not SUCCESS, then id is not valid + uint32_t id // id to be associated to the request +)> 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<void( + uint32_t count, // number of locations in arrays + LocationError* errs, // array of LocationError associated to the request + uint32_t* ids // array of ids to be associated to the request +)> 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<void( + Location location +)> 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<void( + uint32_t count, // number of locations in array + Location* location, // array of locations + BatchingOptions batchingOptions // Batching options +)> batchingCallback; + +typedef std::function<void( + BatchingStatusInfo batchingStatus, // batch status + std::list<uint32_t> & 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<void( + GnssLocationInfoNotification gnssLocationInfoNotification +)> 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<void( + uint32_t count, + GnssLocationInfoNotification* engineLocationInfoNotification +)> engineLocationsInfoCallback; + +/* Used for addGeofences API, optional can be NULL + geofenceBreachCallback is called when any number of geofences have a state change */ +typedef std::function<void( + GeofenceBreachNotification geofenceBreachNotification +)> geofenceBreachCallback; + +/* Used for addGeofences API, optional can be NULL + geofenceStatusCallback is called when any number of geofences have a status change */ +typedef std::function<void( + GeofenceStatusNotification geofenceStatusNotification +)> geofenceStatusCallback; + +/* Network Initiated request, optional can be NULL + This callback should be responded to by calling gnssNiResponse */ +typedef std::function<void( + uint32_t id, // id that should be used to respond by calling gnssNiResponse + GnssNiNotification gnssNiNotification +)> 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<void( + GnssSvNotification gnssSvNotification +)> 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<void( + GnssNmeaNotification gnssNmeaNotification +)> 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<void( + GnssDataNotification gnssDataNotification +)> 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<void( + GnssMeasurementsNotification gnssMeasurementsNotification +)> gnssMeasurementsCallback; + +/* Provides the current GNSS configuration to the client */ +typedef std::function<void( + GnssConfig& config +)> gnssConfigCallback; + +/* LocationSystemInfoCb is for receiving rare occuring location + system information update. optional, can be NULL. +*/ +typedef std::function<void( + LocationSystemInfo locationSystemInfo +)> locationSystemInfoCallback; + +typedef std::function<void( +)> 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; + +#endif /* LOCATIONDATATYPES_H */ diff --git a/location/Makefile.am b/location/Makefile.am new file mode 100644 index 0000000..fccdf94 --- /dev/null +++ b/location/Makefile.am @@ -0,0 +1,40 @@ +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_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/location/configure.ac b/location/configure.ac new file mode 100644 index 0000000..6391d65 --- /dev/null +++ b/location/configure.ac @@ -0,0 +1,82 @@ +# 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]) +# 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") + +AC_CONFIG_FILES([ \ + Makefile \ + location-api.pc \ + ]) + +AC_OUTPUT diff --git a/location/location-api.pc.in b/location/location-api.pc.in new file mode 100644 index 0000000..c7b146a --- /dev/null +++ b/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/location/location_interface.h b/location/location_interface.h new file mode 100644 index 0000000..fb15bea --- /dev/null +++ b/location/location_interface.h @@ -0,0 +1,121 @@ +/* Copyright (c) 2017-2019 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 <LocationAPI.h> +#include <gps_extended_c.h> + +/* 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<void( + uint64_t gnssEnergyConsumedFromFirstBoot +)> 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)(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); + void (*odcpiInit)(const OdcpiRequestCallback& callback); + 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)(void* powerStateCb); + void (*injectLocationExt)(const GnssLocationInfoNotification &locationInfo); + void (*updateBatteryStatus)(bool charging); +}; + +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 */ |