summaryrefslogtreecommitdiff
path: root/location
diff options
context:
space:
mode:
authorDante Russo <drusso@codeaurora.org>2017-02-28 16:45:47 -0800
committerDante Russo <drusso@codeaurora.org>2017-02-28 16:47:50 -0800
commitc85c8ff673e4347cea911b353de120f639b39b83 (patch)
tree5fe203230801cf76dc1823b6d05a44ea94663883 /location
parent4bb940c0679ab23c9b8954bcb9ad8da5ede093cd (diff)
downloadgps-c85c8ff673e4347cea911b353de120f639b39b83.tar.gz
LocationAPI implementation
Implementation of LocationAPI into gps hal to be a common API that is called into by platform specific APIs. Change-Id: Ie5a7bd217d4ae2175ad49e6aca2fb6ecd4702f3b CRs-fixed: 1112712
Diffstat (limited to 'location')
-rw-r--r--location/Android.mk41
-rw-r--r--location/LocationAPI.cpp675
-rw-r--r--location/LocationAPI.h866
-rw-r--r--location/LocationAPIClientBase.cpp769
-rw-r--r--location/LocationAPIClientBase.h457
-rw-r--r--location/location_interface.h86
6 files changed, 2894 insertions, 0 deletions
diff --git a/location/Android.mk b/location/Android.mk
new file mode 100644
index 0000000..49a60d7
--- /dev/null
+++ b/location/Android.mk
@@ -0,0 +1,41 @@
+ifneq ($(BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE),)
+ifneq ($(BUILD_TINY_ANDROID),true)
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := liblocation_api
+LOCAL_MODULE_OWNER := qti
+
+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_C_INCLUDES:= \
+ $(TARGET_OUT_HEADERS)/gps.utils
+
+LOCAL_COPY_HEADERS_TO:= liblocation_api/
+LOCAL_COPY_HEADERS:= \
+ LocationAPI.h \
+ LocationAPIClientBase.h \
+ location_interface.h
+
+LOCAL_PRELINK_MODULE := false
+
+include $(BUILD_SHARED_LIBRARY)
+
+endif # not BUILD_TINY_ANDROID
+endif # BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE
diff --git a/location/LocationAPI.cpp b/location/LocationAPI.cpp
new file mode 100644
index 0000000..c800851
--- /dev/null
+++ b/location/LocationAPI.cpp
@@ -0,0 +1,675 @@
+/* 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 <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;
+ 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()) {
+ size_t gnssClientCount = 0;
+ size_t flpClientCount = 0;
+ size_t geofenceClientCount = 0;
+ for (auto it2=gData.clientData.begin(); it2 != gData.clientData.end(); ++it2) {
+ if (isGnssClient(it2->second)) {
+ gnssClientCount++;
+ }
+ if (isFlpClient(it2->second)) {
+ flpClientCount++;
+ }
+ if (isGeofenceClient(it2->second)) {
+ geofenceClientCount++;
+ }
+ }
+ if (isGnssClient(it->second) && NULL != gData.gnssInterface) {
+ gData.gnssInterface->removeClient(it->first);
+ if (1 == gnssClientCount && NULL == gData.controlAPI) {
+ gData.gnssInterface->deinitialize();
+ }
+ }
+ if (isFlpClient(it->second) && NULL != gData.flpInterface) {
+ gData.flpInterface->removeClient(it->first);
+ if (1 == flpClientCount) {
+ gData.flpInterface->deinitialize();
+ }
+ }
+ if (isGeofenceClient(it->second) && NULL != gData.geofenceInterface) {
+ gData.geofenceInterface->removeClient(it->first);
+ if (1 == geofenceClientCount) {
+ gData.geofenceInterface->deinitialize();
+ }
+ }
+ 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)
+{
+ uint32_t id = 0;
+ pthread_mutex_lock(&gDataMutex);
+
+ if (gData.flpInterface != NULL) {
+ id = gData.flpInterface->startBatching(this, locationOptions);
+ } 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)
+{
+ pthread_mutex_lock(&gDataMutex);
+
+ if (gData.flpInterface != NULL) {
+ gData.flpInterface->updateBatchingOptions(this,
+ id,
+ locationOptions);
+ } 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);
+
+ size_t gnssClientCount = 0;
+ for (auto it=gData.clientData.begin(); it != gData.clientData.end(); ++it) {
+ if (isGnssClient(it->second)) {
+ gnssClientCount++;
+ }
+ }
+ if (gData.gnssInterface != NULL && 0 == gnssClientCount) {
+ //@todo: we might want to call gData.gnssInterface.disable before deinitialize?
+ gData.gnssInterface->deinitialize();
+ }
+ 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/location/LocationAPI.h b/location/LocationAPI.h
new file mode 100644
index 0000000..cc15ddd
--- /dev/null
+++ b/location/LocationAPI.h
@@ -0,0 +1,866 @@
+/* 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 <stdint.h>
+#include <functional>
+
+#define GNSS_NI_REQUESTOR_MAX 256
+#define GNSS_NI_MESSAGE_ID_MAX 2048
+#define GNSS_SV_MAX 64
+#define GNSS_MEASUREMENTS_MAX 64
+
+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
+} 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_VER_ACCURACY_BIT = (1<<3), // valid vertical accuracy
+ GNSS_LOCATION_INFO_SPEED_ACCURACY_BIT = (1<<4), // valid speed accuracy
+ GNSS_LOCATION_INFO_BEARING_ACCURACY_BIT = (1<<5), // valid bearing accuracy
+ GNSS_LOCATION_INFO_HOR_RELIABILITY_BIT = (1<<6), // valid horizontal reliability
+ GNSS_LOCATION_INFO_VER_RELIABILITY_BIT = (1<<7), // valid vertical reliability
+ GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MAJOR_BIT = (1<<8), // valid elipsode semi major
+ GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MINOR_BIT = (1<<9), // valid elipsode semi minor
+ GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_AZIMUTH_BIT = (1<<10),// 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),
+} 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
+} 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
+} 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 = (1<<0),
+ GNSS_CONFIG_SUPL_MODE_MSA = (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 = (1<<0),
+ GNSS_NI_OPTIONS_VERIFICATION = (1<<1),
+ GNSS_NI_OPTIONS_PRIVACY_OVERRIDE = (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 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 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),
+} 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 = (1<<0), // ephemeris
+ GNSS_AIDING_DATA_SV_ALMANAC = (1<<1), // almanac
+ GNSS_AIDING_DATA_SV_HEALTH = (1<<2), // health
+ GNSS_AIDING_DATA_SV_DIRECTION = (1<<3), // direction
+ GNSS_AIDING_DATA_SV_STEER = (1<<4), // steer
+ GNSS_AIDING_DATA_SV_ALMANAC_CORR = (1<<5), // almanac correction
+ GNSS_AIDING_DATA_SV_BLACKLIST = (1<<6), // blacklist SVs
+ GNSS_AIDING_DATA_SV_SA_DATA = (1<<7), // sensitivity assistance data
+ GNSS_AIDING_DATA_SV_NO_EXIST = (1<<8), // SV does not exist
+ GNSS_AIDING_DATA_SV_IONOSPHERE = (1<<9), // ionosphere correction
+ GNSS_AIDING_DATA_SV_TIME = (1<<10),// reset satellite time
+} GnssAidingDataSvBits;
+
+typedef uint32_t GnssAidingDataSvTypeMask;
+typedef enum {
+ GNSS_AIDING_DATA_SV_TYPE_GPS = (1<<0),
+ GNSS_AIDING_DATA_SV_TYPE_GLONASS = (1<<1),
+ GNSS_AIDING_DATA_SV_TYPE_QZSS = (1<<2),
+ GNSS_AIDING_DATA_SV_TYPE_BEIDOU = (1<<3),
+ GNSS_AIDING_DATA_SV_TYPE_GALILEO = (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 = (1<<0), // position estimate
+ GNSS_AIDING_DATA_COMMON_TIME = (1<<1), // reset all clock values
+ GNSS_AIDING_DATA_COMMON_UTC = (1<<2), // UTC estimate
+ GNSS_AIDING_DATA_COMMON_RTI = (1<<3), // RTI
+ GNSS_AIDING_DATA_COMMON_FREQ_BIAS_EST = (1<<4), // frequency bias estimate
+ GNSS_AIDING_DATA_COMMON_CELLDB = (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
+ 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; // 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
+ float verAccuracy; // vertical accuracy in meters
+ float speedAccuracy; // speed accuracy in meters/second
+ float bearingAccuracy; // bearing accuracy in degrees (0 to 359.999)
+ 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;
+} 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;
+
+/* 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
+)> batchingCallback;
+
+/* 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
+} 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&); // 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&);
+
+ /* 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/location/LocationAPIClientBase.cpp b/location/LocationAPIClientBase.cpp
new file mode 100644
index 0000000..3413d3e
--- /dev/null
+++ b/location/LocationAPIClientBase.cpp
@@ -0,0 +1,769 @@
+/* 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 <log_util.h>
+#include <loc_cfg.h>
+#include "LocationAPIClientBase.h"
+
+#define FLP_CONF_FILE "/etc/flp.conf"
+
+LocationAPIClientBase::LocationAPIClientBase() :
+ mTrackingCallback(nullptr),
+ mBatchingCallback(nullptr),
+ mGeofenceBreachCallback(nullptr),
+ mLocationAPI(nullptr),
+ mLocationControlAPI(nullptr),
+ mBatchSize(-1)
+{
+
+ // 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] = nullptr;
+ }
+
+ memset(&mConfig, 0, sizeof(GnssConfig));
+}
+
+void LocationAPIClientBase::locAPISetCallbacks(LocationCallbacks& locationCallbacks)
+{
+ 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 (mLocationAPI == nullptr ) {
+ mLocationAPI = LocationAPI::createInstance(locationCallbacks);
+ } else {
+ mLocationAPI->updateCallbacks(locationCallbacks);
+ }
+
+ if (mLocationControlAPI == nullptr) {
+ 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);
+ }
+}
+
+LocationAPIClientBase::~LocationAPIClientBase()
+{
+ if (mLocationAPI) {
+ mLocationAPI->destroy();
+ mLocationAPI = nullptr;
+ }
+ if (mLocationControlAPI) {
+ mLocationControlAPI->destroy();
+ mLocationControlAPI = nullptr;
+ }
+
+ pthread_mutex_lock(&mMutex);
+ for (int i = 0; i < REQUEST_MAX; i++) {
+ if (mRequestQueues[i]) {
+ delete mRequestQueues[i];
+ mRequestQueues[i] = nullptr;
+ }
+ }
+ pthread_mutex_unlock(&mMutex);
+
+ pthread_mutex_destroy(&mMutex);
+}
+
+uint32_t LocationAPIClientBase::locAPIStartTracking(LocationOptions& options)
+{
+ uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
+ if (mLocationAPI) {
+ pthread_mutex_lock(&mMutex);
+ RequestQueue* requests = mRequestQueues[REQUEST_TRACKING];
+ if (requests) {
+ delete requests;
+ }
+ 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]
+ requests = new RequestQueue(session);
+ requests->push(new StartTrackingRequest(*this));
+ mRequestQueues[REQUEST_TRACKING] = requests;
+ pthread_mutex_unlock(&mMutex);
+
+ retVal = LOCATION_ERROR_SUCCESS;
+ }
+
+ return retVal;
+}
+
+void LocationAPIClientBase::locAPIStopTracking()
+{
+ if (mLocationAPI) {
+ pthread_mutex_lock(&mMutex);
+ uint32_t session = -1;
+ RequestQueue* requests = mRequestQueues[REQUEST_TRACKING];
+ if (requests) {
+ session = requests->getSession();
+ requests->push(new StopTrackingRequest(*this));
+ mLocationAPI->stopTracking(session);
+ }
+ pthread_mutex_unlock(&mMutex);
+ }
+}
+
+void LocationAPIClientBase::locAPIUpdateTrackingOptions(LocationOptions& options)
+{
+ if (mLocationAPI) {
+ pthread_mutex_lock(&mMutex);
+ uint32_t session = -1;
+ RequestQueue* requests = mRequestQueues[REQUEST_TRACKING];
+ if (requests) {
+ session = requests->getSession();
+ requests->push(new UpdateTrackingOptionsRequest(*this));
+ mLocationAPI->updateTrackingOptions(session, options);
+ }
+ 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& options)
+{
+ uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
+ if (mLocationAPI) {
+ pthread_mutex_lock(&mMutex);
+
+ if (mSessionMap.find(id) != mSessionMap.end()) {
+ 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) {
+ RequestQueue* requests = mRequestQueues[REQUEST_TRACKING];
+ if (requests) {
+ delete requests;
+ }
+ trackingSession = mLocationAPI->startTracking(options);
+ LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, trackingSession);
+ requests = new RequestQueue(trackingSession);
+ requests->push(new StartTrackingRequest(*this));
+ mRequestQueues[REQUEST_TRACKING] = requests;
+ } else if (sessionMode == SESSION_MODE_ON_FULL) {
+ RequestQueue* requests = mRequestQueues[REQUEST_BATCHING];
+ if (requests) {
+ delete requests;
+ }
+ batchingSession = mLocationAPI->startBatching(options);
+ LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, batchingSession);
+ requests = new RequestQueue(batchingSession);
+ requests->push(new StartBatchingRequest(*this));
+ mRequestQueues[REQUEST_BATCHING] = requests;
+ }
+
+ SessionEntity entity;
+ entity.id = id;
+ entity.trackingSession = trackingSession;
+ entity.batchingSession = batchingSession;
+ entity.sessionMode = sessionMode;
+ mSessionMap[id] = 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;
+ if (mLocationAPI) {
+ pthread_mutex_lock(&mMutex);
+
+ if (mSessionMap.find(id) != mSessionMap.end()) {
+ SessionEntity entity = mSessionMap[id];
+
+ uint32_t trackingSession = entity.trackingSession;
+ uint32_t batchingSession = entity.batchingSession;
+ uint32_t sMode = entity.sessionMode;
+
+ mSessionMap.erase(id);
+
+ if (sMode == SESSION_MODE_ON_FIX) {
+ RequestQueue* requests = mRequestQueues[REQUEST_TRACKING];
+ if (requests) {
+ requests->push(new StopTrackingRequest(*this));
+ mLocationAPI->stopTracking(trackingSession);
+ }
+ } else if (sMode == SESSION_MODE_ON_FULL) {
+ RequestQueue* requests = mRequestQueues[REQUEST_BATCHING];
+ if (requests) {
+ requests->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;
+ if (mLocationAPI) {
+ pthread_mutex_lock(&mMutex);
+
+ if (mSessionMap.find(id) != mSessionMap.end()) {
+ SessionEntity& entity = mSessionMap[id];
+
+ uint32_t trackingSession = entity.trackingSession;
+ uint32_t batchingSession = entity.batchingSession;
+ uint32_t sMode = entity.sessionMode;
+
+ if (sessionMode == SESSION_MODE_ON_FIX) {
+ if (sMode == SESSION_MODE_ON_FIX) {
+ RequestQueue* requests = mRequestQueues[REQUEST_TRACKING];
+ if (requests) {
+ requests->push(new UpdateTrackingOptionsRequest(*this));
+ mLocationAPI->updateTrackingOptions(trackingSession, options);
+ }
+ } else if (sMode == SESSION_MODE_ON_FULL) {
+ // stop batching
+ {
+ RequestQueue* requests = mRequestQueues[REQUEST_BATCHING];
+ if (requests) {
+ requests->push(new StopBatchingRequest(*this));
+ mLocationAPI->stopBatching(batchingSession);
+ batchingSession = 0;
+ }
+ }
+ // start tracking
+ {
+ RequestQueue* requests = mRequestQueues[REQUEST_TRACKING];
+ if (requests) {
+ delete requests;
+ }
+ trackingSession = mLocationAPI->startTracking(options);
+ LOC_LOGI("%s:%d] start new session: %d",
+ __FUNCTION__, __LINE__, trackingSession);
+ requests = new RequestQueue(trackingSession);
+ requests->push(new StartTrackingRequest(*this));
+ mRequestQueues[REQUEST_TRACKING] = requests;
+ }
+ }
+ } else if (sessionMode == SESSION_MODE_ON_FULL) {
+ if (sMode == SESSION_MODE_ON_FIX) {
+ // stop tracking
+ {
+ RequestQueue* requests = mRequestQueues[REQUEST_TRACKING];
+ if (requests) {
+ requests->push(new StopTrackingRequest(*this));
+ mLocationAPI->stopTracking(trackingSession);
+ trackingSession = 0;
+ }
+ }
+ // start batching
+ {
+ RequestQueue* requests = mRequestQueues[REQUEST_BATCHING];
+ if (requests) {
+ delete requests;
+ }
+ batchingSession = mLocationAPI->startBatching(options);
+ LOC_LOGI("%s:%d] start new session: %d",
+ __FUNCTION__, __LINE__, batchingSession);
+ requests = new RequestQueue(batchingSession);
+ requests->push(new StartBatchingRequest(*this));
+ mRequestQueues[REQUEST_BATCHING] = requests;
+ }
+ } else if (sMode == SESSION_MODE_ON_FULL) {
+ RequestQueue* requests = mRequestQueues[REQUEST_BATCHING];
+ requests = mRequestQueues[REQUEST_BATCHING];
+ if (requests) {
+ requests->push(new UpdateBatchingOptionsRequest(*this));
+ mLocationAPI->updateBatchingOptions(batchingSession, options);
+ }
+ }
+ }
+
+ entity.trackingSession = trackingSession;
+ entity.batchingSession = batchingSession;
+ entity.sessionMode = sessionMode;
+
+ 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;
+}
+
+void LocationAPIClientBase::locAPIGetBatchedLocations(size_t count)
+{
+ if (mLocationAPI) {
+ pthread_mutex_lock(&mMutex);
+ uint32_t session = -1;
+ RequestQueue* requests = mRequestQueues[REQUEST_BATCHING];
+ if (requests) {
+ session = requests->getSession();
+ requests->push(new GetBatchedLocationsRequest(*this));
+ mLocationAPI->getBatchedLocations(session, count);
+ }
+ pthread_mutex_unlock(&mMutex);
+ }
+}
+
+uint32_t LocationAPIClientBase::locAPIAddGeofences(
+ size_t count, uint32_t* ids, GeofenceOption* options, GeofenceInfo* data)
+{
+ uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
+ if (mLocationAPI) {
+ pthread_mutex_lock(&mMutex);
+ RequestQueue* requests = mRequestQueues[REQUEST_GEOFENCE];
+ if (requests) {
+ delete requests;
+ }
+ uint32_t* sessions = mLocationAPI->addGeofences(count, options, data);
+ LOC_LOGI("%s:%d] start new sessions: %p", __FUNCTION__, __LINE__, sessions);
+ requests = new RequestQueue(-1);
+ requests->push(new AddGeofencesRequest(*this));
+ mRequestQueues[REQUEST_GEOFENCE] = requests;
+
+ for (size_t i = 0; i < count; i++) {
+ mGeofenceBiDict.set(ids[i], sessions[i], options[i].breachTypeMask);
+ }
+ pthread_mutex_unlock(&mMutex);
+
+ retVal = LOCATION_ERROR_SUCCESS;
+ }
+
+ return retVal;
+}
+
+void LocationAPIClientBase::locAPIRemoveGeofences(size_t count, uint32_t* ids)
+{
+ if (mLocationAPI) {
+ uint32_t* sessions = (uint32_t*)malloc(sizeof(uint32_t) * count);
+
+ pthread_mutex_lock(&mMutex);
+ RequestQueue* requests = mRequestQueues[REQUEST_GEOFENCE];
+ if (requests) {
+ for (size_t i = 0; i < count; i++) {
+ sessions[i] = mGeofenceBiDict.getSession(ids[i]);
+ }
+ requests->push(new RemoveGeofencesRequest(*this));
+ mLocationAPI->removeGeofences(count, sessions);
+ }
+ pthread_mutex_unlock(&mMutex);
+
+ free(sessions);
+ }
+}
+
+void LocationAPIClientBase::locAPIModifyGeofences(
+ size_t count, uint32_t* ids, GeofenceOption* options)
+{
+ if (mLocationAPI) {
+ uint32_t* sessions = (uint32_t*)malloc(sizeof(uint32_t) * count);
+
+ pthread_mutex_lock(&mMutex);
+ RequestQueue* requests = mRequestQueues[REQUEST_GEOFENCE];
+ if (requests) {
+ for (size_t i = 0; i < count; i++) {
+ sessions[i] = mGeofenceBiDict.getSession(ids[i]);
+ mGeofenceBiDict.set(ids[i], sessions[i], options[i].breachTypeMask);
+ }
+ requests->push(new ModifyGeofencesRequest(*this));
+ mLocationAPI->modifyGeofences(count, sessions, options);
+ }
+ pthread_mutex_unlock(&mMutex);
+
+ free(sessions);
+ }
+}
+
+void LocationAPIClientBase::locAPIPauseGeofences(size_t count, uint32_t* ids)
+{
+ if (mLocationAPI) {
+ uint32_t* sessions = (uint32_t*)malloc(sizeof(uint32_t) * count);
+
+ pthread_mutex_lock(&mMutex);
+ RequestQueue* requests = mRequestQueues[REQUEST_GEOFENCE];
+ if (requests) {
+ for (size_t i = 0; i < count; i++) {
+ sessions[i] = mGeofenceBiDict.getSession(ids[i]);
+ }
+ requests->push(new PauseGeofencesRequest(*this));
+ mLocationAPI->pauseGeofences(count, sessions);
+ }
+ pthread_mutex_unlock(&mMutex);
+
+ free(sessions);
+ }
+}
+
+void LocationAPIClientBase::locAPIResumeGeofences(
+ size_t count, uint32_t* ids, GeofenceBreachTypeMask* mask)
+{
+ if (mLocationAPI) {
+ uint32_t* sessions = (uint32_t*)malloc(sizeof(uint32_t) * count);
+
+ pthread_mutex_lock(&mMutex);
+ RequestQueue* requests = mRequestQueues[REQUEST_GEOFENCE];
+ if (requests) {
+ for (size_t i = 0; i < count; i++) {
+ sessions[i] = mGeofenceBiDict.getSession(ids[i]);
+ if (mask) {
+ mGeofenceBiDict.set(ids[i], sessions[i], mask[i]);
+ }
+ }
+ requests->push(new ResumeGeofencesRequest(*this));
+ mLocationAPI->resumeGeofences(count, sessions);
+ }
+ pthread_mutex_unlock(&mMutex);
+
+ free(sessions);
+ }
+}
+
+void LocationAPIClientBase::locAPIRemoveAllGeofences()
+{
+ if (mLocationAPI) {
+ std::vector<uint32_t> sessionsVec = mGeofenceBiDict.getAllSessions();
+ size_t count = sessionsVec.size();
+ uint32_t* sessions = (uint32_t*)malloc(sizeof(uint32_t) * count);
+
+ pthread_mutex_lock(&mMutex);
+ RequestQueue* requests = mRequestQueues[REQUEST_GEOFENCE];
+ if (requests) {
+ for (size_t i = 0; i < count; i++) {
+ sessions[i] = sessionsVec[i];
+ }
+ requests->push(new RemoveGeofencesRequest(*this));
+ mLocationAPI->removeGeofences(count, sessions);
+ }
+ pthread_mutex_unlock(&mMutex);
+
+ free(sessions);
+ }
+}
+
+void LocationAPIClientBase::locAPIGnssNiResponse(uint32_t id, GnssNiResponse response)
+{
+ uint32_t session = 0;
+ if (mLocationAPI) {
+ pthread_mutex_lock(&mMutex);
+ RequestQueue* requests = mRequestQueues[REQUEST_NIRESPONSE];
+ if (requests) {
+ delete requests;
+ }
+ uint32_t session = id;
+ mLocationAPI->gnssNiResponse(id, response);
+ LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, session);
+ requests = new RequestQueue(session);
+ requests->push(new GnssNiResponseRequest(*this));
+ mRequestQueues[REQUEST_NIRESPONSE] = requests;
+ pthread_mutex_unlock(&mMutex);
+ }
+}
+
+uint32_t LocationAPIClientBase::locAPIGnssDeleteAidingData(GnssAidingData& data)
+{
+ uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
+ if (mLocationControlAPI) {
+ pthread_mutex_lock(&mMutex);
+ RequestQueue* requests = mRequestQueues[REQUEST_DELETEAIDINGDATA];
+ if (requests) {
+ delete requests;
+ }
+ uint32_t session = mLocationControlAPI->gnssDeleteAidingData(data);
+ LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, session);
+ requests = new RequestQueue(session);
+ requests->push(new GnssDeleteAidingDataRequest(*this));
+ mRequestQueues[REQUEST_DELETEAIDINGDATA] = requests;
+ pthread_mutex_unlock(&mMutex);
+
+ retVal = LOCATION_ERROR_SUCCESS;
+ }
+
+ return retVal;
+}
+
+uint32_t LocationAPIClientBase::locAPIEnable(LocationTechnologyType techType)
+{
+ uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
+ if (mLocationControlAPI) {
+ pthread_mutex_lock(&mMutex);
+ RequestQueue* requests = mRequestQueues[REQUEST_CONTROL];
+ if (requests) {
+ delete requests;
+ }
+ uint32_t session = mLocationControlAPI->enable(techType);
+ LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, session);
+ requests = new RequestQueue(session);
+ requests->push(new EnableRequest(*this));
+ mRequestQueues[REQUEST_CONTROL] = requests;
+ pthread_mutex_unlock(&mMutex);
+
+ retVal = LOCATION_ERROR_SUCCESS;
+ }
+
+ return retVal;
+}
+
+void LocationAPIClientBase::locAPIDisable()
+{
+ if (mLocationControlAPI) {
+ pthread_mutex_lock(&mMutex);
+ uint32_t session = -1;
+ RequestQueue* requests = mRequestQueues[REQUEST_CONTROL];
+ if (requests) {
+ session = requests->getSession();
+ requests->push(new DisableRequest(*this));
+ mLocationControlAPI->disable(session);
+ }
+ pthread_mutex_unlock(&mMutex);
+ }
+}
+
+uint32_t LocationAPIClientBase::locAPIGnssUpdateConfig(GnssConfig config)
+{
+ uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
+ if (memcmp(&mConfig, &config, sizeof(GnssConfig)) == 0) {
+ LOC_LOGE("%s:%d] GnssConfig is identical to previous call", __FUNCTION__, __LINE__);
+ return retVal;
+ }
+
+ if (mLocationControlAPI) {
+ pthread_mutex_lock(&mMutex);
+
+ memcpy(&mConfig, &config, sizeof(GnssConfig));
+
+ uint32_t session = -1;
+ RequestQueue* requests = mRequestQueues[REQUEST_CONTROL];
+ if (requests) {
+ session = requests->getSession();
+ requests->push(new GnssUpdateConfigRequest(*this));
+ uint32_t* idArray = mLocationControlAPI->gnssUpdateConfig(config);
+ LOC_LOGV("%s:%d] gnssUpdateConfig return array: %p", __FUNCTION__, __LINE__, idArray);
+ }
+ pthread_mutex_unlock(&mMutex);
+
+ retVal = LOCATION_ERROR_SUCCESS;
+ }
+ return retVal;
+}
+
+void LocationAPIClientBase::beforeGeofenceBreachCb(
+ GeofenceBreachNotification geofenceBreachNotification)
+{
+ if (mGeofenceBreachCallback == nullptr)
+ return;
+ uint32_t* ids = (uint32_t*)malloc(sizeof(uint32_t) * geofenceBreachNotification.count);
+ uint32_t* backup = geofenceBreachNotification.ids;
+ size_t n = geofenceBreachNotification.count;
+
+ size_t count = 0;
+ for (size_t i = 0; i < n; i++) {
+ uint32_t id = mGeofenceBiDict.getId(geofenceBreachNotification.ids[i]);
+ GeofenceBreachTypeMask type = mGeofenceBiDict.getType(geofenceBreachNotification.ids[i]);
+ 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;
+ mGeofenceBreachCallback(geofenceBreachNotification);
+
+ // restore ids
+ geofenceBreachNotification.ids = backup;
+ geofenceBreachNotification.count = n;
+ free(ids);
+}
+
+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] error: %d id: %d", __FUNCTION__, __LINE__, error, id);
+ }
+ LocationAPIRequest* request = getRequestBySession(id);
+ if (request) {
+ request->onResponse(error);
+ 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] error: %d id: %d", __FUNCTION__, __LINE__, errors[i], ids[i]);
+ }
+ }
+ LocationAPIRequest* request = nullptr;
+ if (count > 0 && ids)
+ request = getRequestBySession(ids[0]);
+ if (!request)
+ request = getGeofencesRequest();
+ if (request) {
+ request->onCollectiveResponse(count, errors, ids);
+ delete request;
+ }
+}
+
+void LocationAPIClientBase::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] error: %d id: %d", __FUNCTION__, __LINE__, error, id);
+ }
+ LocationAPIRequest* request = getRequestBySession(id);
+ if (request) {
+ request->onResponse(error);
+ delete request;
+ }
+}
+
+void LocationAPIClientBase::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] error: %d id: %d", __FUNCTION__, __LINE__, errors[i], ids[i]);
+ }
+ }
+ LocationAPIRequest* request = nullptr;
+ if (count > 0 && ids)
+ request = getRequestBySession(ids[0]);
+ if (request) {
+ request->onCollectiveResponse(count, errors, ids);
+ delete request;
+ }
+}
+
+LocationAPIClientBase::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 &&
+ mRequestQueues[i] &&
+ mRequestQueues[i]->getSession() == session) {
+ request = mRequestQueues[i]->pop();
+ break;
+ }
+ }
+ pthread_mutex_unlock(&mMutex);
+ return request;
+}
+
+LocationAPIClientBase::LocationAPIRequest*
+LocationAPIClientBase::getGeofencesRequest()
+{
+ pthread_mutex_lock(&mMutex);
+ LocationAPIRequest* request = nullptr;
+ if (mRequestQueues[REQUEST_GEOFENCE]) {
+ request = mRequestQueues[REQUEST_GEOFENCE]->pop();
+ }
+ pthread_mutex_unlock(&mMutex);
+ return request;
+}
diff --git a/location/LocationAPIClientBase.h b/location/LocationAPIClientBase.h
new file mode 100644
index 0000000..8bbaa3d
--- /dev/null
+++ b/location/LocationAPIClientBase.h
@@ -0,0 +1,457 @@
+/* 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,
+};
+
+enum REQUEST_TYPE {
+ REQUEST_TRACKING = 0,
+ REQUEST_BATCHING,
+ REQUEST_GEOFENCE,
+ REQUEST_NIRESPONSE,
+ REQUEST_DELETEAIDINGDATA,
+ REQUEST_CONTROL,
+ REQUEST_MAX,
+};
+
+class LocationAPIClientBase
+{
+public:
+ LocationAPIClientBase();
+ virtual ~LocationAPIClientBase();
+ LocationAPIClientBase(const LocationAPIClientBase&) = delete;
+ LocationAPIClientBase& operator=(const LocationAPIClientBase&) = delete;
+
+ void locAPISetCallbacks(LocationCallbacks& locationCallbacks);
+
+ // 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);
+ void locAPIGetBatchedLocations(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);
+ uint32_t locAPIGnssDeleteAidingData(GnssAidingData& data);
+
+ uint32_t locAPIEnable(LocationTechnologyType techType);
+ void locAPIDisable();
+ uint32_t locAPIGnssUpdateConfig(GnssConfig config);
+
+ // callbacks
+ void onResponseCb(LocationError error, uint32_t id);
+ void onCollectiveResponseCb(size_t count, LocationError* errors, uint32_t* ids);
+
+ void onCtrlResponseCb(LocationError error, uint32_t id);
+ void onCtrlCollectiveResponseCb(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*/) {}
+ inline virtual void onStartBatchingCb(LocationError /*error*/) {}
+ inline virtual void onStopBatchingCb(LocationError /*error*/) {}
+ inline virtual void onUpdateBatchingOptionsCb(LocationError /*error*/) {}
+ inline virtual void onGetBatchedLocationsCb(LocationError /*error*/) {}
+
+ inline virtual void onGeofenceBreachCb(
+ GeofenceBreachNotification /*geofenceBreachNotification*/) {}
+ inline virtual void onGeofenceStatusCb(
+ GeofenceStatusNotification /*geofenceStatusNotification*/) {}
+ inline virtual void onAddGeofencesCb(
+ size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {}
+ inline virtual void onRemoveGeofencesCb(
+ size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {}
+ inline virtual void onModifyGeofencesCb(
+ size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {}
+ inline virtual void onPauseGeofencesCb(
+ size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {}
+ inline virtual void onResumeGeofencesCb(
+ size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {}
+
+ inline virtual void onGnssNiCb(uint32_t /*id*/, GnssNiNotification /*gnssNiNotification*/) {}
+ inline virtual void onGnssNiResponseCb(LocationError /*error*/) {}
+ inline virtual void 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*/) {}
+
+private:
+ // private inner classes
+ typedef struct {
+ uint32_t id;
+ uint32_t trackingSession;
+ uint32_t batchingSession;
+ uint32_t sessionMode;
+ } SessionEntity;
+
+ class BiDict {
+ public:
+ BiDict() {
+ pthread_mutex_init(&mBiDictMutex, nullptr);
+ }
+ ~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;
+ }
+ void set(uint32_t id, uint32_t session, uint32_t type) {
+ pthread_mutex_lock(&mBiDictMutex);
+ mForwardMap[id] = session;
+ mBackwardMap[session] = id;
+ mTypeMap[session] = type;
+ pthread_mutex_unlock(&mBiDictMutex);
+ }
+ void clear() {
+ pthread_mutex_lock(&mBiDictMutex);
+ mForwardMap.clear();
+ mBackwardMap.clear();
+ mTypeMap.clear();
+ pthread_mutex_unlock(&mBiDictMutex);
+ }
+ void rmById(uint32_t id) {
+ pthread_mutex_lock(&mBiDictMutex);
+ mBackwardMap.erase(mForwardMap[id]);
+ mTypeMap.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);
+ mTypeMap.erase(session);
+ pthread_mutex_unlock(&mBiDictMutex);
+ }
+ uint32_t getId(uint32_t session) {
+ pthread_mutex_lock(&mBiDictMutex);
+ uint32_t ret = mBackwardMap[session];
+ pthread_mutex_unlock(&mBiDictMutex);
+ return ret;
+ }
+ uint32_t getSession(uint32_t id) {
+ pthread_mutex_lock(&mBiDictMutex);
+ uint32_t ret = mForwardMap[id];
+ pthread_mutex_unlock(&mBiDictMutex);
+ return ret;
+ }
+ uint32_t getType(uint32_t session) {
+ pthread_mutex_lock(&mBiDictMutex);
+ uint32_t ret = mTypeMap[session];
+ 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;
+ // mTypeMap mapping session->type
+ std::map<uint32_t, uint32_t> mTypeMap;
+ };
+
+ class LocationAPIRequest {
+ public:
+ LocationAPIRequest(LocationAPIClientBase& API) : mAPI(API) {}
+ virtual ~LocationAPIRequest() {}
+ virtual void onResponse(LocationError /*error*/) {};
+ virtual void onCollectiveResponse(
+ size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {};
+ LocationAPIClientBase& mAPI;
+ };
+
+ class StartTrackingRequest : public LocationAPIRequest {
+ public:
+ StartTrackingRequest(LocationAPIClientBase& API) : LocationAPIRequest(API) {}
+ inline void onResponse(LocationError error) {
+ mAPI.onStartTrackingCb(error);
+ }
+ };
+
+ class StopTrackingRequest : public LocationAPIRequest {
+ public:
+ StopTrackingRequest(LocationAPIClientBase& API) : LocationAPIRequest(API) {}
+ inline void onResponse(LocationError error) {
+ mAPI.onStopTrackingCb(error);
+ }
+ };
+
+ class UpdateTrackingOptionsRequest : public LocationAPIRequest {
+ public:
+ UpdateTrackingOptionsRequest(LocationAPIClientBase& API) : LocationAPIRequest(API) {}
+ inline void onResponse(LocationError error) {
+ mAPI.onUpdateTrackingOptionsCb(error);
+ }
+ };
+
+ class StartBatchingRequest : public LocationAPIRequest {
+ public:
+ StartBatchingRequest(LocationAPIClientBase& API) : LocationAPIRequest(API) {}
+ inline void onResponse(LocationError error) {
+ mAPI.onStartBatchingCb(error);
+ }
+ };
+
+ class StopBatchingRequest : public LocationAPIRequest {
+ public:
+ StopBatchingRequest(LocationAPIClientBase& API) : LocationAPIRequest(API) {}
+ inline void onResponse(LocationError error) {
+ mAPI.onStopBatchingCb(error);
+ }
+ };
+
+ class UpdateBatchingOptionsRequest : public LocationAPIRequest {
+ public:
+ UpdateBatchingOptionsRequest(LocationAPIClientBase& API) : LocationAPIRequest(API) {}
+ inline void onResponse(LocationError error) {
+ mAPI.onUpdateBatchingOptionsCb(error);
+ }
+ };
+
+ class GetBatchedLocationsRequest : public LocationAPIRequest {
+ public:
+ GetBatchedLocationsRequest(LocationAPIClientBase& API) : LocationAPIRequest(API) {}
+ inline void onResponse(LocationError error) {
+ mAPI.onGetBatchedLocationsCb(error);
+ }
+ };
+
+ class AddGeofencesRequest : public LocationAPIRequest {
+ public:
+ AddGeofencesRequest(LocationAPIClientBase& API) : LocationAPIRequest(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);
+ }
+ };
+
+ class RemoveGeofencesRequest : public LocationAPIRequest {
+ public:
+ RemoveGeofencesRequest(LocationAPIClientBase& API) : LocationAPIRequest(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.mGeofenceBiDict.rmBySession(sessions[i]);
+ }
+ mAPI.onRemoveGeofencesCb(count, errors, ids);
+ free(ids);
+ }
+ };
+
+ class ModifyGeofencesRequest : public LocationAPIRequest {
+ public:
+ ModifyGeofencesRequest(LocationAPIClientBase& API) : LocationAPIRequest(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);
+ }
+ };
+
+ class PauseGeofencesRequest : public LocationAPIRequest {
+ public:
+ PauseGeofencesRequest(LocationAPIClientBase& API) : LocationAPIRequest(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);
+ }
+ };
+
+ class ResumeGeofencesRequest : public LocationAPIRequest {
+ public:
+ ResumeGeofencesRequest(LocationAPIClientBase& API) : LocationAPIRequest(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);
+ }
+ };
+
+ class GnssNiResponseRequest : public LocationAPIRequest {
+ public:
+ GnssNiResponseRequest(LocationAPIClientBase& API) : LocationAPIRequest(API) {}
+ inline void onResponse(LocationError error) {
+ mAPI.onGnssNiResponseCb(error);
+ }
+ };
+
+ class GnssDeleteAidingDataRequest : public LocationAPIRequest {
+ public:
+ GnssDeleteAidingDataRequest(LocationAPIClientBase& API) : LocationAPIRequest(API) {}
+ inline void onResponse(LocationError error) {
+ mAPI.onGnssDeleteAidingDataCb(error);
+ }
+ };
+
+ class EnableRequest : public LocationAPIRequest {
+ public:
+ EnableRequest(LocationAPIClientBase& API) : LocationAPIRequest(API) {}
+ inline void onResponse(LocationError error) {
+ mAPI.onEnableCb(error);
+ }
+ };
+
+ class DisableRequest : public LocationAPIRequest {
+ public:
+ DisableRequest(LocationAPIClientBase& API) : LocationAPIRequest(API) {}
+ inline void onResponse(LocationError error) {
+ mAPI.onDisableCb(error);
+ }
+ };
+
+ class GnssUpdateConfigRequest : public LocationAPIRequest {
+ public:
+ GnssUpdateConfigRequest(LocationAPIClientBase& API) : LocationAPIRequest(API) {}
+ inline void onCollectiveResponse(size_t count, LocationError* errors, uint32_t* ids) {
+ mAPI.onGnssUpdateConfigCb(count, errors, ids);
+ }
+ };
+
+ class RequestQueue {
+ public:
+ RequestQueue(uint32_t session): mSession(session) {
+ }
+ ~RequestQueue() {
+ LocationAPIRequest* request = nullptr;
+ while (!mQueue.empty()) {
+ request = mQueue.front();
+ mQueue.pop();
+ delete request;
+ }
+ }
+ 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;
+ };
+
+ LocationAPIRequest* getRequestBySession(uint32_t session);
+ LocationAPIRequest* getGeofencesRequest();
+
+private:
+ pthread_mutex_t mMutex;
+
+ trackingCallback mTrackingCallback;
+ batchingCallback mBatchingCallback;
+ geofenceBreachCallback mGeofenceBreachCallback;
+
+ LocationAPI* mLocationAPI;
+ LocationControlAPI* mLocationControlAPI;
+
+ BiDict mGeofenceBiDict;
+ RequestQueue* mRequestQueues[REQUEST_MAX];
+ std::map<uint32_t, SessionEntity> mSessionMap;
+ int32_t mBatchSize;
+
+ GnssConfig mConfig;
+};
+
+#endif /* LOCATION_API_CLINET_BASE_H */
diff --git a/location/location_interface.h b/location/location_interface.h
new file mode 100644
index 0000000..b726931
--- /dev/null
+++ b/location/location_interface.h
@@ -0,0 +1,86 @@
+/* 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>
+
+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);
+};
+
+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&);
+ void (*stopBatching)(LocationAPI* client, uint32_t id);
+ void (*updateBatchingOptions)(LocationAPI* client, uint32_t id, LocationOptions&);
+ 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 */