summaryrefslogtreecommitdiff
path: root/location/LocationAPIClientBase.cpp
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/LocationAPIClientBase.cpp
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/LocationAPIClientBase.cpp')
-rw-r--r--location/LocationAPIClientBase.cpp769
1 files changed, 769 insertions, 0 deletions
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;
+}