diff options
author | Dante Russo <drusso@codeaurora.org> | 2017-02-28 16:45:47 -0800 |
---|---|---|
committer | Dante Russo <drusso@codeaurora.org> | 2017-02-28 16:47:50 -0800 |
commit | c85c8ff673e4347cea911b353de120f639b39b83 (patch) | |
tree | 5fe203230801cf76dc1823b6d05a44ea94663883 /location/LocationAPIClientBase.cpp | |
parent | 4bb940c0679ab23c9b8954bcb9ad8da5ede093cd (diff) | |
download | gps-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.cpp | 769 |
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; +} |