summaryrefslogtreecommitdiff
path: root/gps/location
diff options
context:
space:
mode:
Diffstat (limited to 'gps/location')
-rw-r--r--gps/location/Android.mk42
-rw-r--r--gps/location/LocationAPI.cpp644
-rw-r--r--gps/location/LocationAPI.h974
-rw-r--r--gps/location/LocationAPIClientBase.cpp911
-rw-r--r--gps/location/LocationAPIClientBase.h545
-rw-r--r--gps/location/Makefile.am40
-rw-r--r--gps/location/location_interface.h94
7 files changed, 3250 insertions, 0 deletions
diff --git a/gps/location/Android.mk b/gps/location/Android.mk
new file mode 100644
index 0000000..6ac8e36
--- /dev/null
+++ b/gps/location/Android.mk
@@ -0,0 +1,42 @@
+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_MODULE_PATH_32 := $(TARGET_OUT_VENDOR)/lib
+LOCAL_MODULE_PATH_64 := $(TARGET_OUT_VENDOR)/lib64
+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/gps/location/LocationAPI.cpp b/gps/location/LocationAPI.cpp
new file mode 100644
index 0000000..21d2de0
--- /dev/null
+++ b/gps/location/LocationAPI.cpp
@@ -0,0 +1,644 @@
+/* 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_TAG "LocSvc_LocationAPI"
+
+#include <location_interface.h>
+#include <dlfcn.h>
+#include <platform_lib_log_util.h>
+#include <pthread.h>
+#include <map>
+
+typedef void* (getLocationInterface)();
+typedef std::map<LocationAPI*, LocationCallbacks> LocationClientMap;
+typedef struct {
+ LocationClientMap clientData;
+ LocationControlAPI* controlAPI;
+ LocationControlCallbacks controlCallbacks;
+ GnssInterface* gnssInterface;
+ GeofenceInterface* geofenceInterface;
+ FlpInterface* flpInterface;
+} LocationAPIData;
+static LocationAPIData gData = {};
+static pthread_mutex_t gDataMutex = PTHREAD_MUTEX_INITIALIZER;
+static bool gGnssLoadFailed = false;
+static bool gFlpLoadFailed = false;
+static bool gGeofenceLoadFailed = false;
+
+static bool needsGnssTrackingInfo(LocationCallbacks& locationCallbacks)
+{
+ return (locationCallbacks.gnssLocationInfoCb != nullptr ||
+ locationCallbacks.gnssSvCb != nullptr ||
+ locationCallbacks.gnssNmeaCb != nullptr ||
+ locationCallbacks.gnssMeasurementsCb != nullptr);
+}
+
+static bool isGnssClient(LocationCallbacks& locationCallbacks)
+{
+ return (locationCallbacks.gnssNiCb != nullptr ||
+ locationCallbacks.trackingCb != nullptr ||
+ locationCallbacks.gnssMeasurementsCb != nullptr);
+}
+
+static bool isFlpClient(LocationCallbacks& locationCallbacks)
+{
+ return (locationCallbacks.trackingCb != nullptr ||
+ locationCallbacks.batchingCb != nullptr);
+}
+
+static bool isGeofenceClient(LocationCallbacks& locationCallbacks)
+{
+ return (locationCallbacks.geofenceBreachCb != nullptr ||
+ locationCallbacks.geofenceStatusCb != nullptr);
+}
+
+static void* loadLocationInterface(const char* library, const char* name) {
+ LOC_LOGD("%s]: loading %s::%s ...", __func__, library, name);
+ if (NULL == library || NULL == name) {
+ return NULL;
+ }
+ getLocationInterface* getter = NULL;
+ const char *error = NULL;
+ dlerror();
+ void *handle = dlopen(library, RTLD_NOW);
+ if (NULL == handle || (error = dlerror()) != NULL) {
+ LOC_LOGW("dlopen for %s failed, error = %s", library, error);
+ } else {
+ getter = (getLocationInterface*)dlsym(handle, name);
+ if ((error = dlerror()) != NULL) {
+ LOC_LOGW("dlsym for %s::%s failed, error = %s", library, name, error);
+ getter = NULL;
+ }
+ }
+
+ if (NULL == getter) {
+ return (void*)getter;
+ } else {
+ return (*getter)();
+ }
+}
+
+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("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 (isFlpClient(locationCallbacks)) {
+ if (NULL == gData.flpInterface && !gFlpLoadFailed) {
+ gData.flpInterface =
+ (FlpInterface*)loadLocationInterface("libflp.so", "getFlpInterface");
+ if (NULL == gData.flpInterface) {
+ gFlpLoadFailed = true;
+ LOC_LOGW("%s:%d]: No flp interface available", __func__, __LINE__);
+ } else {
+ gData.flpInterface->initialize();
+ }
+ }
+ if (NULL != gData.flpInterface) {
+ gData.flpInterface->addClient(newLocationAPI, locationCallbacks);
+ if (!requestedCapabilities) {
+ gData.flpInterface->requestCapabilities(newLocationAPI);
+ requestedCapabilities = true;
+ }
+ }
+ }
+
+ if (isGeofenceClient(locationCallbacks)) {
+ if (NULL == gData.geofenceInterface && !gGeofenceLoadFailed) {
+ gData.geofenceInterface =
+ (GeofenceInterface*)loadLocationInterface("libgeofence.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()
+{
+ delete this;
+}
+
+LocationAPI::LocationAPI()
+{
+ LOC_LOGD("LOCATION API CONSTRUCTOR");
+}
+
+LocationAPI::~LocationAPI()
+{
+ LOC_LOGD("LOCATION API DESTRUCTOR");
+ pthread_mutex_lock(&gDataMutex);
+
+ auto it = gData.clientData.find(this);
+ if (it != gData.clientData.end()) {
+ if (isGnssClient(it->second) && NULL != gData.gnssInterface) {
+ gData.gnssInterface->removeClient(it->first);
+ }
+ if (isFlpClient(it->second) && NULL != gData.flpInterface) {
+ gData.flpInterface->removeClient(it->first);
+ }
+ if (isGeofenceClient(it->second) && NULL != gData.geofenceInterface) {
+ gData.geofenceInterface->removeClient(it->first);
+ }
+ gData.clientData.erase(it);
+ } else {
+ LOC_LOGE("%s:%d]: Location API client %p not found in client data",
+ __func__, __LINE__, this);
+ }
+
+ pthread_mutex_unlock(&gDataMutex);
+}
+
+void
+LocationAPI::updateCallbacks(LocationCallbacks& locationCallbacks)
+{
+ if (nullptr == locationCallbacks.capabilitiesCb ||
+ nullptr == locationCallbacks.responseCb ||
+ nullptr == locationCallbacks.collectiveResponseCb) {
+ return;
+ }
+
+ pthread_mutex_lock(&gDataMutex);
+
+ if (isGnssClient(locationCallbacks)) {
+ if (NULL == gData.gnssInterface && !gGnssLoadFailed) {
+ gData.gnssInterface =
+ (GnssInterface*)loadLocationInterface("libgnss.so", "getGnssInterface");
+ if (NULL == gData.gnssInterface) {
+ gGnssLoadFailed = true;
+ LOC_LOGW("%s:%d]: No gnss interface available", __func__, __LINE__);
+ } else {
+ gData.gnssInterface->initialize();
+ }
+ }
+ if (NULL != gData.gnssInterface) {
+ // either adds new Client or updates existing Client
+ gData.gnssInterface->addClient(this, locationCallbacks);
+ }
+ }
+
+ if (isFlpClient(locationCallbacks)) {
+ if (NULL == gData.flpInterface && !gFlpLoadFailed) {
+ gData.flpInterface =
+ (FlpInterface*)loadLocationInterface("libflp.so", "getFlpInterface");
+ if (NULL == gData.flpInterface) {
+ gFlpLoadFailed = true;
+ LOC_LOGW("%s:%d]: No flp interface available", __func__, __LINE__);
+ } else {
+ gData.flpInterface->initialize();
+ }
+ }
+ if (NULL != gData.flpInterface) {
+ // either adds new Client or updates existing Client
+ gData.flpInterface->addClient(this, locationCallbacks);
+ }
+ }
+
+ if (isGeofenceClient(locationCallbacks)) {
+ if (NULL == gData.geofenceInterface && !gGeofenceLoadFailed) {
+ gData.geofenceInterface =
+ (GeofenceInterface*)loadLocationInterface("libgeofence.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(LocationOptions& locationOptions)
+{
+ uint32_t id = 0;
+ pthread_mutex_lock(&gDataMutex);
+
+ auto it = gData.clientData.find(this);
+ if (it != gData.clientData.end()) {
+ if (gData.flpInterface != NULL && locationOptions.minDistance > 0) {
+ id = gData.flpInterface->startTracking(this, locationOptions);
+ } else if (gData.gnssInterface != NULL && needsGnssTrackingInfo(it->second)) {
+ id = gData.gnssInterface->startTracking(this, locationOptions);
+ } else if (gData.flpInterface != NULL) {
+ id = gData.flpInterface->startTracking(this, locationOptions);
+ } else if (gData.gnssInterface != NULL) {
+ id = gData.gnssInterface->startTracking(this, locationOptions);
+ } else {
+ LOC_LOGE("%s:%d]: No gnss/flp 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()) {
+ // we don't know if tracking was started on flp or gnss, so we call stop on both, where
+ // stopTracking call to the incorrect interface will fail without response back to client
+ if (gData.gnssInterface != NULL) {
+ gData.gnssInterface->stopTracking(this, id);
+ }
+ if (gData.flpInterface != NULL) {
+ gData.flpInterface->stopTracking(this, id);
+ }
+ if (gData.flpInterface == NULL && gData.gnssInterface == NULL) {
+ LOC_LOGE("%s:%d]: No gnss/flp 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, LocationOptions& locationOptions)
+{
+ pthread_mutex_lock(&gDataMutex);
+
+ auto it = gData.clientData.find(this);
+ if (it != gData.clientData.end()) {
+ // we don't know if tracking was started on flp or gnss, so we call update on both, where
+ // updateTracking call to the incorrect interface will fail without response back to client
+ if (gData.gnssInterface != NULL) {
+ gData.gnssInterface->updateTrackingOptions(this, id, locationOptions);
+ }
+ if (gData.flpInterface != NULL) {
+ gData.flpInterface->updateTrackingOptions(this, id, locationOptions);
+ }
+ if (gData.flpInterface == NULL && gData.gnssInterface == NULL) {
+ LOC_LOGE("%s:%d]: No gnss/flp 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(LocationOptions& locationOptions, BatchingOptions &batchingOptions)
+{
+ uint32_t id = 0;
+ pthread_mutex_lock(&gDataMutex);
+
+ if (gData.flpInterface != NULL) {
+ id = gData.flpInterface->startBatching(this, locationOptions, batchingOptions);
+ } else {
+ LOC_LOGE("%s:%d]: No flp 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 (gData.flpInterface != NULL) {
+ gData.flpInterface->stopBatching(this, id);
+ } else {
+ LOC_LOGE("%s:%d]: No flp interface available for Location API client %p ",
+ __func__, __LINE__, this);
+ }
+
+ pthread_mutex_unlock(&gDataMutex);
+}
+
+void
+LocationAPI::updateBatchingOptions(uint32_t id,
+ LocationOptions& locationOptions, BatchingOptions& batchOptions)
+{
+ pthread_mutex_lock(&gDataMutex);
+
+ if (gData.flpInterface != NULL) {
+ gData.flpInterface->updateBatchingOptions(this,
+ id,
+ locationOptions,
+ batchOptions);
+ } else {
+ LOC_LOGE("%s:%d]: No flp 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.flpInterface != NULL) {
+ gData.flpInterface->getBatchedLocations(this, id, count);
+ } else {
+ LOC_LOGE("%s:%d]: No flp 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("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::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/gps/location/LocationAPI.h b/gps/location/LocationAPI.h
new file mode 100644
index 0000000..530b1b0
--- /dev/null
+++ b/gps/location/LocationAPI.h
@@ -0,0 +1,974 @@
+/* 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.
+ */
+
+#ifndef LOCATION_H
+#define LOCATION_H
+
+#include <vector>
+#include <stdint.h>
+#include <functional>
+#include <list>
+
+#define GNSS_NI_REQUESTOR_MAX 256
+#define GNSS_NI_MESSAGE_ID_MAX 2048
+#define GNSS_SV_MAX 64
+#define GNSS_MEASUREMENTS_MAX 64
+#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)
+
+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
+} 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 enum {
+ LOCATION_RELIABILITY_NOT_SET = 0,
+ LOCATION_RELIABILITY_VERY_LOW,
+ LOCATION_RELIABILITY_LOW,
+ LOCATION_RELIABILITY_MEDIUM,
+ LOCATION_RELIABILITY_HIGH,
+} LocationReliability;
+
+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
+} 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)
+} LocationCapabilitiesBits;
+
+typedef enum {
+ LOCATION_TECHNOLOGY_TYPE_GNSS = 0,
+} LocationTechnologyType;
+
+// Configures how GPS is locked when GPS is disabled (through GnssDisable)
+typedef 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
+} 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),
+} 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,
+} 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),
+} GnssSvOptionsBits;
+
+typedef enum {
+ GNSS_ASSISTANCE_TYPE_SUPL = 0,
+ GNSS_ASSISTANCE_TYPE_C2K,
+} 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),
+} GnssMeasurementsAdrStateBits;
+
+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),
+} 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
+} 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),
+} GnssAidingDataSvTypeBits;
+
+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
+} GnssAidingData;
+
+typedef struct {
+ size_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;
+} Location;
+
+typedef struct {
+ size_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
+} LocationOptions;
+
+typedef struct {
+ size_t size;
+ BatchingMode batchingMode;
+} BatchingOptions;
+
+typedef struct {
+ size_t size;
+ BatchingStatus batchingStatus;
+} BatchingStatusInfo;
+
+typedef struct {
+ size_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 {
+ size_t size; // set to sizeof(GeofenceInfo)
+ double latitude; // in degrees
+ double longitude; // in degrees
+ double radius; // in meters
+} GeofenceInfo;
+
+typedef struct {
+ size_t size; // set to sizeof(GeofenceBreachNotification)
+ size_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 {
+ size_t size; // set to sizeof(GeofenceBreachNotification)
+ GeofenceStatusAvailable available; // GEOFENCE_STATUS_AVAILABILE_NO/_YES
+ LocationTechnologyType techType; // GNSS
+} GeofenceStatusNotification;
+
+typedef struct {
+ size_t size; // set to sizeof(GnssLocationInfo)
+ 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 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
+} GnssLocationInfoNotification;
+
+typedef struct {
+ size_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 {
+ size_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
+} GnssSv;
+
+typedef struct {
+ size_t size; // set to sizeof(GnssConfigSetAssistanceServer)
+ GnssAssistanceType type; // SUPL or C2K
+ const char* hostName; // null terminated string
+ uint32_t port; // port of server
+} GnssConfigSetAssistanceServer;
+
+typedef struct {
+ size_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;
+} GnssMeasurementsData;
+
+typedef struct {
+ size_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 {
+ size_t size; // set to sizeof(GnssSvNotification)
+ size_t count; // number of SVs in the GnssSv array
+ GnssSv gnssSvs[GNSS_SV_MAX]; // information on a number of SVs
+} GnssSvNotification;
+
+typedef struct {
+ size_t size; // set to sizeof(GnssNmeaNotification)
+ uint64_t timestamp; // timestamp
+ const char* nmea; // nmea text
+ size_t length; // length of the nmea text
+} GnssNmeaNotification;
+
+typedef struct {
+ size_t size; // set to sizeof(GnssMeasurementsNotification)
+ size_t count; // number of items in GnssMeasurements array
+ GnssMeasurementsData measurements[GNSS_MEASUREMENTS_MAX];
+ GnssMeasurementsClock clock; // clock
+} GnssMeasurementsNotification;
+
+typedef struct {
+ size_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
+} GnssConfig;
+
+typedef struct {
+ size_t size; // set to sizeof
+ bool mValid;
+ Location mLocation;
+ double verticalAccuracyMeters;
+ double speedAccuracyMetersPerSecond;
+ double bearingAccuracyDegrees;
+ timespec mUtcReported;
+} GnssDebugLocation;
+
+typedef struct {
+ size_t size; // set to sizeof
+ bool mValid;
+ int64_t timeEstimate;
+ float timeUncertaintyNs;
+ float frequencyUncertaintyNsPerSec;
+} GnssDebugTime;
+
+typedef struct {
+ size_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 {
+ size_t size; // set to sizeof
+ GnssDebugLocation mLocation;
+ GnssDebugTime mTime;
+ std::vector<GnssDebugSatelliteInfo> mSatelliteInfo;
+} GnssDebugReport;
+
+/* 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(
+ size_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(
+ size_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;
+
+/* 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 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;
+
+typedef struct {
+ size_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
+ gnssMeasurementsCallback gnssMeasurementsCb; // optional
+ batchingStatusCallback batchingStatusCb; // optional
+} LocationCallbacks;
+
+class LocationAPI
+{
+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 LocationAPI object is
+ no longer needed. LocationAPI* returned from createInstance will no longer valid
+ after destroy is called */
+ void destroy();
+
+ /* updates/changes the callbacks that will be called.
+ mandatory callbacks must be present for callbacks to be successfully updated
+ no return value */
+ void updateCallbacks(LocationCallbacks&);
+
+ /* ================================== 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 LocationOptions parameter is invalid */
+ uint32_t startTracking(LocationOptions&); // returns session id
+
+ /* 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 */
+ void stopTracking(uint32_t id);
+
+ /* updateTrackingOptions 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 */
+ void updateTrackingOptions(uint32_t id, LocationOptions&);
+
+ /* ================================== 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 */
+ uint32_t startBatching(LocationOptions&, BatchingOptions&); // returns session id
+
+ /* 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 */
+ void stopBatching(uint32_t id);
+
+ /* updateBatchingOptions 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 */
+ void updateBatchingOptions(uint32_t id, LocationOptions&, BatchingOptions&);
+
+ /* 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 */
+ void getBatchedLocations(uint32_t id, size_t count);
+
+ /* ================================== 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 */
+ uint32_t* addGeofences(size_t count, GeofenceOption*, GeofenceInfo*); // returns id array
+
+ /* 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 */
+ void removeGeofences(size_t count, uint32_t* ids);
+
+ /* 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 */
+ void modifyGeofences(size_t count, uint32_t* ids, GeofenceOption* options);
+
+ /* 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 */
+ void pauseGeofences(size_t count, uint32_t* ids);
+
+ /* 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 */
+ void resumeGeofences(size_t count, uint32_t* ids);
+
+ /* ================================== 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 */
+ void gnssNiResponse(uint32_t id, GnssNiResponse response);
+};
+
+typedef struct {
+ size_t size; // set to sizeof(LocationControlCallbacks)
+ responseCallback responseCb; // mandatory
+ collectiveResponseCallback collectiveResponseCb; // mandatory
+} LocationControlCallbacks;
+
+class LocationControlAPI
+{
+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 */
+ uint32_t* gnssUpdateConfig(GnssConfig config);
+
+ /* 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 */
+ uint32_t gnssDeleteAidingData(GnssAidingData& data);
+};
+
+#endif /* LOCATION_H */
diff --git a/gps/location/LocationAPIClientBase.cpp b/gps/location/LocationAPIClientBase.cpp
new file mode 100644
index 0000000..50b4b83
--- /dev/null
+++ b/gps/location/LocationAPIClientBase.cpp
@@ -0,0 +1,911 @@
+/* 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_NDDEBUG 0
+#define LOG_TAG "LocSvc_APIClientBase"
+
+#include <platform_lib_log_util.h>
+#include <inttypes.h>
+#include <loc_cfg.h>
+#include "LocationAPIClientBase.h"
+
+#define FLP_CONF_FILE "/etc/flp.conf"
+#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(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(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;
+ if (memcmp(&mConfig, &config, sizeof(GnssConfig)) == 0) {
+ LOC_LOGV("%s:%d] GnssConfig is identical to previous call", __FUNCTION__, __LINE__);
+ retVal = LOCATION_ERROR_SUCCESS;
+ return retVal;
+ }
+
+ pthread_mutex_lock(&mMutex);
+ if (mLocationControlAPI) {
+
+ memcpy(&mConfig, &config, sizeof(GnssConfig));
+
+ uint32_t session = 0;
+ uint32_t* idArray = mLocationControlAPI->gnssUpdateConfig(config);
+ LOC_LOGV("%s:%d] gnssUpdateConfig return array: %p", __FUNCTION__, __LINE__, idArray);
+ if (idArray != nullptr) {
+ if (mRequestQueues[CTRL_REQUEST_CONFIG].getSession() != CONFIG_SESSION_ID) {
+ mRequestQueues[CTRL_REQUEST_CONFIG].reset(CONFIG_SESSION_ID);
+ }
+ mRequestQueues[CTRL_REQUEST_CONFIG].push(new GnssUpdateConfigRequest(*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 = nullptr;
+ pthread_mutex_lock(&mMutex);
+ if (mRequestQueues[CTRL_REQUEST_CONFIG].getSession() == CONFIG_SESSION_ID) {
+ request = mRequestQueues[CTRL_REQUEST_CONFIG].pop();
+ }
+ pthread_mutex_unlock(&mMutex);
+ if (request) {
+ request->onCollectiveResponse(count, errors, ids);
+ delete request;
+ }
+}
+
+LocationAPIRequest* LocationAPIControlClient::getRequestBySession(uint32_t session)
+{
+ pthread_mutex_lock(&mMutex);
+ LocationAPIRequest* request = nullptr;
+ for (int i = 0; i < CTRL_REQUEST_MAX; i++) {
+ if (i != CTRL_REQUEST_CONFIG &&
+ mRequestQueues[i].getSession() == session) {
+ request = mRequestQueues[i].pop();
+ break;
+ }
+ }
+ 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(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(0);
+ }
+
+ pthread_mutex_unlock(&mMutex);
+
+ pthread_mutex_destroy(&mMutex);
+}
+
+uint32_t LocationAPIClientBase::locAPIStartTracking(LocationOptions& 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_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__, session);
+ }
+ }
+ pthread_mutex_unlock(&mMutex);
+}
+
+void LocationAPIClientBase::locAPIUpdateTrackingOptions(LocationOptions& 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(FLP_CONF_FILE, 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,
+ LocationOptions& locationOptions)
+{
+ 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(locationOptions);
+ 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;
+ }
+
+ batchingSession = mLocationAPI->startBatching(locationOptions, 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,
+ LocationOptions& 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;
+
+ // start batching
+ batchingSession = mLocationAPI->startBatching(options, batchOptions);
+ LOC_LOGI("%s:%d] start new session: %d",
+ __FUNCTION__, __LINE__, batchingSession);
+ mRequestQueues[REQUEST_SESSION].setSession(batchingSession);
+ } else {
+ mLocationAPI->updateBatchingOptions(batchingSession, options, 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);
+ uint32_t batchingSession = entity.batchingSession;
+ mRequestQueues[REQUEST_SESSION].push(new GetBatchedLocationsRequest(*this));
+ mLocationAPI->getBatchedLocations(batchingSession, count);
+ retVal = LOCATION_ERROR_SUCCESS;
+ } 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) {
+ size_t j = 0;
+ uint32_t id_cb;
+ LocationError err;
+ for (size_t i = 0; i < count; i++) {
+ sessions[j] = mGeofenceBiDict.getSession(ids[i]);
+ id_cb = ids[i];
+ if (sessions[j] > 0) {
+ mGeofenceBiDict.rmBySession(sessions[j]);
+ err = LOCATION_ERROR_SUCCESS;
+ onRemoveGeofencesCb(1, &err, &id_cb);
+ j++;
+ } else {
+ err = LOCATION_ERROR_ID_UNKNOWN;
+ onRemoveGeofencesCb(1, &err, &id_cb);
+ }
+ }
+
+ if (j > 0) {
+ mRequestQueues[REQUEST_GEOFENCE].push(new RemoveGeofencesRequest(*this));
+ mLocationAPI->removeGeofences(j, sessions);
+ }
+ } 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/gps/location/LocationAPIClientBase.h b/gps/location/LocationAPIClientBase.h
new file mode 100644
index 0000000..c6ea05c
--- /dev/null
+++ b/gps/location/LocationAPIClientBase.h
@@ -0,0 +1,545 @@
+/* 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.
+ */
+
+#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"
+
+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,
+ 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) {
+ }
+ virtual ~RequestQueue() {
+ reset(0);
+ }
+ void inline setSession(uint32_t session) { mSession = session; }
+ void reset(uint32_t session) {
+ LocationAPIRequest* request = nullptr;
+ while (!mQueue.empty()) {
+ request = mQueue.front();
+ mQueue.pop();
+ delete request;
+ }
+ mSession = session;
+ }
+ 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; }
+private:
+ uint32_t mSession;
+ std::queue<LocationAPIRequest*> mQueue;
+};
+
+class LocationAPIControlClient {
+public:
+ LocationAPIControlClient();
+ virtual ~LocationAPIControlClient();
+ LocationAPIControlClient(const LocationAPIControlClient&) = delete;
+ LocationAPIControlClient& operator=(const LocationAPIControlClient&) = delete;
+
+ LocationAPIRequest* getRequestBySession(uint32_t session);
+
+ // LocationControlAPI
+ uint32_t locAPIGnssDeleteAidingData(GnssAidingData& data);
+ uint32_t locAPIEnable(LocationTechnologyType techType);
+ void locAPIDisable();
+ uint32_t locAPIGnssUpdateConfig(GnssConfig config);
+
+ // 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*/) {}
+
+ 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;
+ };
+
+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(LocationOptions& options);
+ void locAPIStopTracking();
+ void locAPIUpdateTrackingOptions(LocationOptions& options);
+
+ int32_t locAPIGetBatchSize();
+ uint32_t locAPIStartSession(uint32_t id, uint32_t sessionMode,
+ LocationOptions& options);
+ uint32_t locAPIStopSession(uint32_t id);
+ uint32_t locAPIUpdateSessionOptions(uint32_t id, uint32_t sessionMode,
+ LocationOptions& options);
+ 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 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*/) {}
+
+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]);
+ }
+ mAPI.onAddGeofencesCb(count, errors, ids);
+ free(ids);
+ }
+ LocationAPIClientBase& mAPI;
+ };
+
+ class RemoveGeofencesRequest : public LocationAPIRequest {
+ public:
+ RemoveGeofencesRequest(LocationAPIClientBase& API) : mAPI(API) {}
+ inline void onCollectiveResponse(size_t count, LocationError* errors, uint32_t* sessions) {
+ // No need to handle collectiveResponse, cbs already notified
+ }
+ LocationAPIClientBase& mAPI;
+ };
+
+ 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/gps/location/Makefile.am b/gps/location/Makefile.am
new file mode 100644
index 0000000..d1d0131
--- /dev/null
+++ b/gps/location/Makefile.am
@@ -0,0 +1,40 @@
+AM_CFLAGS = \
+ $(LOCPLA_CFLAGS) \
+ $(GPSUTILS_CFLAGS) \
+ $(LOCHAL_CFLAGS) \
+ -I./ \
+ -I../utils \
+ -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++ -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 = -lpthread -shared -version-info 1:0:0
+liblocation_api_la_CPPFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS)
+endif
+
+liblocation_api_la_LIBADD = -lstdc++ $(LOCPLA_LIBS) $(GPSUTILS_LIBS) $(LOCHAL_LIBS)
+
+library_include_HEADERS = \
+ LocationAPI.h \
+ LocationAPIClientBase.h \
+ location_interface.h
+
+#Create and Install libraries
+lib_LTLIBRARIES = liblocation_api.la
+
+library_includedir = $(pkgincludedir)
+#pkgconfigdir = $(libdir)/pkgconfig
+#pkgconfig_DATA = location-api.pc
+#EXTRA_DIST = $(pkgconfig_DATA)
+
+
+
+
diff --git a/gps/location/location_interface.h b/gps/location/location_interface.h
new file mode 100644
index 0000000..33ec29e
--- /dev/null
+++ b/gps/location/location_interface.h
@@ -0,0 +1,94 @@
+/* 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.
+ */
+
+#ifndef LOCATION_INTERFACE_H
+#define LOCATION_INTERFACE_H
+
+#include <LocationAPI.h>
+#include <gps_extended_c.h>
+
+struct GnssInterface {
+ size_t size;
+ void (*initialize)(void);
+ void (*deinitialize)(void);
+ void (*addClient)(LocationAPI* client, const LocationCallbacks& callbacks);
+ void (*removeClient)(LocationAPI* client);
+ void (*requestCapabilities)(LocationAPI* client);
+ uint32_t (*startTracking)(LocationAPI* client, LocationOptions& options);
+ void (*updateTrackingOptions)(LocationAPI* client, uint32_t id, LocationOptions& options);
+ 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 (*gnssDeleteAidingData)(GnssAidingData& data);
+ 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, uint8_t type);
+};
+
+struct FlpInterface {
+ size_t size;
+ void (*initialize)(void);
+ void (*deinitialize)(void);
+ void (*addClient)(LocationAPI* client, const LocationCallbacks& callbacks);
+ void (*removeClient)(LocationAPI* client);
+ void (*requestCapabilities)(LocationAPI* client);
+ uint32_t (*startTracking)(LocationAPI* client, LocationOptions& options);
+ void (*updateTrackingOptions)(LocationAPI* client, uint32_t id, LocationOptions& options);
+ void (*stopTracking)(LocationAPI* client, uint32_t id);
+ uint32_t (*startBatching)(LocationAPI* client, LocationOptions&, BatchingOptions&);
+ void (*stopBatching)(LocationAPI* client, uint32_t id);
+ void (*updateBatchingOptions)(LocationAPI* client, uint32_t id, LocationOptions&,
+ BatchingOptions&);
+ void (*getBatchedLocations)(LocationAPI* client, uint32_t id, size_t count);
+ void (*getPowerStateChanges)(void* powerStateCb);
+};
+
+struct GeofenceInterface {
+ size_t size;
+ void (*initialize)(void);
+ void (*deinitialize)(void);
+ void (*addClient)(LocationAPI* client, const LocationCallbacks& callbacks);
+ void (*removeClient)(LocationAPI* client);
+ 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 */