diff options
Diffstat (limited to 'batching')
-rw-r--r-- | batching/Android.mk | 37 | ||||
-rw-r--r-- | batching/BatchingAdapter.cpp | 1050 | ||||
-rw-r--r-- | batching/BatchingAdapter.h | 152 | ||||
-rw-r--r-- | batching/Makefile.am | 45 | ||||
-rw-r--r-- | batching/configure.ac | 78 | ||||
-rw-r--r-- | batching/location-batching.pc.in | 10 | ||||
-rw-r--r-- | batching/location_batching.cpp | 134 |
7 files changed, 1506 insertions, 0 deletions
diff --git a/batching/Android.mk b/batching/Android.mk new file mode 100644 index 0000000..b08d155 --- /dev/null +++ b/batching/Android.mk @@ -0,0 +1,37 @@ +ifneq ($(BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE),) +ifneq ($(BUILD_TINY_ANDROID),true) + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := libbatching +LOCAL_VENDOR_MODULE := true +LOCAL_MODULE_TAGS := optional + +LOCAL_SHARED_LIBRARIES := \ + libutils \ + libcutils \ + liblog \ + libloc_core \ + libgps.utils \ + libdl \ + liblbs_core + +LOCAL_SRC_FILES += \ + location_batching.cpp \ + BatchingAdapter.cpp + +LOCAL_HEADER_LIBRARIES := \ + libgps.utils_headers \ + libloc_core_headers \ + libloc_pla_headers \ + liblocation_api_headers + +LOCAL_PRELINK_MODULE := false + +LOCAL_CFLAGS += $(GNSS_CFLAGS) +include $(BUILD_SHARED_LIBRARY) + +endif # not BUILD_TINY_ANDROID +endif # BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE diff --git a/batching/BatchingAdapter.cpp b/batching/BatchingAdapter.cpp new file mode 100644 index 0000000..135f0ed --- /dev/null +++ b/batching/BatchingAdapter.cpp @@ -0,0 +1,1050 @@ +/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#define LOG_NDEBUG 0 +#define LOG_TAG "LocSvc_BatchingAdapter" + +#include <loc_pla.h> +#include <log_util.h> +#include <LocContext.h> +#include <BatchingAdapter.h> + +using namespace loc_core; + +BatchingAdapter::BatchingAdapter() : + LocAdapterBase(0, + LocContext::getLocContext( + NULL, + NULL, + LocContext::mLocationHalName, + false)), + mOngoingTripDistance(0), + mOngoingTripTBFInterval(0), + mTripWithOngoingTBFDropped(false), + mTripWithOngoingTripDistanceDropped(false), + mBatchingTimeout(0), + mBatchingAccuracy(1), + mBatchSize(0), + mTripBatchSize(0) +{ + LOC_LOGD("%s]: Constructor", __func__); + readConfigCommand(); + setConfigCommand(); +} + +void +BatchingAdapter::readConfigCommand() +{ + LOC_LOGD("%s]: ", __func__); + + struct MsgReadConfig : public LocMsg { + BatchingAdapter& mAdapter; + inline MsgReadConfig(BatchingAdapter& adapter) : + LocMsg(), + mAdapter(adapter) {} + inline virtual void proc() const { + uint32_t batchingTimeout = 0; + uint32_t batchingAccuracy = 0; + uint32_t batchSize = 0; + uint32_t tripBatchSize = 0; + static const loc_param_s_type flp_conf_param_table[] = + { + {"BATCH_SIZE", &batchSize, NULL, 'n'}, + {"OUTDOOR_TRIP_BATCH_SIZE", &tripBatchSize, NULL, 'n'}, + {"BATCH_SESSION_TIMEOUT", &batchingTimeout, NULL, 'n'}, + {"ACCURACY", &batchingAccuracy, NULL, 'n'}, + }; + UTIL_READ_CONF(LOC_PATH_FLP_CONF, flp_conf_param_table); + + LOC_LOGD("%s]: batchSize %u tripBatchSize %u batchingAccuracy %u batchingTimeout %u ", + __func__, batchSize, tripBatchSize, batchingAccuracy, batchingTimeout); + + mAdapter.setBatchSize(batchSize); + mAdapter.setTripBatchSize(tripBatchSize); + mAdapter.setBatchingTimeout(batchingTimeout); + mAdapter.setBatchingAccuracy(batchingAccuracy); + } + }; + + sendMsg(new MsgReadConfig(*this)); + +} + +void +BatchingAdapter::setConfigCommand() +{ + LOC_LOGD("%s]: ", __func__); + + struct MsgSetConfig : public LocMsg { + BatchingAdapter& mAdapter; + LocApiBase& mApi; + inline MsgSetConfig(BatchingAdapter& adapter, + LocApiBase& api) : + LocMsg(), + mAdapter(adapter), + mApi(api) {} + inline virtual void proc() const { + mApi.setBatchSize(mAdapter.getBatchSize()); + mApi.setTripBatchSize(mAdapter.getTripBatchSize()); + } + }; + + sendMsg(new MsgSetConfig(*this, *mLocApi)); +} + +void +BatchingAdapter::stopClientSessions(LocationAPI* client) +{ + LOC_LOGD("%s]: client %p", __func__, client); + + typedef struct pairKeyBatchMode { + LocationAPI* client; + uint32_t id; + BatchingMode batchingMode; + inline pairKeyBatchMode(LocationAPI* _client, uint32_t _id, BatchingMode _bMode) : + client(_client), id(_id), batchingMode(_bMode) {} + } pairKeyBatchMode; + std::vector<pairKeyBatchMode> vBatchingClient; + for (auto it : mBatchingSessions) { + if (client == it.first.client) { + vBatchingClient.emplace_back(it.first.client, it.first.id, it.second.batchingMode); + } + } + for (auto keyBatchingMode : vBatchingClient) { + if (keyBatchingMode.batchingMode != BATCHING_MODE_TRIP) { + stopBatching(keyBatchingMode.client, keyBatchingMode.id); + } else { + stopTripBatchingMultiplex(keyBatchingMode.client, keyBatchingMode.id); + } + } +} + +void +BatchingAdapter::updateClientsEventMask() +{ + LOC_API_ADAPTER_EVENT_MASK_T mask = 0; + for (auto it=mClientData.begin(); it != mClientData.end(); ++it) { + // we don't register LOC_API_ADAPTER_BIT_BATCH_FULL until we + // start batching with ROUTINE or TRIP option + if (it->second.batchingCb != nullptr) { + mask |= LOC_API_ADAPTER_BIT_BATCH_STATUS; + } + } + if (autoReportBatchingSessionsCount() > 0) { + mask |= LOC_API_ADAPTER_BIT_BATCH_FULL; + } + updateEvtMask(mask, LOC_REGISTRATION_MASK_SET); +} + +void +BatchingAdapter::handleEngineUpEvent() +{ + struct MsgSSREvent : public LocMsg { + BatchingAdapter& mAdapter; + LocApiBase& mApi; + inline MsgSSREvent(BatchingAdapter& adapter, + LocApiBase& api) : + LocMsg(), + mAdapter(adapter), + mApi(api) {} + virtual void proc() const { + mAdapter.setEngineCapabilitiesKnown(true); + mAdapter.broadcastCapabilities(mAdapter.getCapabilities()); + mApi.setBatchSize(mAdapter.getBatchSize()); + mApi.setTripBatchSize(mAdapter.getTripBatchSize()); + mAdapter.restartSessions(); + for (auto msg: mAdapter.mPendingMsgs) { + mAdapter.sendMsg(msg); + } + mAdapter.mPendingMsgs.clear(); + } + }; + + sendMsg(new MsgSSREvent(*this, *mLocApi)); +} + +void +BatchingAdapter::restartSessions() +{ + LOC_LOGD("%s]: ", __func__); + + if (autoReportBatchingSessionsCount() > 0) { + updateEvtMask(LOC_API_ADAPTER_BIT_BATCH_FULL, + LOC_REGISTRATION_MASK_ENABLED); + } + for (auto it = mBatchingSessions.begin(); + it != mBatchingSessions.end(); ++it) { + if (it->second.batchingMode != BATCHING_MODE_TRIP) { + mLocApi->startBatching(it->first.id, it->second, + getBatchingAccuracy(), getBatchingTimeout(), + new LocApiResponse(*getContext(), + [] (LocationError /*err*/) {})); + } + } + + if (mTripSessions.size() > 0) { + // restart outdoor trip batching session if any. + mOngoingTripDistance = 0; + mOngoingTripTBFInterval = 0; + + // record the min trip distance and min tbf interval of all ongoing sessions + for (auto tripSession : mTripSessions) { + + TripSessionStatus &tripSessStatus = tripSession.second; + + if ((0 == mOngoingTripDistance) || + (mOngoingTripDistance > + (tripSessStatus.tripDistance - tripSessStatus.accumulatedDistanceThisTrip))) { + mOngoingTripDistance = tripSessStatus.tripDistance - + tripSessStatus.accumulatedDistanceThisTrip; + } + + if ((0 == mOngoingTripTBFInterval) || + (mOngoingTripTBFInterval > tripSessStatus.tripTBFInterval)) { + mOngoingTripTBFInterval = tripSessStatus.tripTBFInterval; + } + + // reset the accumulatedDistanceOngoingBatch for each session + tripSessStatus.accumulatedDistanceOngoingBatch = 0; + + } + + mLocApi->startOutdoorTripBatching(mOngoingTripDistance, mOngoingTripTBFInterval, + getBatchingTimeout(), new LocApiResponse(*getContext(), [this] (LocationError err) { + if (LOCATION_ERROR_SUCCESS != err) { + mOngoingTripDistance = 0; + mOngoingTripTBFInterval = 0; + } + printTripReport(); + })); + } +} + +bool +BatchingAdapter::hasBatchingCallback(LocationAPI* client) +{ + auto it = mClientData.find(client); + return (it != mClientData.end() && it->second.batchingCb); +} + +bool +BatchingAdapter::isBatchingSession(LocationAPI* client, uint32_t sessionId) +{ + LocationSessionKey key(client, sessionId); + return (mBatchingSessions.find(key) != mBatchingSessions.end()); +} + +bool +BatchingAdapter::isTripSession(uint32_t sessionId) { + return (mTripSessions.find(sessionId) != mTripSessions.end()); +} + +void +BatchingAdapter::saveBatchingSession(LocationAPI* client, uint32_t sessionId, + const BatchingOptions& batchingOptions) +{ + LocationSessionKey key(client, sessionId); + mBatchingSessions[key] = batchingOptions; +} + +void +BatchingAdapter::eraseBatchingSession(LocationAPI* client, uint32_t sessionId) +{ + LocationSessionKey key(client, sessionId); + auto it = mBatchingSessions.find(key); + if (it != mBatchingSessions.end()) { + mBatchingSessions.erase(it); + } +} + +void +BatchingAdapter::reportResponse(LocationAPI* client, LocationError err, uint32_t sessionId) +{ + LOC_LOGD("%s]: client %p id %u err %u", __func__, client, sessionId, err); + + auto it = mClientData.find(client); + if (it != mClientData.end() && + it->second.responseCb != nullptr) { + it->second.responseCb(err, sessionId); + } else { + LOC_LOGE("%s]: client %p id %u not found in data", __func__, client, sessionId); + } +} + +uint32_t +BatchingAdapter::autoReportBatchingSessionsCount() +{ + uint32_t count = 0; + for (auto batchingSession: mBatchingSessions) { + if (batchingSession.second.batchingMode != BATCHING_MODE_NO_AUTO_REPORT) { + count++; + } + } + count += mTripSessions.size(); + return count; +} + +uint32_t +BatchingAdapter::startBatchingCommand( + LocationAPI* client, BatchingOptions& batchOptions) +{ + uint32_t sessionId = generateSessionId(); + LOC_LOGD("%s]: client %p id %u minInterval %u minDistance %u mode %u Batching Mode %d", + __func__, client, sessionId, batchOptions.minInterval, batchOptions.minDistance, + batchOptions.mode,batchOptions.batchingMode); + + struct MsgStartBatching : public LocMsg { + BatchingAdapter& mAdapter; + LocApiBase& mApi; + LocationAPI* mClient; + uint32_t mSessionId; + BatchingOptions mBatchingOptions; + inline MsgStartBatching(BatchingAdapter& adapter, + LocApiBase& api, + LocationAPI* client, + uint32_t sessionId, + BatchingOptions batchOptions) : + LocMsg(), + mAdapter(adapter), + mApi(api), + mClient(client), + mSessionId(sessionId), + mBatchingOptions(batchOptions) {} + inline virtual void proc() const { + if (!mAdapter.isEngineCapabilitiesKnown()) { + mAdapter.mPendingMsgs.push_back(new MsgStartBatching(*this)); + return; + } + LocationError err = LOCATION_ERROR_SUCCESS; + + if (!mAdapter.hasBatchingCallback(mClient)) { + err = LOCATION_ERROR_CALLBACK_MISSING; + } else if (0 == mBatchingOptions.size) { + err = LOCATION_ERROR_INVALID_PARAMETER; + } else if (!ContextBase::isMessageSupported( + LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_LOCATION_BATCHING)) { + err = LOCATION_ERROR_NOT_SUPPORTED; + } + if (LOCATION_ERROR_SUCCESS == err) { + if (mBatchingOptions.batchingMode == BATCHING_MODE_ROUTINE || + mBatchingOptions.batchingMode == BATCHING_MODE_NO_AUTO_REPORT) { + mAdapter.startBatching(mClient, mSessionId, mBatchingOptions); + } else if (mBatchingOptions.batchingMode == BATCHING_MODE_TRIP) { + mAdapter.startTripBatchingMultiplex(mClient, mSessionId, mBatchingOptions); + } else { + mAdapter.reportResponse(mClient, LOCATION_ERROR_INVALID_PARAMETER, mSessionId); + } + } + } + }; + + sendMsg(new MsgStartBatching(*this, *mLocApi, client, sessionId, batchOptions)); + + return sessionId; +} + +void +BatchingAdapter::startBatching(LocationAPI* client, uint32_t sessionId, + const BatchingOptions& batchingOptions) +{ + if (batchingOptions.batchingMode != BATCHING_MODE_NO_AUTO_REPORT && + 0 == autoReportBatchingSessionsCount()) { + // if there is currenty no batching sessions interested in batch full event, then this + // new session will need to register for batch full event + updateEvtMask(LOC_API_ADAPTER_BIT_BATCH_FULL, + LOC_REGISTRATION_MASK_ENABLED); + } + + // Assume start will be OK, remove session if not + saveBatchingSession(client, sessionId, batchingOptions); + mLocApi->startBatching(sessionId, batchingOptions, getBatchingAccuracy(), getBatchingTimeout(), + new LocApiResponse(*getContext(), + [this, client, sessionId, batchingOptions] (LocationError err) { + if (LOCATION_ERROR_SUCCESS != err) { + eraseBatchingSession(client, sessionId); + } + + if (LOCATION_ERROR_SUCCESS != err && + batchingOptions.batchingMode != BATCHING_MODE_NO_AUTO_REPORT && + 0 == autoReportBatchingSessionsCount()) { + // if we fail to start batching and we have already registered batch full event + // we need to undo that since no sessions are now interested in batch full event + updateEvtMask(LOC_API_ADAPTER_BIT_BATCH_FULL, + LOC_REGISTRATION_MASK_DISABLED); + } + + reportResponse(client, err, sessionId); + })); +} + +void +BatchingAdapter::updateBatchingOptionsCommand(LocationAPI* client, uint32_t id, + BatchingOptions& batchOptions) +{ + LOC_LOGD("%s]: client %p id %u minInterval %u minDistance %u mode %u batchMode %u", + __func__, client, id, batchOptions.minInterval, + batchOptions.minDistance, batchOptions.mode, + batchOptions.batchingMode); + + struct MsgUpdateBatching : public LocMsg { + BatchingAdapter& mAdapter; + LocApiBase& mApi; + LocationAPI* mClient; + uint32_t mSessionId; + BatchingOptions mBatchOptions; + inline MsgUpdateBatching(BatchingAdapter& adapter, + LocApiBase& api, + LocationAPI* client, + uint32_t sessionId, + BatchingOptions batchOptions) : + LocMsg(), + mAdapter(adapter), + mApi(api), + mClient(client), + mSessionId(sessionId), + mBatchOptions(batchOptions) {} + inline virtual void proc() const { + if (!mAdapter.isEngineCapabilitiesKnown()) { + mAdapter.mPendingMsgs.push_back(new MsgUpdateBatching(*this)); + return; + } + LocationError err = LOCATION_ERROR_SUCCESS; + if (!mAdapter.isBatchingSession(mClient, mSessionId)) { + err = LOCATION_ERROR_ID_UNKNOWN; + } else if ((0 == mBatchOptions.size) || + (mBatchOptions.batchingMode > BATCHING_MODE_NO_AUTO_REPORT)) { + err = LOCATION_ERROR_INVALID_PARAMETER; + } + if (LOCATION_ERROR_SUCCESS == err) { + if (!mAdapter.isTripSession(mSessionId)) { + mAdapter.stopBatching(mClient, mSessionId, true, mBatchOptions); + } else { + mAdapter.stopTripBatchingMultiplex(mClient, mSessionId, true, mBatchOptions); + } + } + } + }; + + sendMsg(new MsgUpdateBatching(*this, *mLocApi, client, id, batchOptions)); +} + +void +BatchingAdapter::stopBatchingCommand(LocationAPI* client, uint32_t id) +{ + LOC_LOGD("%s]: client %p id %u", __func__, client, id); + + struct MsgStopBatching : public LocMsg { + BatchingAdapter& mAdapter; + LocApiBase& mApi; + LocationAPI* mClient; + uint32_t mSessionId; + inline MsgStopBatching(BatchingAdapter& adapter, + LocApiBase& api, + LocationAPI* client, + uint32_t sessionId) : + LocMsg(), + mAdapter(adapter), + mApi(api), + mClient(client), + mSessionId(sessionId) {} + inline virtual void proc() const { + if (!mAdapter.isEngineCapabilitiesKnown()) { + mAdapter.mPendingMsgs.push_back(new MsgStopBatching(*this)); + return; + } + LocationError err = LOCATION_ERROR_SUCCESS; + if (!mAdapter.isBatchingSession(mClient, mSessionId)) { + err = LOCATION_ERROR_ID_UNKNOWN; + } + if (LOCATION_ERROR_SUCCESS == err) { + if (mAdapter.isTripSession(mSessionId)) { + mAdapter.stopTripBatchingMultiplex(mClient, mSessionId); + } else { + mAdapter.stopBatching(mClient, mSessionId); + } + } + } + }; + + sendMsg(new MsgStopBatching(*this, *mLocApi, client, id)); +} + +void +BatchingAdapter::stopBatching(LocationAPI* client, uint32_t sessionId, bool restartNeeded, + const BatchingOptions& batchOptions) +{ + LocationSessionKey key(client, sessionId); + auto it = mBatchingSessions.find(key); + if (it != mBatchingSessions.end()) { + auto flpOptions = it->second; + // Assume stop will be OK, restore session if not + eraseBatchingSession(client, sessionId); + mLocApi->stopBatching(sessionId, + new LocApiResponse(*getContext(), + [this, client, sessionId, flpOptions, restartNeeded, batchOptions] + (LocationError err) { + if (LOCATION_ERROR_SUCCESS != err) { + saveBatchingSession(client, sessionId, batchOptions); + } else { + // if stopBatching is success, unregister for batch full event if this was the last + // batching session that is interested in batch full event + if (0 == autoReportBatchingSessionsCount() && + flpOptions.batchingMode != BATCHING_MODE_NO_AUTO_REPORT) { + updateEvtMask(LOC_API_ADAPTER_BIT_BATCH_FULL, + LOC_REGISTRATION_MASK_DISABLED); + } + + if (restartNeeded) { + if (batchOptions.batchingMode == BATCHING_MODE_ROUTINE || + batchOptions.batchingMode == BATCHING_MODE_NO_AUTO_REPORT) { + startBatching(client, sessionId, batchOptions); + } else if (batchOptions.batchingMode == BATCHING_MODE_TRIP) { + startTripBatchingMultiplex(client, sessionId, batchOptions); + } + } + } + reportResponse(client, err, sessionId); + })); + } +} + +void +BatchingAdapter::getBatchedLocationsCommand(LocationAPI* client, uint32_t id, size_t count) +{ + LOC_LOGD("%s]: client %p id %u count %zu", __func__, client, id, count); + + struct MsgGetBatchedLocations : public LocMsg { + BatchingAdapter& mAdapter; + LocApiBase& mApi; + LocationAPI* mClient; + uint32_t mSessionId; + size_t mCount; + inline MsgGetBatchedLocations(BatchingAdapter& adapter, + LocApiBase& api, + LocationAPI* client, + uint32_t sessionId, + size_t count) : + LocMsg(), + mAdapter(adapter), + mApi(api), + mClient(client), + mSessionId(sessionId), + mCount(count) {} + inline virtual void proc() const { + if (!mAdapter.isEngineCapabilitiesKnown()) { + mAdapter.mPendingMsgs.push_back(new MsgGetBatchedLocations(*this)); + return; + } + LocationError err = LOCATION_ERROR_SUCCESS; + if (!mAdapter.hasBatchingCallback(mClient)) { + err = LOCATION_ERROR_CALLBACK_MISSING; + } else if (!mAdapter.isBatchingSession(mClient, mSessionId)) { + err = LOCATION_ERROR_ID_UNKNOWN; + } + if (LOCATION_ERROR_SUCCESS == err) { + if (mAdapter.isTripSession(mSessionId)) { + mApi.getBatchedTripLocations(mCount, 0, + new LocApiResponse(*mAdapter.getContext(), + [&mAdapter = mAdapter, mSessionId = mSessionId, + mClient = mClient] (LocationError err) { + mAdapter.reportResponse(mClient, err, mSessionId); + })); + } else { + mApi.getBatchedLocations(mCount, new LocApiResponse(*mAdapter.getContext(), + [&mAdapter = mAdapter, mSessionId = mSessionId, + mClient = mClient] (LocationError err) { + mAdapter.reportResponse(mClient, err, mSessionId); + })); + } + } else { + mAdapter.reportResponse(mClient, err, mSessionId); + } + } + }; + + sendMsg(new MsgGetBatchedLocations(*this, *mLocApi, client, id, count)); +} + +void +BatchingAdapter::reportLocationsEvent(const Location* locations, size_t count, + BatchingMode batchingMode) +{ + LOC_LOGD("%s]: count %zu batchMode %d", __func__, count, batchingMode); + + struct MsgReportLocations : public LocMsg { + BatchingAdapter& mAdapter; + Location* mLocations; + size_t mCount; + BatchingMode mBatchingMode; + inline MsgReportLocations(BatchingAdapter& adapter, + const Location* locations, + size_t count, + BatchingMode batchingMode) : + LocMsg(), + mAdapter(adapter), + mLocations(new Location[count]), + mCount(count), + mBatchingMode(batchingMode) + { + if (nullptr == mLocations) { + LOC_LOGE("%s]: new failed to allocate mLocations", __func__); + return; + } + for (size_t i=0; i < mCount; ++i) { + mLocations[i] = locations[i]; + } + } + inline virtual ~MsgReportLocations() { + if (nullptr != mLocations) + delete[] mLocations; + } + inline virtual void proc() const { + mAdapter.reportLocations(mLocations, mCount, mBatchingMode); + } + }; + + sendMsg(new MsgReportLocations(*this, locations, count, batchingMode)); +} + +void +BatchingAdapter::reportLocations(Location* locations, size_t count, BatchingMode batchingMode) +{ + BatchingOptions batchOptions = {sizeof(BatchingOptions), batchingMode}; + + for (auto it=mClientData.begin(); it != mClientData.end(); ++it) { + if (nullptr != it->second.batchingCb) { + it->second.batchingCb(count, locations, batchOptions); + } + } +} + +void +BatchingAdapter::reportCompletedTripsEvent(uint32_t accumulated_distance) +{ + struct MsgReportCompletedTrips : public LocMsg { + BatchingAdapter& mAdapter; + uint32_t mAccumulatedDistance; + inline MsgReportCompletedTrips(BatchingAdapter& adapter, + uint32_t accumulated_distance) : + LocMsg(), + mAdapter(adapter), + mAccumulatedDistance(accumulated_distance) + { + } + inline virtual ~MsgReportCompletedTrips() { + } + inline virtual void proc() const { + + // Check if any trips are completed + std::list<uint32_t> completedTripsList; + completedTripsList.clear(); + + for(auto itt = mAdapter.mTripSessions.begin(); itt != mAdapter.mTripSessions.end();) + { + TripSessionStatus &tripSession = itt->second; + + tripSession.accumulatedDistanceThisTrip = + tripSession.accumulatedDistanceOnTripRestart + + (mAccumulatedDistance - tripSession.accumulatedDistanceOngoingBatch); + if (tripSession.tripDistance <= tripSession.accumulatedDistanceThisTrip) { + // trip is completed + completedTripsList.push_back(itt->first); + itt = mAdapter.mTripSessions.erase(itt); + + if (tripSession.tripTBFInterval == mAdapter.mOngoingTripTBFInterval) { + // trip with ongoing TBF interval is completed + mAdapter.mTripWithOngoingTBFDropped = true; + } + + if (tripSession.tripDistance == mAdapter.mOngoingTripDistance) { + // trip with ongoing trip distance is completed + mAdapter.mTripWithOngoingTripDistanceDropped = true; + } + } else { + itt++; + } + } + + if (completedTripsList.size() > 0) { + mAdapter.reportBatchStatusChange(BATCHING_STATUS_TRIP_COMPLETED, + completedTripsList); + mAdapter.restartTripBatching(false, mAccumulatedDistance, 0); + } else { + mAdapter.printTripReport(); + } + } + }; + + LOC_LOGD("%s]: Accumulated Distance so far: %u", + __func__, accumulated_distance); + + sendMsg(new MsgReportCompletedTrips(*this, accumulated_distance)); +} + +void +BatchingAdapter::reportBatchStatusChange(BatchingStatus batchStatus, + std::list<uint32_t> & completedTripsList) +{ + BatchingStatusInfo batchStatusInfo = + {sizeof(BatchingStatusInfo), batchStatus}; + + for (auto it=mClientData.begin(); it != mClientData.end(); ++it) { + if (nullptr != it->second.batchingStatusCb) { + it->second.batchingStatusCb(batchStatusInfo, completedTripsList); + } + } +} + +void +BatchingAdapter::reportBatchStatusChangeEvent(BatchingStatus batchStatus) +{ + struct MsgReportBatchStatus : public LocMsg { + BatchingAdapter& mAdapter; + BatchingStatus mBatchStatus; + inline MsgReportBatchStatus(BatchingAdapter& adapter, + BatchingStatus batchStatus) : + LocMsg(), + mAdapter(adapter), + mBatchStatus(batchStatus) + { + } + inline virtual ~MsgReportBatchStatus() { + } + inline virtual void proc() const { + std::list<uint32_t> tempList; + tempList.clear(); + mAdapter.reportBatchStatusChange(mBatchStatus, tempList); + } + }; + + sendMsg(new MsgReportBatchStatus(*this, batchStatus)); +} + +void +BatchingAdapter::startTripBatchingMultiplex(LocationAPI* client, uint32_t sessionId, + const BatchingOptions& batchingOptions) +{ + if (mTripSessions.size() == 0) { + // if there is currenty no batching sessions interested in batch full event, then this + // new session will need to register for batch full event + if (0 == autoReportBatchingSessionsCount()) { + updateEvtMask(LOC_API_ADAPTER_BIT_BATCH_FULL, + LOC_REGISTRATION_MASK_ENABLED); + } + + // Assume start will be OK, remove session if not + saveBatchingSession(client, sessionId, batchingOptions); + + mTripSessions[sessionId] = { 0, 0, 0, batchingOptions.minDistance, + batchingOptions.minInterval}; + mLocApi->startOutdoorTripBatching(batchingOptions.minDistance, + batchingOptions.minInterval, getBatchingTimeout(), new LocApiResponse(*getContext(), + [this, client, sessionId, batchingOptions] (LocationError err) { + if (err == LOCATION_ERROR_SUCCESS) { + mOngoingTripDistance = batchingOptions.minDistance; + mOngoingTripTBFInterval = batchingOptions.minInterval; + LOC_LOGD("%s] New Trip started ...", __func__); + printTripReport(); + } else { + eraseBatchingSession(client, sessionId); + mTripSessions.erase(sessionId); + // if we fail to start batching and we have already registered batch full event + // we need to undo that since no sessions are now interested in batch full event + if (0 == autoReportBatchingSessionsCount()) { + updateEvtMask(LOC_API_ADAPTER_BIT_BATCH_FULL, + LOC_REGISTRATION_MASK_DISABLED); + } + } + reportResponse(client, err, sessionId); + })); + } else { + // query accumulated distance + mLocApi->queryAccumulatedTripDistance( + new LocApiResponseData<LocApiBatchData>(*getContext(), + [this, batchingOptions, sessionId, client] + (LocationError err, LocApiBatchData data) { + uint32_t accumulatedDistanceOngoingBatch = 0; + uint32_t numOfBatchedPositions = 0; + uint32_t ongoingTripDistance = mOngoingTripDistance; + uint32_t ongoingTripInterval = mOngoingTripTBFInterval; + bool needsRestart = false; + + // check if TBF of new session is lesser than ongoing TBF interval + if (ongoingTripInterval > batchingOptions.minInterval) { + ongoingTripInterval = batchingOptions.minInterval; + needsRestart = true; + } + accumulatedDistanceOngoingBatch = data.accumulatedDistance; + numOfBatchedPositions = data.numOfBatchedPositions; + TripSessionStatus newTripSession = { accumulatedDistanceOngoingBatch, 0, 0, + batchingOptions.minDistance, + batchingOptions.minInterval}; + if (err != LOCATION_ERROR_SUCCESS) { + // unable to query accumulated distance, assume remaining distance in + // ongoing batch is mongoingTripDistance. + if (batchingOptions.minDistance < ongoingTripDistance) { + ongoingTripDistance = batchingOptions.minDistance; + needsRestart = true; + } + } else { + // compute the remaining distance + uint32_t ongoing_trip_remaining_distance = ongoingTripDistance - + accumulatedDistanceOngoingBatch; + + // check if new trip distance is lesser than the ongoing batch remaining distance + if (batchingOptions.minDistance < ongoing_trip_remaining_distance) { + ongoingTripDistance = batchingOptions.minDistance; + needsRestart = true; + } else if (needsRestart == true) { + // needsRestart is anyways true , may be because of lesser TBF of new session. + ongoingTripDistance = ongoing_trip_remaining_distance; + } + mTripSessions[sessionId] = newTripSession; + LOC_LOGD("%s] New Trip started ...", __func__); + printTripReport(); + } + + if (needsRestart) { + mOngoingTripDistance = ongoingTripDistance; + mOngoingTripTBFInterval = ongoingTripInterval; + + // reset the accumulatedDistanceOngoingBatch for each session, + // and record the total accumulated distance so far for the session. + for (auto itt = mTripSessions.begin(); itt != mTripSessions.end(); itt++) { + TripSessionStatus &tripSessStatus = itt->second; + tripSessStatus.accumulatedDistanceOngoingBatch = 0; + tripSessStatus.accumulatedDistanceOnTripRestart = + tripSessStatus.accumulatedDistanceThisTrip; + } + mLocApi->reStartOutdoorTripBatching(ongoingTripDistance, ongoingTripInterval, + getBatchingTimeout(), new LocApiResponse(*getContext(), + [this, client, sessionId] (LocationError err) { + if (err != LOCATION_ERROR_SUCCESS) { + LOC_LOGE("%s] New Trip restart failed!", __func__); + } + reportResponse(client, err, sessionId); + })); + } else { + reportResponse(client, LOCATION_ERROR_SUCCESS, sessionId); + } + })); + } +} + +void +BatchingAdapter::stopTripBatchingMultiplex(LocationAPI* client, uint32_t sessionId, + bool restartNeeded, const BatchingOptions& batchOptions) +{ + LocationError err = LOCATION_ERROR_SUCCESS; + + if (mTripSessions.size() == 1) { + mLocApi->stopOutdoorTripBatching(true, new LocApiResponse(*getContext(), + [this, restartNeeded, client, sessionId, batchOptions] + (LocationError err) { + if (LOCATION_ERROR_SUCCESS == err) { + // if stopOutdoorTripBatching is success, unregister for batch full event if this + // was the last batching session that is interested in batch full event + if (1 == autoReportBatchingSessionsCount()) { + updateEvtMask(LOC_API_ADAPTER_BIT_BATCH_FULL, + LOC_REGISTRATION_MASK_DISABLED); + } + } + stopTripBatchingMultiplexCommon(err, client, sessionId, restartNeeded, batchOptions); + })); + return; + } + + stopTripBatchingMultiplexCommon(err, client, sessionId, restartNeeded, batchOptions); +} + +void +BatchingAdapter::stopTripBatchingMultiplexCommon(LocationError err, LocationAPI* client, + uint32_t sessionId, bool restartNeeded, const BatchingOptions& batchOptions) +{ + auto itt = mTripSessions.find(sessionId); + TripSessionStatus tripSess = itt->second; + if (tripSess.tripTBFInterval == mOngoingTripTBFInterval) { + // trip with ongoing trip interval is stopped + mTripWithOngoingTBFDropped = true; + } + + if (tripSess.tripDistance == mOngoingTripDistance) { + // trip with ongoing trip distance is stopped + mTripWithOngoingTripDistanceDropped = true; + } + + mTripSessions.erase(sessionId); + + if (mTripSessions.size() == 0) { + mOngoingTripDistance = 0; + mOngoingTripTBFInterval = 0; + } else { + restartTripBatching(true); + } + + if (restartNeeded) { + eraseBatchingSession(client, sessionId); + if (batchOptions.batchingMode == BATCHING_MODE_ROUTINE || + batchOptions.batchingMode == BATCHING_MODE_NO_AUTO_REPORT) { + startBatching(client, sessionId, batchOptions); + } else if (batchOptions.batchingMode == BATCHING_MODE_TRIP) { + startTripBatchingMultiplex(client, sessionId, batchOptions); + } + } + reportResponse(client, err, sessionId); +} + + +void +BatchingAdapter::restartTripBatching(bool queryAccumulatedDistance, uint32_t accDist, + uint32_t numbatchedPos) +{ + // does batch need restart with new trip distance / TBF interval + uint32_t minRemainingDistance = 0; + uint32_t minTBFInterval = 0; + + // if no more trips left, stop the ongoing trip + if (mTripSessions.size() == 0) { + mLocApi->stopOutdoorTripBatching(true, new LocApiResponse(*getContext(), + [] (LocationError /*err*/) {})); + mOngoingTripDistance = 0; + mOngoingTripTBFInterval = 0; + // unregister for batch full event if there are no more + // batching session that is interested in batch full event + if (0 == autoReportBatchingSessionsCount()) { + updateEvtMask(LOC_API_ADAPTER_BIT_BATCH_FULL, + LOC_REGISTRATION_MASK_DISABLED); + } + return; + } + + // record the min trip distance and min tbf interval of all ongoing sessions + for (auto itt = mTripSessions.begin(); itt != mTripSessions.end(); itt++) { + + TripSessionStatus tripSessStatus = itt->second; + + if ((minRemainingDistance == 0) || + (minRemainingDistance > (tripSessStatus.tripDistance + - tripSessStatus.accumulatedDistanceThisTrip))) { + minRemainingDistance = tripSessStatus.tripDistance - + tripSessStatus.accumulatedDistanceThisTrip; + } + + if ((minTBFInterval == 0) || + (minTBFInterval > tripSessStatus.tripTBFInterval)) { + minTBFInterval = tripSessStatus.tripTBFInterval; + } + } + + mLocApi->queryAccumulatedTripDistance( + new LocApiResponseData<LocApiBatchData>(*getContext(), + [this, queryAccumulatedDistance, minRemainingDistance, minTBFInterval, accDist, + numbatchedPos] (LocationError /*err*/, LocApiBatchData data) { + bool needsRestart = false; + + uint32_t ongoingTripDistance = mOngoingTripDistance; + uint32_t ongoingTripInterval = mOngoingTripTBFInterval; + uint32_t accumulatedDistance = accDist; + uint32_t numOfBatchedPositions = numbatchedPos; + + if (queryAccumulatedDistance) { + accumulatedDistance = data.accumulatedDistance; + numOfBatchedPositions = data.numOfBatchedPositions; + } + + if ((!mTripWithOngoingTripDistanceDropped) && + (ongoingTripDistance - accumulatedDistance != 0)) { + // if ongoing trip is already not completed still, + // check the min distance against the remaining distance + if (minRemainingDistance < + (ongoingTripDistance - accumulatedDistance)) { + ongoingTripDistance = minRemainingDistance; + needsRestart = true; + } + } else if (minRemainingDistance != 0) { + // else if ongoing trip is already completed / dropped, + // use the minRemainingDistance of ongoing sessions + ongoingTripDistance = minRemainingDistance; + needsRestart = true; + } + + if ((minTBFInterval < ongoingTripInterval) || + ((minTBFInterval != ongoingTripInterval) && + (mTripWithOngoingTBFDropped))) { + ongoingTripInterval = minTBFInterval; + needsRestart = true; + } + + if (needsRestart) { + mLocApi->reStartOutdoorTripBatching(ongoingTripDistance, ongoingTripInterval, + getBatchingTimeout(), new LocApiResponse(*getContext(), + [this, accumulatedDistance, ongoingTripDistance, ongoingTripInterval] + (LocationError err) { + + if (err == LOCATION_ERROR_SUCCESS) { + for(auto itt = mTripSessions.begin(); itt != mTripSessions.end(); itt++) { + TripSessionStatus &tripSessStatus = itt->second; + tripSessStatus.accumulatedDistanceThisTrip = + tripSessStatus.accumulatedDistanceOnTripRestart + + (accumulatedDistance - + tripSessStatus.accumulatedDistanceOngoingBatch); + + tripSessStatus.accumulatedDistanceOngoingBatch = 0; + tripSessStatus.accumulatedDistanceOnTripRestart = + tripSessStatus.accumulatedDistanceThisTrip; + } + + mOngoingTripDistance = ongoingTripDistance; + mOngoingTripTBFInterval = ongoingTripInterval; + } + })); + } + })); +} + +void +BatchingAdapter::printTripReport() +{ + IF_LOC_LOGD { + LOC_LOGD("Ongoing Trip Distance = %u, Ongoing Trip TBF Interval = %u", + mOngoingTripDistance, mOngoingTripTBFInterval); + + for (auto itt = mTripSessions.begin(); itt != mTripSessions.end(); itt++) { + TripSessionStatus tripSessStatus = itt->second; + + LOC_LOGD("tripDistance:%u tripTBFInterval:%u" + " trip accumulated Distance:%u" + " trip accumualted distance ongoing batch:%u" + " trip accumulated distance on trip restart %u \r\n", + tripSessStatus.tripDistance, tripSessStatus.tripTBFInterval, + tripSessStatus.accumulatedDistanceThisTrip, + tripSessStatus.accumulatedDistanceOngoingBatch, + tripSessStatus.accumulatedDistanceOnTripRestart); + } + } +} diff --git a/batching/BatchingAdapter.h b/batching/BatchingAdapter.h new file mode 100644 index 0000000..66f7c5f --- /dev/null +++ b/batching/BatchingAdapter.h @@ -0,0 +1,152 @@ +/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef BATCHING_ADAPTER_H +#define BATCHING_ADAPTER_H + +#include <LocAdapterBase.h> +#include <LocContext.h> +#include <LocationAPI.h> +#include <map> + +using namespace loc_core; + +class BatchingAdapter : public LocAdapterBase { + + /* ==== BATCHING ======================================================================= */ + typedef struct { + uint32_t accumulatedDistanceOngoingBatch; + uint32_t accumulatedDistanceThisTrip; + uint32_t accumulatedDistanceOnTripRestart; + uint32_t tripDistance; + uint32_t tripTBFInterval; + } TripSessionStatus; + typedef std::map<uint32_t, TripSessionStatus> TripSessionStatusMap; + typedef std::map<LocationSessionKey, BatchingOptions> BatchingSessionMap; + + BatchingSessionMap mBatchingSessions; + TripSessionStatusMap mTripSessions; + uint32_t mOngoingTripDistance; + uint32_t mOngoingTripTBFInterval; + bool mTripWithOngoingTBFDropped; + bool mTripWithOngoingTripDistanceDropped; + + void startTripBatchingMultiplex(LocationAPI* client, uint32_t sessionId, + const BatchingOptions& batchingOptions); + void stopTripBatchingMultiplex(LocationAPI* client, uint32_t sessionId, + bool restartNeeded, + const BatchingOptions& batchOptions); + inline void stopTripBatchingMultiplex(LocationAPI* client, uint32_t id) { + BatchingOptions batchOptions; + stopTripBatchingMultiplex(client, id, false, batchOptions); + }; + void stopTripBatchingMultiplexCommon(LocationError err, + LocationAPI* client, + uint32_t sessionId, + bool restartNeeded, + const BatchingOptions& batchOptions); + void restartTripBatching(bool queryAccumulatedDistance, uint32_t accDist = 0, + uint32_t numbatchedPos = 0); + void printTripReport(); + + /* ==== CONFIGURATION ================================================================== */ + uint32_t mBatchingTimeout; + uint32_t mBatchingAccuracy; + size_t mBatchSize; + size_t mTripBatchSize; + +protected: + + /* ==== CLIENT ========================================================================= */ + virtual void updateClientsEventMask(); + virtual void stopClientSessions(LocationAPI* client); + +public: + BatchingAdapter(); + virtual ~BatchingAdapter() {} + + /* ==== SSR ============================================================================ */ + /* ======== EVENTS ====(Called from QMI Thread)========================================= */ + virtual void handleEngineUpEvent(); + /* ======== UTILITIES ================================================================== */ + void restartSessions(); + + /* ==== BATCHING ======================================================================= */ + /* ======== COMMANDS ====(Called from Client Thread)==================================== */ + uint32_t startBatchingCommand(LocationAPI* client, BatchingOptions &batchOptions); + void updateBatchingOptionsCommand( + LocationAPI* client, uint32_t id, BatchingOptions& batchOptions); + void stopBatchingCommand(LocationAPI* client, uint32_t id); + void getBatchedLocationsCommand(LocationAPI* client, uint32_t id, size_t count); + /* ======== RESPONSES ================================================================== */ + void reportResponse(LocationAPI* client, LocationError err, uint32_t sessionId); + /* ======== UTILITIES ================================================================== */ + bool hasBatchingCallback(LocationAPI* client); + bool isBatchingSession(LocationAPI* client, uint32_t sessionId); + bool isTripSession(uint32_t sessionId); + void saveBatchingSession(LocationAPI* client, uint32_t sessionId, + const BatchingOptions& batchingOptions); + void eraseBatchingSession(LocationAPI* client, uint32_t sessionId); + uint32_t autoReportBatchingSessionsCount(); + void startBatching(LocationAPI* client, uint32_t sessionId, + const BatchingOptions& batchingOptions); + void stopBatching(LocationAPI* client, uint32_t sessionId, bool restartNeeded, + const BatchingOptions& batchOptions); + void stopBatching(LocationAPI* client, uint32_t sessionId) { + BatchingOptions batchOptions; + stopBatching(client, sessionId, false, batchOptions); + }; + + /* ==== REPORTS ======================================================================== */ + /* ======== EVENTS ====(Called from QMI Thread)========================================= */ + void reportLocationsEvent(const Location* locations, size_t count, + BatchingMode batchingMode); + void reportCompletedTripsEvent(uint32_t accumulatedDistance); + void reportBatchStatusChangeEvent(BatchingStatus batchStatus); + /* ======== UTILITIES ================================================================== */ + void reportLocations(Location* locations, size_t count, BatchingMode batchingMode); + void reportBatchStatusChange(BatchingStatus batchStatus, + std::list<uint32_t> & completedTripsList); + + /* ==== CONFIGURATION ================================================================== */ + /* ======== COMMANDS ====(Called from Client Thread)==================================== */ + void readConfigCommand(); + void setConfigCommand(); + /* ======== UTILITIES ================================================================== */ + void setBatchSize(size_t batchSize) { mBatchSize = batchSize; } + size_t getBatchSize() { return mBatchSize; } + void setTripBatchSize(size_t batchSize) { mTripBatchSize = batchSize; } + size_t getTripBatchSize() { return mTripBatchSize; } + void setBatchingTimeout(uint32_t batchingTimeout) { mBatchingTimeout = batchingTimeout; } + uint32_t getBatchingTimeout() { return mBatchingTimeout; } + void setBatchingAccuracy(uint32_t accuracy) { mBatchingAccuracy = accuracy; } + uint32_t getBatchingAccuracy() { return mBatchingAccuracy; } + +}; + +#endif /* BATCHING_ADAPTER_H */ diff --git a/batching/Makefile.am b/batching/Makefile.am new file mode 100644 index 0000000..ef8011e --- /dev/null +++ b/batching/Makefile.am @@ -0,0 +1,45 @@ +AM_CFLAGS = \ + $(GPSUTILS_CFLAGS) \ + $(LOCCORE_CFLAGS) \ + -I./ \ + -std=c++1y \ + -D__func__=__PRETTY_FUNCTION__ \ + -fno-short-enums + +ACLOCAL_AMFLAGS = -I m4 + +requiredlibs = \ + $(GPSUTILS_LIBS) \ + $(LOCCORE_LIBS) \ + -llog + +h_sources = \ + BatchingAdapter.h + +libbatching_la_SOURCES = \ + location_batching.cpp \ + BatchingAdapter.cpp + +if USE_GLIB +libbatching_la_CFLAGS = -DUSE_GLIB $(AM_CFLAGS) @GLIB_CFLAGS@ +#libbatching_la_LDFLAGS = -lstdc++ -g -Wl,-z,defs -lpthread $(requiredlibs) @GLIB_LIBS@ -shared -avoid-version +libbatching_la_LDFLAGS = -lstdc++ -g -Wl,-z,defs -lpthread $(requiredlibs) @GLIB_LIBS@ -avoid-version +libbatching_la_CPPFLAGS = -DUSE_GLIB $(AM_CFLAGS) $(AM_CPPFLAGS) @GLIB_CFLAGS@ +else +libbatching_la_CFLAGS = $(AM_CFLAGS) +libbatching_la_LDFLAGS = -Wl,-z,defs -lpthread $(requiredlibs) -shared -version-info 1:0:0 +libbatching_la_CPPFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS) +endif + +library_include_HEADERS = $(h_sources) + +library_includedir = $(pkgincludedir) + +#Create and Install libraries +lib_LTLIBRARIES = libbatching.la + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = location-batching.pc +sysconf_DATA = $(WORKSPACE)/hardware/qcom/gps/etc/flp.conf +EXTRA_DIST = $(pkgconfig_DATA) + diff --git a/batching/configure.ac b/batching/configure.ac new file mode 100644 index 0000000..27435c6 --- /dev/null +++ b/batching/configure.ac @@ -0,0 +1,78 @@ +# configure.ac -- Autoconf script for gps location-batching +# +# Process this file with autoconf to produce a configure script + +# Requires autoconf tool later than 2.61 +AC_PREREQ(2.61) +# Initialize the gps location-batching package version 1.0.0 +AC_INIT([location-batching],1.0.0) +# Does not strictly follow GNU Coding standards +AM_INIT_AUTOMAKE([foreign]) +# Disables auto rebuilding of configure, Makefile.ins +AM_MAINTAINER_MODE +# Verifies the --srcdir is correct by checking for the path +AC_CONFIG_SRCDIR([Makefile.am]) +# defines some macros variable to be included by source +AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_MACRO_DIR([m4]) + +# Checks for programs. +AC_PROG_LIBTOOL +AC_PROG_CXX +AC_PROG_CC +AM_PROG_CC_C_O +AC_PROG_AWK +AC_PROG_CPP +AC_PROG_INSTALL +AC_PROG_LN_S +AC_PROG_MAKE_SET +PKG_PROG_PKG_CONFIG + +# Checks for libraries. +PKG_CHECK_MODULES([GPSUTILS], [gps-utils]) +AC_SUBST([GPSUTILS_CFLAGS]) +AC_SUBST([GPSUTILS_LIBS]) + +PKG_CHECK_MODULES([LOCCORE], [loc-core]) +AC_SUBST([LOCCORE_CFLAGS]) +AC_SUBST([LOCCORE_LIBS]) + +PKG_CHECK_MODULES([GEOFENCE], [location-geofence]) +AC_SUBST([GEOFENCE_CFLAGS]) +AC_SUBST([GEOFENCE_LIBS]) + +AC_ARG_WITH([locpla_includes], + AC_HELP_STRING([--with-locpla-includes=@<:@dir@:>@], + [specify the path to locpla-includes in loc-pla_git.bb]), + [locpla_incdir=$withval], + with_locpla_includes=no) + +if test "x$with_locpla_includes" != "xno"; then + AC_SUBST(LOCPLA_CFLAGS, "-I${locpla_incdir}") +fi + +AC_ARG_WITH([glib], + AC_HELP_STRING([--with-glib], + [enable glib, building HLOS systems which use glib])) + +if (test "x${with_glib}" = "xyes"); then + AC_DEFINE(ENABLE_USEGLIB, 1, [Define if HLOS systems uses glib]) + PKG_CHECK_MODULES(GTHREAD, gthread-2.0 >= 2.16, dummy=yes, + AC_MSG_ERROR(GThread >= 2.16 is required)) + PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.16, dummy=yes, + AC_MSG_ERROR(GLib >= 2.16 is required)) + GLIB_CFLAGS="$GLIB_CFLAGS $GTHREAD_CFLAGS" + GLIB_LIBS="$GLIB_LIBS $GTHREAD_LIBS" + + AC_SUBST(GLIB_CFLAGS) + AC_SUBST(GLIB_LIBS) +fi + +AM_CONDITIONAL(USE_GLIB, test "x${with_glib}" = "xyes") + +AC_CONFIG_FILES([ \ + Makefile \ + location-batching.pc + ]) + +AC_OUTPUT diff --git a/batching/location-batching.pc.in b/batching/location-batching.pc.in new file mode 100644 index 0000000..da1fbf4 --- /dev/null +++ b/batching/location-batching.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: location-batching +Description: QTI GPS Batching +Version: @VERSION +Libs: -L${libdir} -lbatching +Cflags: -I${includedir}/location-batching diff --git a/batching/location_batching.cpp b/batching/location_batching.cpp new file mode 100644 index 0000000..571da72 --- /dev/null +++ b/batching/location_batching.cpp @@ -0,0 +1,134 @@ +/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "BatchingAdapter.h" +#include "location_interface.h" + +static BatchingAdapter* gBatchingAdapter = NULL; + +static void initialize(); +static void deinitialize(); + +static void addClient(LocationAPI* client, const LocationCallbacks& callbacks); +static void removeClient(LocationAPI* client, removeClientCompleteCallback rmClientCb); +static void requestCapabilities(LocationAPI* client); + +static uint32_t startBatching(LocationAPI* client, BatchingOptions&); +static void stopBatching(LocationAPI* client, uint32_t id); +static void updateBatchingOptions(LocationAPI* client, uint32_t id, BatchingOptions&); +static void getBatchedLocations(LocationAPI* client, uint32_t id, size_t count); + +static const BatchingInterface gBatchingInterface = { + sizeof(BatchingInterface), + initialize, + deinitialize, + addClient, + removeClient, + requestCapabilities, + startBatching, + stopBatching, + updateBatchingOptions, + getBatchedLocations +}; + +#ifndef DEBUG_X86 +extern "C" const BatchingInterface* getBatchingInterface() +#else +const BatchingInterface* getBatchingInterface() +#endif // DEBUG_X86 +{ + return &gBatchingInterface; +} + +static void initialize() +{ + if (NULL == gBatchingAdapter) { + gBatchingAdapter = new BatchingAdapter(); + } +} + +static void deinitialize() +{ + if (NULL != gBatchingAdapter) { + delete gBatchingAdapter; + gBatchingAdapter = NULL; + } +} + +static void addClient(LocationAPI* client, const LocationCallbacks& callbacks) +{ + if (NULL != gBatchingAdapter) { + gBatchingAdapter->addClientCommand(client, callbacks); + } +} + +static void removeClient(LocationAPI* client, removeClientCompleteCallback rmClientCb) +{ + if (NULL != gBatchingAdapter) { + gBatchingAdapter->removeClientCommand(client, rmClientCb); + } +} + +static void requestCapabilities(LocationAPI* client) +{ + if (NULL != gBatchingAdapter) { + gBatchingAdapter->requestCapabilitiesCommand(client); + } +} + +static uint32_t startBatching(LocationAPI* client, BatchingOptions &batchOptions) +{ + if (NULL != gBatchingAdapter) { + return gBatchingAdapter->startBatchingCommand(client, batchOptions); + } else { + return 0; + } +} + +static void stopBatching(LocationAPI* client, uint32_t id) +{ + if (NULL != gBatchingAdapter) { + gBatchingAdapter->stopBatchingCommand(client, id); + } +} + +static void updateBatchingOptions( + LocationAPI* client, uint32_t id, BatchingOptions& batchOptions) +{ + if (NULL != gBatchingAdapter) { + gBatchingAdapter->updateBatchingOptionsCommand(client, id, batchOptions); + } +} + +static void getBatchedLocations(LocationAPI* client, uint32_t id, size_t count) +{ + if (NULL != gBatchingAdapter) { + gBatchingAdapter->getBatchedLocationsCommand(client, id, count); + } +} + |