diff --git a/android/1.0/location_api/GnssAPIClient.cpp b/android/1.0/location_api/GnssAPIClient.cpp index d04939e3..a36d2b48 100644 --- a/android/1.0/location_api/GnssAPIClient.cpp +++ b/android/1.0/location_api/GnssAPIClient.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. +/* 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 @@ -36,7 +36,7 @@ #include "LocationUtil.h" #include "GnssAPIClient.h" -#include +#include namespace android { namespace hardware { @@ -110,9 +110,9 @@ void GnssAPIClient::gnssUpdateCallbacks(const sp& gpsCb, locationCallbacks.gnssNiCb = nullptr; loc_core::ContextBase* context = - loc_core::LocDualContext::getLocFgContext( + loc_core::LocContext::getLocContext( NULL, NULL, - loc_core::LocDualContext::mLocationHalName, false); + loc_core::LocContext::mLocationHalName, false); if (mGnssNiCbIface != nullptr && !context->hasAgpsExtendedCapabilities()) { LOC_LOGD("Registering NI CB"); locationCallbacks.gnssNiCb = [this](uint32_t id, GnssNiNotification gnssNiNotification) { diff --git a/android/1.1/location_api/GnssAPIClient.cpp b/android/1.1/location_api/GnssAPIClient.cpp index fcef4592..89877e5e 100644 --- a/android/1.1/location_api/GnssAPIClient.cpp +++ b/android/1.1/location_api/GnssAPIClient.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. +/* 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 @@ -36,7 +36,7 @@ #include "LocationUtil.h" #include "GnssAPIClient.h" -#include +#include namespace android { namespace hardware { @@ -110,9 +110,9 @@ void GnssAPIClient::gnssUpdateCallbacks(const sp& gpsCb, locationCallbacks.gnssNiCb = nullptr; loc_core::ContextBase* context = - loc_core::LocDualContext::getLocFgContext( + loc_core::LocContext::getLocContext( NULL, NULL, - loc_core::LocDualContext::mLocationHalName, false); + loc_core::LocContext::mLocationHalName, false); if (mGnssNiCbIface != nullptr && !context->hasAgpsExtendedCapabilities()) { LOC_LOGD("Registering NI CB"); locationCallbacks.gnssNiCb = [this](uint32_t id, GnssNiNotification gnssNiNotification) { diff --git a/android/2.0/location_api/GnssAPIClient.cpp b/android/2.0/location_api/GnssAPIClient.cpp index ceb0aa47..44ae284c 100644 --- a/android/2.0/location_api/GnssAPIClient.cpp +++ b/android/2.0/location_api/GnssAPIClient.cpp @@ -36,7 +36,7 @@ #include "LocationUtil.h" #include "GnssAPIClient.h" -#include +#include namespace android { namespace hardware { @@ -110,9 +110,9 @@ void GnssAPIClient::gnssUpdateCallbacks(const sp& gpsCb, locationCallbacks.gnssNiCb = nullptr; loc_core::ContextBase* context = - loc_core::LocDualContext::getLocFgContext( + loc_core::LocContext::getLocContext( NULL, NULL, - loc_core::LocDualContext::mLocationHalName, false); + loc_core::LocContext::mLocationHalName, false); if (mGnssNiCbIface != nullptr && !context->hasAgpsExtendedCapabilities()) { LOC_LOGD("Registering NI CB"); locationCallbacks.gnssNiCb = [this](uint32_t id, GnssNiNotification gnssNiNotification) { diff --git a/batching/Android.mk b/batching/Android.mk new file mode 100644 index 00000000..b08d1558 --- /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 00000000..135f0ed9 --- /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 +#include +#include +#include + +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 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 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 & 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 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(*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(*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 00000000..66f7c5f1 --- /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 +#include +#include +#include + +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 TripSessionStatusMap; + typedef std::map 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 & 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 00000000..ef8011e9 --- /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 00000000..27435c66 --- /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 00000000..da1fbf44 --- /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 00000000..571da725 --- /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); + } +} + diff --git a/core/Android.mk b/core/Android.mk index 97614a17..bd955c1f 100644 --- a/core/Android.mk +++ b/core/Android.mk @@ -21,7 +21,7 @@ LOCAL_SRC_FILES += \ LocApiBase.cpp \ LocAdapterBase.cpp \ ContextBase.cpp \ - LocDualContext.cpp \ + LocContext.cpp \ loc_core_log.cpp \ data-items/DataItemsFactoryProxy.cpp \ SystemStatusOsObserver.cpp \ diff --git a/core/LocAdapterBase.cpp b/core/LocAdapterBase.cpp index cea72fa9..5f6a0c8e 100644 --- a/core/LocAdapterBase.cpp +++ b/core/LocAdapterBase.cpp @@ -46,7 +46,8 @@ LocAdapterBase::LocAdapterBase(const LOC_API_ADAPTER_EVENT_MASK_T mask, LocAdapterProxyBase *adapterProxyBase) : mIsMaster(isMaster), mEvtMask(mask), mContext(context), mLocApi(context->getLocApi()), mLocAdapterProxyBase(adapterProxyBase), - mMsgTask(context->getMsgTask()) + mMsgTask(context->getMsgTask()), + mIsEngineCapabilitiesKnown(ContextBase::sIsEngineCapabilitiesKnown) { mLocApi->addAdapter(this); } @@ -203,4 +204,208 @@ DEFAULT_IMPL(false) void LocAdapterBase:: reportNfwNotificationEvent(GnssNfwNotification& /*notification*/) DEFAULT_IMPL() + +void +LocAdapterBase::geofenceBreachEvent(size_t /*count*/, uint32_t* /*hwIds*/, Location& /*location*/, + GeofenceBreachType /*breachType*/, uint64_t /*timestamp*/) +DEFAULT_IMPL() + +void +LocAdapterBase::geofenceStatusEvent(GeofenceStatusAvailable /*available*/) +DEFAULT_IMPL() + +void +LocAdapterBase::reportLocationsEvent(const Location* /*locations*/, size_t /*count*/, + BatchingMode /*batchingMode*/) +DEFAULT_IMPL() + +void +LocAdapterBase::reportCompletedTripsEvent(uint32_t /*accumulated_distance*/) +DEFAULT_IMPL() + +void +LocAdapterBase::reportBatchStatusChangeEvent(BatchingStatus /*batchStatus*/) +DEFAULT_IMPL() + +void +LocAdapterBase::reportPositionEvent(UlpLocation& /*location*/, + GpsLocationExtended& /*locationExtended*/, + enum loc_sess_status /*status*/, + LocPosTechMask /*loc_technology_mask*/) +DEFAULT_IMPL() + +void +LocAdapterBase::saveClient(LocationAPI* client, const LocationCallbacks& callbacks) +{ + mClientData[client] = callbacks; + updateClientsEventMask(); +} + +void +LocAdapterBase::eraseClient(LocationAPI* client) +{ + auto it = mClientData.find(client); + if (it != mClientData.end()) { + mClientData.erase(it); + } + updateClientsEventMask(); +} + +LocationCallbacks +LocAdapterBase::getClientCallbacks(LocationAPI* client) +{ + LocationCallbacks callbacks = {}; + auto it = mClientData.find(client); + if (it != mClientData.end()) { + callbacks = it->second; + } + return callbacks; +} + +LocationCapabilitiesMask +LocAdapterBase::getCapabilities() +{ + LocationCapabilitiesMask mask = 0; + + if (isEngineCapabilitiesKnown()) { + // time based tracking always supported + mask |= LOCATION_CAPABILITIES_TIME_BASED_TRACKING_BIT; + if (ContextBase::isMessageSupported( + LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_LOCATION_BATCHING)){ + mask |= LOCATION_CAPABILITIES_TIME_BASED_BATCHING_BIT | + LOCATION_CAPABILITIES_DISTANCE_BASED_BATCHING_BIT; + } + if (ContextBase::isMessageSupported(LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_TRACKING)) { + mask |= LOCATION_CAPABILITIES_DISTANCE_BASED_TRACKING_BIT; + } + if (ContextBase::isMessageSupported(LOC_API_ADAPTER_MESSAGE_OUTDOOR_TRIP_BATCHING)) { + mask |= LOCATION_CAPABILITIES_OUTDOOR_TRIP_BATCHING_BIT; + } + // geofence always supported + mask |= LOCATION_CAPABILITIES_GEOFENCE_BIT; + if (ContextBase::gnssConstellationConfig()) { + mask |= LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT; + } + uint32_t carrierCapabilities = ContextBase::getCarrierCapabilities(); + if (carrierCapabilities & LOC_GPS_CAPABILITY_MSB) { + mask |= LOCATION_CAPABILITIES_GNSS_MSB_BIT; + } + if (LOC_GPS_CAPABILITY_MSA & carrierCapabilities) { + mask |= LOCATION_CAPABILITIES_GNSS_MSA_BIT; + } + if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02)) { + mask |= LOCATION_CAPABILITIES_DEBUG_NMEA_BIT; + } + if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) { + mask |= LOCATION_CAPABILITIES_CONSTELLATION_ENABLEMENT_BIT; + } + if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_AGPM_V02)) { + mask |= LOCATION_CAPABILITIES_AGPM_BIT; + } + } else { + LOC_LOGE("%s]: attempt to get capabilities before they are known.", __func__); + } + + return mask; +} + +void +LocAdapterBase::broadcastCapabilities(LocationCapabilitiesMask mask) +{ + for (auto clientData : mClientData) { + if (nullptr != clientData.second.capabilitiesCb) { + clientData.second.capabilitiesCb(mask); + } + } +} + +void +LocAdapterBase::updateClientsEventMask() +DEFAULT_IMPL() + +void +LocAdapterBase::stopClientSessions(LocationAPI* client) +DEFAULT_IMPL() + +void +LocAdapterBase::addClientCommand(LocationAPI* client, const LocationCallbacks& callbacks) +{ + LOC_LOGD("%s]: client %p", __func__, client); + + struct MsgAddClient : public LocMsg { + LocAdapterBase& mAdapter; + LocationAPI* mClient; + const LocationCallbacks mCallbacks; + inline MsgAddClient(LocAdapterBase& adapter, + LocationAPI* client, + const LocationCallbacks& callbacks) : + LocMsg(), + mAdapter(adapter), + mClient(client), + mCallbacks(callbacks) {} + inline virtual void proc() const { + mAdapter.saveClient(mClient, mCallbacks); + } + }; + + sendMsg(new MsgAddClient(*this, client, callbacks)); +} + +void +LocAdapterBase::removeClientCommand(LocationAPI* client, + removeClientCompleteCallback rmClientCb) +{ + LOC_LOGD("%s]: client %p", __func__, client); + + struct MsgRemoveClient : public LocMsg { + LocAdapterBase& mAdapter; + LocationAPI* mClient; + removeClientCompleteCallback mRmClientCb; + inline MsgRemoveClient(LocAdapterBase& adapter, + LocationAPI* client, + removeClientCompleteCallback rmCb) : + LocMsg(), + mAdapter(adapter), + mClient(client), + mRmClientCb(rmCb){} + inline virtual void proc() const { + mAdapter.stopClientSessions(mClient); + mAdapter.eraseClient(mClient); + if (nullptr != mRmClientCb) { + (mRmClientCb)(mClient); + } + } + }; + + sendMsg(new MsgRemoveClient(*this, client, rmClientCb)); +} + +void +LocAdapterBase::requestCapabilitiesCommand(LocationAPI* client) +{ + LOC_LOGD("%s]: ", __func__); + + struct MsgRequestCapabilities : public LocMsg { + LocAdapterBase& mAdapter; + LocationAPI* mClient; + inline MsgRequestCapabilities(LocAdapterBase& adapter, + LocationAPI* client) : + LocMsg(), + mAdapter(adapter), + mClient(client) {} + inline virtual void proc() const { + if (!mAdapter.isEngineCapabilitiesKnown()) { + mAdapter.mPendingMsgs.push_back(new MsgRequestCapabilities(*this)); + return; + } + LocationCallbacks callbacks = mAdapter.getClientCallbacks(mClient); + if (callbacks.capabilitiesCb != nullptr) { + callbacks.capabilitiesCb(mAdapter.getCapabilities()); + } + } + }; + + sendMsg(new MsgRequestCapabilities(*this, client)); +} + } // namespace loc_core diff --git a/core/LocAdapterBase.h b/core/LocAdapterBase.h index 8aa7112f..05b72dbe 100644 --- a/core/LocAdapterBase.h +++ b/core/LocAdapterBase.h @@ -51,8 +51,8 @@ inline bool operator ==(LocationSessionKey const& left, LocationSessionKey const inline bool operator !=(LocationSessionKey const& left, LocationSessionKey const& right) { return left.id != right.id || left.client != right.client; } -typedef std::map LocationSessionMap; -typedef std::map TrackingOptionsMap; + +typedef void (*removeClientCompleteCallback)(LocationAPI* client); namespace loc_core { @@ -62,6 +62,8 @@ class LocAdapterBase { private: static uint32_t mSessionIdCounter; const bool mIsMaster; + bool mIsEngineCapabilitiesKnown = false; + protected: LOC_API_ADAPTER_EVENT_MASK_T mEvtMask; ContextBase* mContext; @@ -71,6 +73,20 @@ protected: inline LocAdapterBase(const MsgTask* msgTask) : mIsMaster(false), mEvtMask(0), mContext(NULL), mLocApi(NULL), mLocAdapterProxyBase(NULL), mMsgTask(msgTask) {} + + /* ==== CLIENT ========================================================================= */ + typedef std::map ClientDataMap; + ClientDataMap mClientData; + std::vector mPendingMsgs; // For temporal storage of msgs before Open is completed + /* ======== UTILITIES ================================================================== */ + void saveClient(LocationAPI* client, const LocationCallbacks& callbacks); + void eraseClient(LocationAPI* client); + LocationCallbacks getClientCallbacks(LocationAPI* client); + LocationCapabilitiesMask getCapabilities(); + void broadcastCapabilities(LocationCapabilitiesMask mask); + virtual void updateClientsEventMask(); + virtual void stopClientSessions(LocationAPI* client); + public: inline virtual ~LocAdapterBase() { mLocApi->removeAdapter(this); } LocAdapterBase(const LOC_API_ADAPTER_EVENT_MASK_T mask, @@ -126,12 +142,11 @@ public: return mIsMaster; } + inline bool isEngineCapabilitiesKnown() { return mIsEngineCapabilitiesKnown;} + inline void setEngineCapabilitiesKnown(bool value) { mIsEngineCapabilitiesKnown = value;} + virtual void handleEngineUpEvent(); virtual void handleEngineDownEvent(); - inline virtual void setPositionModeCommand(LocPosMode& posMode) { - - (void)posMode; - } virtual void reportPositionEvent(const UlpLocation& location, const GpsLocationExtended& locationExtended, enum loc_sess_status status, @@ -174,6 +189,28 @@ public: virtual bool reportGnssAdditionalSystemInfoEvent( GnssAdditionalSystemInfo& additionalSystemInfo); virtual void reportNfwNotificationEvent(GnssNfwNotification& notification); + + virtual void geofenceBreachEvent(size_t count, uint32_t* hwIds, Location& location, + GeofenceBreachType breachType, uint64_t timestamp); + virtual void geofenceStatusEvent(GeofenceStatusAvailable available); + + virtual void reportPositionEvent(UlpLocation &location, + GpsLocationExtended &locationExtended, + enum loc_sess_status status, + LocPosTechMask loc_technology_mask); + + virtual void reportLocationsEvent(const Location* locations, size_t count, + BatchingMode batchingMode); + virtual void reportCompletedTripsEvent(uint32_t accumulated_distance); + virtual void reportBatchStatusChangeEvent(BatchingStatus batchStatus); + + /* ==== CLIENT ========================================================================= */ + /* ======== COMMANDS ====(Called from Client Thread)==================================== */ + void addClientCommand(LocationAPI* client, const LocationCallbacks& callbacks); + void removeClientCommand(LocationAPI* client, + removeClientCompleteCallback rmClientCb); + void requestCapabilitiesCommand(LocationAPI* client); + }; } // namespace loc_core diff --git a/core/LocApiBase.cpp b/core/LocApiBase.cpp index fac81e77..3c67af2e 100644 --- a/core/LocApiBase.cpp +++ b/core/LocApiBase.cpp @@ -35,7 +35,7 @@ #include #include #include -#include +#include namespace loc_core { @@ -197,8 +197,8 @@ bool LocApiBase::isInSession() } bool LocApiBase::needReport(const UlpLocation& ulpLocation, - enum loc_sess_status status, - LocPosTechMask techMask) + enum loc_sess_status status, + LocPosTechMask techMask) { bool reported = false; @@ -563,6 +563,41 @@ void LocApiBase::reportGnssSvTypeConfig(const GnssSvTypeConfig& config) TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportGnssSvTypeConfigEvent(config)); } +void LocApiBase::geofenceBreach(size_t count, uint32_t* hwIds, Location& location, + GeofenceBreachType breachType, uint64_t timestamp) +{ + TO_ALL_LOCADAPTERS(mLocAdapters[i]->geofenceBreachEvent(count, hwIds, location, breachType, + timestamp)); +} + +void LocApiBase::geofenceStatus(GeofenceStatusAvailable available) +{ + TO_ALL_LOCADAPTERS(mLocAdapters[i]->geofenceStatusEvent(available)); +} + +void LocApiBase::reportDBTPosition(UlpLocation &location, GpsLocationExtended &locationExtended, + enum loc_sess_status status, LocPosTechMask loc_technology_mask) +{ + TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportPositionEvent(location, locationExtended, status, + loc_technology_mask)); +} + +void LocApiBase::reportLocations(Location* locations, size_t count, BatchingMode batchingMode) +{ + TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportLocationsEvent(locations, count, batchingMode)); +} + +void LocApiBase::reportCompletedTrips(uint32_t accumulated_distance) +{ + TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportCompletedTripsEvent(accumulated_distance)); +} + +void LocApiBase::handleBatchStatusEvent(BatchingStatus batchStatus) +{ + TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportBatchStatusChangeEvent(batchStatus)); +} + + enum loc_api_adapter_err LocApiBase:: open(LOC_API_ADAPTER_EVENT_MASK_T /*mask*/) DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) @@ -611,10 +646,6 @@ void LocApiBase:: atlCloseStatus(int /*handle*/, int /*is_succ*/) DEFAULT_IMPL() -void LocApiBase:: - setPositionMode(const LocPosMode& /*posMode*/) -DEFAULT_IMPL() - LocationError LocApiBase:: setServerSync(const char* /*url*/, int /*len*/, LocServerType /*type*/) DEFAULT_IMPL(LOCATION_ERROR_SUCCESS) @@ -750,4 +781,101 @@ DEFAULT_IMPL(LOCATION_ERROR_SUCCESS) LocationError LocApiBase::getGnssEnergyConsumed() DEFAULT_IMPL(LOCATION_ERROR_SUCCESS) + + +void LocApiBase::addGeofence(uint32_t /*clientId*/, const GeofenceOption& /*options*/, + const GeofenceInfo& /*info*/, + LocApiResponseData* /*adapterResponseData*/) +DEFAULT_IMPL() + +void LocApiBase::removeGeofence(uint32_t /*hwId*/, uint32_t /*clientId*/, + LocApiResponse* /*adapterResponse*/) +DEFAULT_IMPL() + +void LocApiBase::pauseGeofence(uint32_t /*hwId*/, uint32_t /*clientId*/, + LocApiResponse* /*adapterResponse*/) +DEFAULT_IMPL() + +void LocApiBase::resumeGeofence(uint32_t /*hwId*/, uint32_t /*clientId*/, + LocApiResponse* /*adapterResponse*/) +DEFAULT_IMPL() + +void LocApiBase::modifyGeofence(uint32_t /*hwId*/, uint32_t /*clientId*/, + const GeofenceOption& /*options*/, LocApiResponse* /*adapterResponse*/) +DEFAULT_IMPL() + +void LocApiBase::startTimeBasedTracking(const TrackingOptions& /*options*/, + LocApiResponse* /*adapterResponse*/) +DEFAULT_IMPL() + +void LocApiBase::stopTimeBasedTracking(LocApiResponse* /*adapterResponse*/) +DEFAULT_IMPL() + +void LocApiBase::startDistanceBasedTracking(uint32_t /*sessionId*/, + const LocationOptions& /*options*/, LocApiResponse* /*adapterResponse*/) +DEFAULT_IMPL() + +void LocApiBase::stopDistanceBasedTracking(uint32_t /*sessionId*/, + LocApiResponse* /*adapterResponse*/) +DEFAULT_IMPL() + +void LocApiBase::startBatching(uint32_t /*sessionId*/, const LocationOptions& /*options*/, + uint32_t /*accuracy*/, uint32_t /*timeout*/, LocApiResponse* /*adapterResponse*/) +DEFAULT_IMPL() + +void LocApiBase::stopBatching(uint32_t /*sessionId*/, LocApiResponse* /*adapterResponse*/) +DEFAULT_IMPL() + +LocationError LocApiBase::startOutdoorTripBatchingSync(uint32_t /*tripDistance*/, + uint32_t /*tripTbf*/, uint32_t /*timeout*/) +DEFAULT_IMPL(LOCATION_ERROR_SUCCESS) + +void LocApiBase::startOutdoorTripBatching(uint32_t /*tripDistance*/, uint32_t /*tripTbf*/, + uint32_t /*timeout*/, LocApiResponse* /*adapterResponse*/) +DEFAULT_IMPL() + +void LocApiBase::reStartOutdoorTripBatching(uint32_t /*ongoingTripDistance*/, + uint32_t /*ongoingTripInterval*/, uint32_t /*batchingTimeout,*/, + LocApiResponse* /*adapterResponse*/) +DEFAULT_IMPL() + +LocationError LocApiBase::stopOutdoorTripBatchingSync(bool /*deallocBatchBuffer*/) +DEFAULT_IMPL(LOCATION_ERROR_SUCCESS) + +void LocApiBase::stopOutdoorTripBatching(bool /*deallocBatchBuffer*/, + LocApiResponse* /*adapterResponse*/) +DEFAULT_IMPL() + +LocationError LocApiBase::getBatchedLocationsSync(size_t /*count*/) +DEFAULT_IMPL(LOCATION_ERROR_SUCCESS) + +void LocApiBase::getBatchedLocations(size_t /*count*/, LocApiResponse* /*adapterResponse*/) +DEFAULT_IMPL() + +LocationError LocApiBase::getBatchedTripLocationsSync(size_t /*count*/, + uint32_t /*accumulatedDistance*/) +DEFAULT_IMPL(LOCATION_ERROR_SUCCESS) + +void LocApiBase::getBatchedTripLocations(size_t /*count*/, uint32_t /*accumulatedDistance*/, + LocApiResponse* /*adapterResponse*/) +DEFAULT_IMPL() + +LocationError LocApiBase::queryAccumulatedTripDistanceSync(uint32_t& /*accumulated_trip_distance*/, + uint32_t& /*numOfBatchedPositions*/) +DEFAULT_IMPL(LOCATION_ERROR_SUCCESS) + +void LocApiBase::queryAccumulatedTripDistance( + LocApiResponseData* /*adapterResponseData*/) +DEFAULT_IMPL() + +void LocApiBase::setBatchSize(size_t /*size*/) +DEFAULT_IMPL() + +void LocApiBase::setTripBatchSize(size_t /*size*/) +DEFAULT_IMPL() + +void LocApiBase::addToCallQueue(LocApiResponse* /*adapterResponse*/) +DEFAULT_IMPL() + + } // namespace loc_core diff --git a/core/LocApiBase.h b/core/LocApiBase.h index f0bd5392..afdb83ce 100644 --- a/core/LocApiBase.h +++ b/core/LocApiBase.h @@ -40,6 +40,7 @@ namespace loc_core { class ContextBase; struct LocApiResponse; +template struct LocApiResponseData; int hexcode(char *hexstring, int string_size, const char *data, int data_size); @@ -191,75 +192,50 @@ public: void reportGnssAdditionalSystemInfo(GnssAdditionalSystemInfo& additionalSystemInfo); void sendNfwNotification(GnssNfwNotification& notification); - // downward calls - // All below functions are to be defined by adapter specific modules: - // RPC, QMI, etc. The default implementation is empty. + void geofenceBreach(size_t count, uint32_t* hwIds, Location& location, + GeofenceBreachType breachType, uint64_t timestamp); + void geofenceStatus(GeofenceStatusAvailable available); + void reportDBTPosition(UlpLocation &location, + GpsLocationExtended &locationExtended, + enum loc_sess_status status, + LocPosTechMask loc_technology_mask); + void reportLocations(Location* locations, size_t count, BatchingMode batchingMode); + void reportCompletedTrips(uint32_t accumulated_distance); + void handleBatchStatusEvent(BatchingStatus batchStatus); + // downward calls virtual void* getSibling(); virtual LocApiProxyBase* getLocApiProxy(); virtual void startFix(const LocPosMode& fixCriteria, LocApiResponse* adapterResponse); - virtual void - stopFix(LocApiResponse* adapterResponse); - virtual void - deleteAidingData(const GnssAidingData& data, LocApiResponse* adapterResponse); - - virtual void - injectPosition(double latitude, double longitude, float accuracy); - - virtual void - injectPosition(const GnssLocationInfoNotification &locationInfo, bool onDemandCpi=false); - - virtual void - injectPosition(const Location& location, bool onDemandCpi); - virtual void - setTime(LocGpsUtcTime time, int64_t timeReference, int uncertainty); - - // // TODO:: called from izatapipds - virtual enum loc_api_adapter_err - setXtraData(char* data, int length); - - virtual void - atlOpenStatus(int handle, int is_succ, char* apn, uint32_t apnLen, - AGpsBearerType bear, LocAGpsType agpsType, - LocApnTypeMask mask); - virtual void - atlCloseStatus(int handle, int is_succ); - virtual void - setPositionMode(const LocPosMode& posMode); - virtual LocationError - setServerSync(const char* url, int len, LocServerType type); - virtual LocationError - setServerSync(unsigned int ip, int port, LocServerType type); - virtual void - informNiResponse(GnssNiResponse userResponse, const void* passThroughData); + virtual void stopFix(LocApiResponse* adapterResponse); + virtual void deleteAidingData(const GnssAidingData& data, LocApiResponse* adapterResponse); + virtual void injectPosition(double latitude, double longitude, float accuracy); + virtual void injectPosition(const GnssLocationInfoNotification &locationInfo, + bool onDemandCpi=false); + virtual void injectPosition(const Location& location, bool onDemandCpi); + virtual void setTime(LocGpsUtcTime time, int64_t timeReference, int uncertainty); + virtual enum loc_api_adapter_err setXtraData(char* data, int length); + virtual void atlOpenStatus(int handle, int is_succ, char* apn, uint32_t apnLen, + AGpsBearerType bear, LocAGpsType agpsType, LocApnTypeMask mask); + virtual void atlCloseStatus(int handle, int is_succ); + virtual LocationError setServerSync(const char* url, int len, LocServerType type); + virtual LocationError setServerSync(unsigned int ip, int port, LocServerType type); + virtual void informNiResponse(GnssNiResponse userResponse, const void* passThroughData); virtual LocationError setSUPLVersionSync(GnssConfigSuplVersion version); - virtual enum loc_api_adapter_err - setNMEATypesSync(uint32_t typesMask); + virtual enum loc_api_adapter_err setNMEATypesSync(uint32_t typesMask); virtual LocationError setLPPConfigSync(GnssConfigLppProfile profile); - virtual enum loc_api_adapter_err - setSensorPropertiesSync(bool gyroBiasVarianceRandomWalk_valid, - float gyroBiasVarianceRandomWalk, - bool accelBiasVarianceRandomWalk_valid, - float accelBiasVarianceRandomWalk, - bool angleBiasVarianceRandomWalk_valid, - float angleBiasVarianceRandomWalk, - bool rateBiasVarianceRandomWalk_valid, - float rateBiasVarianceRandomWalk, - bool velocityBiasVarianceRandomWalk_valid, - float velocityBiasVarianceRandomWalk); - virtual enum loc_api_adapter_err - setSensorPerfControlConfigSync(int controlMode, - int accelSamplesPerBatch, - int accelBatchesPerSec, - int gyroSamplesPerBatch, - int gyroBatchesPerSec, - int accelSamplesPerBatchHigh, - int accelBatchesPerSecHigh, - int gyroSamplesPerBatchHigh, - int gyroBatchesPerSecHigh, - int algorithmConfig); + virtual enum loc_api_adapter_err setSensorPropertiesSync( + bool gyroBiasVarianceRandomWalk_valid, float gyroBiasVarianceRandomWalk, + bool accelBiasVarianceRandomWalk_valid, float accelBiasVarianceRandomWalk, + bool angleBiasVarianceRandomWalk_valid, float angleBiasVarianceRandomWalk, + bool rateBiasVarianceRandomWalk_valid, float rateBiasVarianceRandomWalk, + bool velocityBiasVarianceRandomWalk_valid, float velocityBiasVarianceRandomWalk); + virtual enum loc_api_adapter_err setSensorPerfControlConfigSync(int controlMode, + int accelSamplesPerBatch, int accelBatchesPerSec, int gyroSamplesPerBatch, + int gyroBatchesPerSec, int accelSamplesPerBatchHigh, int accelBatchesPerSecHigh, + int gyroSamplesPerBatchHigh, int gyroBatchesPerSecHigh, int algorithmConfig); virtual LocationError - setAGLONASSProtocolSync(GnssConfigAGlonassPositionProtocolMask aGlonassProtocol); + setAGLONASSProtocolSync(GnssConfigAGlonassPositionProtocolMask aGlonassProtocol); virtual LocationError setLPPeProtocolCpSync(GnssConfigLppeControlPlaneMask lppeCP); virtual LocationError setLPPeProtocolUpSync(GnssConfigLppeUserPlaneMask lppeUP); virtual GnssConfigSuplVersion convertSuplVersion(const uint32_t suplVersion); @@ -270,23 +246,11 @@ public: virtual void getWwanZppFix(); virtual void getBestAvailableZppFix(); - virtual void installAGpsCert(const LocDerEncodedCertificate* pData, - size_t length, - uint32_t slotBitMask); - inline virtual void setInSession(bool inSession) { - - (void)inSession; - } - - - void updateEvtMask(); - void updateNmeaMask(uint32_t mask); - + virtual void installAGpsCert(const LocDerEncodedCertificate* pData, size_t length, + uint32_t slotBitMask); virtual LocationError setGpsLockSync(GnssConfigGpsLock lock); virtual void requestForAidingData(GnssAidingDataSvMask svDataMask); - virtual LocationError setXtraVersionCheckSync(uint32_t check); - /* Requests for SV/Constellation Control */ virtual LocationError setBlacklistSvSync(const GnssSvIdConfig& config); virtual void setBlacklistSv(const GnssSvIdConfig& config); @@ -294,12 +258,55 @@ public: virtual void setConstellationControl(const GnssSvTypeConfig& config); virtual void getConstellationControl(); virtual void resetConstellationControl(); - - virtual LocationError setConstrainedTuncMode(bool enabled, - float tuncConstraint, - uint32_t energyBudget); + virtual LocationError setConstrainedTuncMode(bool enabled, float tuncConstraint, + uint32_t energyBudget); virtual LocationError setPositionAssistedClockEstimatorMode(bool enabled); virtual LocationError getGnssEnergyConsumed(); + + virtual void addGeofence(uint32_t clientId, const GeofenceOption& options, + const GeofenceInfo& info, LocApiResponseData* adapterResponseData); + virtual void removeGeofence(uint32_t hwId, uint32_t clientId, LocApiResponse* adapterResponse); + virtual void pauseGeofence(uint32_t hwId, uint32_t clientId, LocApiResponse* adapterResponse); + virtual void resumeGeofence(uint32_t hwId, uint32_t clientId, LocApiResponse* adapterResponse); + virtual void modifyGeofence(uint32_t hwId, uint32_t clientId, const GeofenceOption& options, + LocApiResponse* adapterResponse); + + virtual void startTimeBasedTracking(const TrackingOptions& options, + LocApiResponse* adapterResponse); + virtual void stopTimeBasedTracking(LocApiResponse* adapterResponse); + virtual void startDistanceBasedTracking(uint32_t sessionId, const LocationOptions& options, + LocApiResponse* adapterResponse); + virtual void stopDistanceBasedTracking(uint32_t sessionId, + LocApiResponse* adapterResponse = nullptr); + virtual void startBatching(uint32_t sessionId, const LocationOptions& options, + uint32_t accuracy, uint32_t timeout, LocApiResponse* adapterResponse); + virtual void stopBatching(uint32_t sessionId, LocApiResponse* adapterResponse); + virtual LocationError startOutdoorTripBatchingSync(uint32_t tripDistance, + uint32_t tripTbf, uint32_t timeout); + virtual void startOutdoorTripBatching(uint32_t tripDistance, + uint32_t tripTbf, uint32_t timeout, LocApiResponse* adapterResponse); + virtual void reStartOutdoorTripBatching(uint32_t ongoingTripDistance, + uint32_t ongoingTripInterval, uint32_t batchingTimeout, + LocApiResponse* adapterResponse); + virtual LocationError stopOutdoorTripBatchingSync(bool deallocBatchBuffer = true); + virtual void stopOutdoorTripBatching(bool deallocBatchBuffer = true, + LocApiResponse* adapterResponse = nullptr); + virtual LocationError getBatchedLocationsSync(size_t count); + virtual void getBatchedLocations(size_t count, LocApiResponse* adapterResponse); + virtual LocationError getBatchedTripLocationsSync(size_t count, uint32_t accumulatedDistance); + virtual void getBatchedTripLocations(size_t count, uint32_t accumulatedDistance, + LocApiResponse* adapterResponse); + virtual LocationError queryAccumulatedTripDistanceSync(uint32_t &accumulated_trip_distance, + uint32_t &numOfBatchedPositions); + virtual void queryAccumulatedTripDistance( + LocApiResponseData* adapterResponseData); + virtual void setBatchSize(size_t size); + virtual void setTripBatchSize(size_t size); + virtual void addToCallQueue(LocApiResponse* adapterResponse); + + void updateEvtMask(); + void updateNmeaMask(uint32_t mask); + }; typedef LocApiBase* (getLocApi_t)(LOC_API_ADAPTER_EVENT_MASK_T exMask, diff --git a/core/LocContext.cpp b/core/LocContext.cpp new file mode 100644 index 00000000..18d3f2d1 --- /dev/null +++ b/core/LocContext.cpp @@ -0,0 +1,98 @@ +/* Copyright (c) 2011-2014, 2016-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_Ctx" + +#include +#include +#include +#include +#include +#include + +namespace loc_core { + +const MsgTask* LocContext::mMsgTask = NULL; +ContextBase* LocContext::mContext = NULL; +// the name must be shorter than 15 chars +const char* LocContext::mLocationHalName = "Loc_hal_worker"; +#ifndef USE_GLIB +const char* LocContext::mLBSLibName = "liblbs_core.so"; +#else +const char* LocContext::mLBSLibName = "liblbs_core.so.1"; +#endif + +pthread_mutex_t LocContext::mGetLocContextMutex = PTHREAD_MUTEX_INITIALIZER; + +const MsgTask* LocContext::getMsgTask(LocThread::tCreate tCreator, + const char* name, bool joinable) +{ + if (NULL == mMsgTask) { + mMsgTask = new MsgTask(tCreator, name, joinable); + } + return mMsgTask; +} + +inline +const MsgTask* LocContext::getMsgTask(const char* name, bool joinable) { + return getMsgTask((LocThread::tCreate)NULL, name, joinable); +} + +ContextBase* LocContext::getLocContext(LocThread::tCreate tCreator, + LocMsg* firstMsg, const char* name, bool joinable) +{ + pthread_mutex_lock(&LocContext::mGetLocContextMutex); + LOC_LOGD("%s:%d]: querying ContextBase with tCreator", __func__, __LINE__); + if (NULL == mContext) { + LOC_LOGD("%s:%d]: creating msgTask with tCreator", __func__, __LINE__); + const MsgTask* msgTask = getMsgTask(tCreator, name, joinable); + mContext = new LocContext(msgTask); + } + pthread_mutex_unlock(&LocContext::mGetLocContextMutex); + + if (firstMsg) { + mContext->sendMsg(firstMsg); + } + + return mContext; +} + +void LocContext :: injectFeatureConfig(ContextBase *curContext) +{ + LOC_LOGD("%s:%d]: Calling LBSProxy (%p) to inject feature config", + __func__, __LINE__, ((LocContext *)curContext)->mLBSProxy); + ((LocContext *)curContext)->mLBSProxy->injectFeatureConfig(curContext); +} + +LocContext::LocContext(const MsgTask* msgTask) : + ContextBase(msgTask, 0, mLBSLibName) +{ +} + +} diff --git a/core/LocDualContext.h b/core/LocContext.h similarity index 66% rename from core/LocDualContext.h rename to core/LocContext.h index edfbfb7d..fb7d009d 100644 --- a/core/LocDualContext.h +++ b/core/LocContext.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2014, 2017 The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2014, 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 @@ -26,8 +26,8 @@ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ -#ifndef __LOC_ENG_CONTEXT__ -#define __LOC_ENG_CONTEXT__ +#ifndef __LOC_CONTEXT__ +#define __LOC_CONTEXT__ #include #include @@ -36,35 +36,26 @@ namespace loc_core { -class LocDualContext : public ContextBase { +class LocContext : public ContextBase { static const MsgTask* mMsgTask; - static ContextBase* mFgContext; - static ContextBase* mBgContext; + static ContextBase* mContext; static const MsgTask* getMsgTask(LocThread::tCreate tCreator, const char* name, bool joinable = true); static const MsgTask* getMsgTask(const char* name, bool joinable = true); static pthread_mutex_t mGetLocContextMutex; protected: - LocDualContext(const MsgTask* msgTask, - LOC_API_ADAPTER_EVENT_MASK_T exMask); - inline virtual ~LocDualContext() {} + LocContext(const MsgTask* msgTask); + inline virtual ~LocContext() {} public: static const char* mLBSLibName; - static const LOC_API_ADAPTER_EVENT_MASK_T mFgExclMask; - static const LOC_API_ADAPTER_EVENT_MASK_T mBgExclMask; static const char* mLocationHalName; - static ContextBase* getLocFgContext(LocThread::tCreate tCreator, LocMsg* firstMsg, + static ContextBase* getLocContext(LocThread::tCreate tCreator, LocMsg* firstMsg, const char* name, bool joinable = true); - inline static ContextBase* getLocFgContext(const char* name, bool joinable = true) { - return getLocFgContext(NULL, NULL, name, joinable); - } - static ContextBase* getLocBgContext(LocThread::tCreate tCreator, LocMsg* firstMsg, - const char* name, bool joinable = true); - inline static ContextBase* getLocBgContext(const char* name, bool joinable = true) { - return getLocBgContext(NULL, NULL, name, joinable); + inline static ContextBase* getLocContext(const char* name, bool joinable = true) { + return getLocContext(NULL, NULL, name, joinable); } static void injectFeatureConfig(ContextBase *context); @@ -72,4 +63,4 @@ public: } -#endif //__LOC_ENG_CONTEXT__ +#endif //__LOC_CONTEXT__ diff --git a/core/LocDualContext.cpp b/core/LocDualContext.cpp deleted file mode 100644 index 9851d610..00000000 --- a/core/LocDualContext.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/* Copyright (c) 2011-2014, 2016-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_NDEBUG 0 -#define LOG_TAG "LocSvc_DualCtx" - -#include -#include -#include -#include -#include -#include - -namespace loc_core { - -// nothing exclude for foreground -const LOC_API_ADAPTER_EVENT_MASK_T -LocDualContext::mFgExclMask = 0; -// excluded events for background clients -const LOC_API_ADAPTER_EVENT_MASK_T -LocDualContext::mBgExclMask = - (LOC_API_ADAPTER_BIT_SATELLITE_REPORT | - LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT | - LOC_API_ADAPTER_BIT_NMEA_POSITION_REPORT | - LOC_API_ADAPTER_BIT_IOCTL_REPORT | - LOC_API_ADAPTER_BIT_STATUS_REPORT | - LOC_API_ADAPTER_BIT_GEOFENCE_GEN_ALERT | - LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT); - -const MsgTask* LocDualContext::mMsgTask = NULL; -ContextBase* LocDualContext::mFgContext = NULL; -ContextBase* LocDualContext::mBgContext = NULL; -// the name must be shorter than 15 chars -const char* LocDualContext::mLocationHalName = "Loc_hal_worker"; -#ifndef USE_GLIB -const char* LocDualContext::mLBSLibName = "liblbs_core.so"; -#else -const char* LocDualContext::mLBSLibName = "liblbs_core.so.1"; -#endif - -pthread_mutex_t LocDualContext::mGetLocContextMutex = PTHREAD_MUTEX_INITIALIZER; - -const MsgTask* LocDualContext::getMsgTask(LocThread::tCreate tCreator, - const char* name, bool joinable) -{ - if (NULL == mMsgTask) { - mMsgTask = new MsgTask(tCreator, name, joinable); - } - return mMsgTask; -} - -inline -const MsgTask* LocDualContext::getMsgTask(const char* name, bool joinable) { - return getMsgTask((LocThread::tCreate)NULL, name, joinable); -} - -ContextBase* LocDualContext::getLocFgContext(LocThread::tCreate tCreator, - LocMsg* firstMsg, const char* name, bool joinable) -{ - pthread_mutex_lock(&LocDualContext::mGetLocContextMutex); - LOC_LOGD("%s:%d]: querying ContextBase with tCreator", __func__, __LINE__); - if (NULL == mFgContext) { - LOC_LOGD("%s:%d]: creating msgTask with tCreator", __func__, __LINE__); - const MsgTask* msgTask = getMsgTask(tCreator, name, joinable); - mFgContext = new LocDualContext(msgTask, - mFgExclMask); - } - pthread_mutex_unlock(&LocDualContext::mGetLocContextMutex); - - if (firstMsg) { - mFgContext->sendMsg(firstMsg); - } - - return mFgContext; -} - -ContextBase* LocDualContext::getLocBgContext(LocThread::tCreate tCreator, - LocMsg* firstMsg, const char* name, bool joinable) -{ - pthread_mutex_lock(&LocDualContext::mGetLocContextMutex); - LOC_LOGD("%s:%d]: querying ContextBase with tCreator", __func__, __LINE__); - if (NULL == mBgContext) { - LOC_LOGD("%s:%d]: creating msgTask with tCreator", __func__, __LINE__); - const MsgTask* msgTask = getMsgTask(tCreator, name, joinable); - mBgContext = new LocDualContext(msgTask, - mBgExclMask); - } - pthread_mutex_unlock(&LocDualContext::mGetLocContextMutex); - - if (firstMsg) { - mBgContext->sendMsg(firstMsg); - } - - return mBgContext; -} - -void LocDualContext :: injectFeatureConfig(ContextBase *curContext) -{ - LOC_LOGD("%s:%d]: Calling LBSProxy (%p) to inject feature config", - __func__, __LINE__, ((LocDualContext *)curContext)->mLBSProxy); - ((LocDualContext *)curContext)->mLBSProxy->injectFeatureConfig(curContext); -} - -LocDualContext::LocDualContext(const MsgTask* msgTask, - LOC_API_ADAPTER_EVENT_MASK_T exMask) : - ContextBase(msgTask, exMask, mLBSLibName) -{ -} - -} diff --git a/core/Makefile.am b/core/Makefile.am index 53059e41..ffd93579 100644 --- a/core/Makefile.am +++ b/core/Makefile.am @@ -15,7 +15,7 @@ libloc_core_la_h_sources = \ LocApiBase.h \ LocAdapterBase.h \ ContextBase.h \ - LocDualContext.h \ + LocContext.h \ LBSProxyBase.h \ loc_core_log.h \ LocAdapterProxyBase.h \ @@ -34,7 +34,7 @@ libloc_core_la_c_sources = \ LocApiBase.cpp \ LocAdapterBase.cpp \ ContextBase.cpp \ - LocDualContext.cpp \ + LocContext.cpp \ loc_core_log.cpp \ data-items/DataItemsFactoryProxy.cpp \ SystemStatusOsObserver.cpp \ diff --git a/etc/Android.mk b/etc/Android.mk index d9eb0e10..22ca2f71 100644 --- a/etc/Android.mk +++ b/etc/Android.mk @@ -1,12 +1,21 @@ LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) +include $(CLEAR_VARS) LOCAL_MODULE := gps.conf +LOCAL_VENDOR_MODULE := true LOCAL_MODULE_TAGS := optional LOCAL_MODULE_CLASS := ETC -LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/etc/ LOCAL_SRC_FILES := gps.conf - +LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC) +include $(BUILD_PREBUILT) + +include $(CLEAR_VARS) +LOCAL_MODULE := flp.conf +LOCAL_VENDOR_MODULE := true +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_CLASS := ETC +LOCAL_SRC_FILES := flp.conf +LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC) include $(BUILD_PREBUILT) diff --git a/etc/flp.conf b/etc/flp.conf new file mode 100644 index 00000000..65d54d38 --- /dev/null +++ b/etc/flp.conf @@ -0,0 +1,60 @@ +################################### +##### FLP settings ##### +################################### + +################################### +# FLP BATCH SIZE +################################### +# The number of batched locations +# requested to modem. The desired number +# defined below may not be satisfied, as +# the modem can only return the number +# of batched locations that can be allocated, +# which is limited by memory. The default +# batch size defined as 20 as below. +BATCH_SIZE=20 + +################################### +# FLP OUTDOOR TRIP BATCH SIZE +################################### +# The number of batched locations +# requested to modem for outdoor +# trip batching. The desired number +# defined below may not be satisfied, as +# the modem can only return the number +# of batched locations that can be allocated, +# which is limited by memory. The default +# trip batch size defined as 600 as below. +OUTDOOR_TRIP_BATCH_SIZE=600 + +################################### +# FLP BATCHING SESSION TIMEOUT +################################### +# Duration with which batch session timeout +# happens in milliseconds. If not specified +# or set to zero, batching session timeout +# defaults to 20 seconds by the modem. +# BATCH_SESSION_TIMEOUT=20000 + +################################### +# FLP BATCHING ACCURACY +################################### +# Set to one of the defined values below +# to define the accuracy of batching. +# If not specified, accuracy defaults +# to LOW. +# FLP BATCHING ACCURACY values: +# Low accuracy = 0 +# Medium accuracy = 1 +# High accuracy = 2 +ACCURACY=1 + +#################################### +# By default if network fixes are not sensor assisted +# these fixes must be dropped. This parameter adds an exception +# for targets where there is no PDR and we still want to +# report out network fixes +# 0: MUST NOT ALLOW NETWORK FIXES +# 1: ALLOW NETWORK FIXES +#################################### +ALLOW_NETWORK_FIXES = 0 diff --git a/etc/gps.conf b/etc/gps.conf index e5be3858..82a7b3ca 100644 --- a/etc/gps.conf +++ b/etc/gps.conf @@ -54,9 +54,8 @@ SUPL_VER=0x10000 # MSB = 0x02 # MSA = 0x04 # ON_DEMAND_TIME = 0x10 -# GEOFENCE = 0x20 -# default = ON_DEMAND_TIME | MSA | MSB | SCHEDULING | GEOFENCE -CAPABILITIES=0x37 +# default = ON_DEMAND_TIME | MSA | MSB | SCHEDULING +CAPABILITIES=0x17 # Accuracy threshold for intermediate positions # less accurate positions are ignored, 0 for passing all positions diff --git a/geofence/Android.mk b/geofence/Android.mk new file mode 100644 index 00000000..6e9e8706 --- /dev/null +++ b/geofence/Android.mk @@ -0,0 +1,36 @@ +ifneq ($(BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE),) +ifneq ($(BUILD_TINY_ANDROID),true) + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := libgeofencing +LOCAL_VENDOR_MODULE := true +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES:= \ + GeofenceAdapter.cpp \ + location_geofence.cpp + +LOCAL_SHARED_LIBRARIES := \ + libutils \ + libcutils \ + libgps.utils \ + liblog \ + libloc_core \ + liblbs_core + +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/geofence/GeofenceAdapter.cpp b/geofence/GeofenceAdapter.cpp new file mode 100644 index 00000000..b8746fbc --- /dev/null +++ b/geofence/GeofenceAdapter.cpp @@ -0,0 +1,867 @@ +/* Copyright (c) 2013-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_TAG "LocSvc_GeofenceAdapter" + +#include +#include "loc_log.h" +#include +#include + +using namespace loc_core; + +GeofenceAdapter::GeofenceAdapter() : + LocAdapterBase(0, + LocContext::getLocContext( + NULL, + NULL, + LocContext::mLocationHalName, + false), + true /*isMaster*/) +{ + LOC_LOGD("%s]: Constructor", __func__); +} + +void +GeofenceAdapter::stopClientSessions(LocationAPI* client) +{ + LOC_LOGD("%s]: client %p", __func__, client); + + + for (auto it = mGeofenceIds.begin(); it != mGeofenceIds.end();) { + uint32_t hwId = it->second; + GeofenceKey key(it->first); + if (client == key.client) { + it = mGeofenceIds.erase(it); + mLocApi->removeGeofence(hwId, key.id, + new LocApiResponse(*getContext(), + [this, hwId] (LocationError err) { + if (LOCATION_ERROR_SUCCESS == err) { + auto it2 = mGeofences.find(hwId); + if (it2 != mGeofences.end()) { + mGeofences.erase(it2); + } else { + LOC_LOGE("%s]:geofence item to erase not found. hwId %u", __func__, hwId); + } + } + })); + continue; + } + ++it; // increment only when not erasing an iterator + } + +} + +void +GeofenceAdapter::updateClientsEventMask() +{ + LOC_API_ADAPTER_EVENT_MASK_T mask = 0; + for (auto it=mClientData.begin(); it != mClientData.end(); ++it) { + if (it->second.geofenceBreachCb != nullptr) { + mask |= LOC_API_ADAPTER_BIT_BATCHED_GENFENCE_BREACH_REPORT; + mask |= LOC_API_ADAPTER_BIT_REPORT_GENFENCE_DWELL; + } + if (it->second.geofenceStatusCb != nullptr) { + mask |= LOC_API_ADAPTER_BIT_GEOFENCE_GEN_ALERT; + } + } + updateEvtMask(mask, LOC_REGISTRATION_MASK_SET); +} + +LocationError +GeofenceAdapter::getHwIdFromClient(LocationAPI* client, uint32_t clientId, uint32_t& hwId) +{ + GeofenceKey key(client, clientId); + auto it = mGeofenceIds.find(key); + if (it != mGeofenceIds.end()) { + hwId = it->second; + return LOCATION_ERROR_SUCCESS; + } + return LOCATION_ERROR_ID_UNKNOWN; +} + +LocationError +GeofenceAdapter::getGeofenceKeyFromHwId(uint32_t hwId, GeofenceKey& key) +{ + auto it = mGeofences.find(hwId); + if (it != mGeofences.end()) { + key = it->second.key; + return LOCATION_ERROR_SUCCESS; + } + return LOCATION_ERROR_ID_UNKNOWN; +} + +void +GeofenceAdapter::handleEngineUpEvent() +{ + struct MsgSSREvent : public LocMsg { + GeofenceAdapter& mAdapter; + inline MsgSSREvent(GeofenceAdapter& adapter) : + LocMsg(), + mAdapter(adapter) {} + virtual void proc() const { + mAdapter.setEngineCapabilitiesKnown(true); + mAdapter.broadcastCapabilities(mAdapter.getCapabilities()); + mAdapter.restartGeofences(); + for (auto msg: mAdapter.mPendingMsgs) { + mAdapter.sendMsg(msg); + } + mAdapter.mPendingMsgs.clear(); + } + }; + + sendMsg(new MsgSSREvent(*this)); +} + +void +GeofenceAdapter::restartGeofences() +{ + if (mGeofences.empty()) { + return; + } + + GeofencesMap oldGeofences(mGeofences); + mGeofences.clear(); + mGeofenceIds.clear(); + + for (auto it = oldGeofences.begin(); it != oldGeofences.end(); it++) { + GeofenceObject object = it->second; + GeofenceOption options = {sizeof(GeofenceOption), + object.breachMask, + object.responsiveness, + object.dwellTime}; + GeofenceInfo info = {sizeof(GeofenceInfo), + object.latitude, + object.longitude, + object.radius}; + mLocApi->addGeofence(object.key.id, + options, + info, + new LocApiResponseData(*getContext(), + [this, object, options, info] (LocationError err, LocApiGeofenceData data) { + if (LOCATION_ERROR_SUCCESS == err) { + if (true == object.paused) { + mLocApi->pauseGeofence(data.hwId, object.key.id, + new LocApiResponse(*getContext(), [] (LocationError err ) {})); + } + saveGeofenceItem(object.key.client, object.key.id, data.hwId, options, info); + } + })); + } +} + +void +GeofenceAdapter::reportResponse(LocationAPI* client, size_t count, LocationError* errs, + uint32_t* ids) +{ + IF_LOC_LOGD { + std::string idsString = "["; + std::string errsString = "["; + if (NULL != ids && NULL != errs) { + for (size_t i=0; i < count; ++i) { + idsString += std::to_string(ids[i]) + " "; + errsString += std::to_string(errs[i]) + " "; + } + } + idsString += "]"; + errsString += "]"; + + LOC_LOGD("%s]: client %p ids %s errs %s", + __func__, client, idsString.c_str(), errsString.c_str()); + } + + auto it = mClientData.find(client); + if (it != mClientData.end() && it->second.collectiveResponseCb != nullptr) { + it->second.collectiveResponseCb(count, errs, ids); + } else { + LOC_LOGE("%s]: client %p response not found in info", __func__, client); + } +} + +uint32_t* +GeofenceAdapter::addGeofencesCommand(LocationAPI* client, size_t count, GeofenceOption* options, + GeofenceInfo* infos) +{ + LOC_LOGD("%s]: client %p count %zu", __func__, client, count); + + struct MsgAddGeofences : public LocMsg { + GeofenceAdapter& mAdapter; + LocApiBase& mApi; + LocationAPI* mClient; + size_t mCount; + uint32_t* mIds; + GeofenceOption* mOptions; + GeofenceInfo* mInfos; + inline MsgAddGeofences(GeofenceAdapter& adapter, + LocApiBase& api, + LocationAPI* client, + size_t count, + uint32_t* ids, + GeofenceOption* options, + GeofenceInfo* infos) : + LocMsg(), + mAdapter(adapter), + mApi(api), + mClient(client), + mCount(count), + mIds(ids), + mOptions(options), + mInfos(infos) {} + inline virtual void proc() const { + LocationError* errs = new LocationError[mCount]; + if (nullptr == errs) { + LOC_LOGE("%s]: new failed to allocate errs", __func__); + return; + } + for (size_t i=0; i < mCount; ++i) { + if (NULL == mIds || NULL == mOptions || NULL == mInfos) { + errs[i] = LOCATION_ERROR_INVALID_PARAMETER; + } else { + mApi.addGeofence(mIds[i], + mOptions[i], + mInfos[i], + new LocApiResponseData(*mAdapter.getContext(), + [&mAdapter = mAdapter, mOptions = mOptions, mClient = mClient, + mCount = mCount, mIds = mIds, mInfos = mInfos, errs, i] + (LocationError err, LocApiGeofenceData data) { + if (LOCATION_ERROR_SUCCESS == err) { + mAdapter.saveGeofenceItem(mClient, + mIds[i], + data.hwId, + mOptions[i], + mInfos[i]); + } + errs[i] = err; + + // Send aggregated response on last item and cleanup + if (i == mCount-1) { + mAdapter.reportResponse(mClient, mCount, errs, mIds); + delete[] errs; + delete[] mIds; + delete[] mOptions; + delete[] mInfos; + } + })); + } + } + } + }; + + if (0 == count) { + return NULL; + } + uint32_t* ids = new uint32_t[count]; + if (nullptr == ids) { + LOC_LOGE("%s]: new failed to allocate ids", __func__); + return NULL; + } + if (NULL != ids) { + for (size_t i=0; i < count; ++i) { + ids[i] = generateSessionId(); + } + } + GeofenceOption* optionsCopy; + if (options == NULL) { + optionsCopy = NULL; + } else { + optionsCopy = new GeofenceOption[count]; + if (nullptr == optionsCopy) { + LOC_LOGE("%s]: new failed to allocate optionsCopy", __func__); + return NULL; + } + COPY_IF_NOT_NULL(optionsCopy, options, count); + } + GeofenceInfo* infosCopy; + if (infos == NULL) { + infosCopy = NULL; + } else { + infosCopy = new GeofenceInfo[count]; + if (nullptr == infosCopy) { + LOC_LOGE("%s]: new failed to allocate infosCopy", __func__); + return NULL; + } + COPY_IF_NOT_NULL(infosCopy, infos, count); + } + + sendMsg(new MsgAddGeofences(*this, *mLocApi, client, count, ids, optionsCopy, infosCopy)); + return ids; +} + +void +GeofenceAdapter::removeGeofencesCommand(LocationAPI* client, size_t count, uint32_t* ids) +{ + LOC_LOGD("%s]: client %p count %zu", __func__, client, count); + + struct MsgRemoveGeofences : public LocMsg { + GeofenceAdapter& mAdapter; + LocApiBase& mApi; + LocationAPI* mClient; + size_t mCount; + uint32_t* mIds; + inline MsgRemoveGeofences(GeofenceAdapter& adapter, + LocApiBase& api, + LocationAPI* client, + size_t count, + uint32_t* ids) : + LocMsg(), + mAdapter(adapter), + mApi(api), + mClient(client), + mCount(count), + mIds(ids) {} + inline virtual void proc() const { + LocationError* errs = new LocationError[mCount]; + if (nullptr == errs) { + LOC_LOGE("%s]: new failed to allocate errs", __func__); + return; + } + for (size_t i=0; i < mCount; ++i) { + mApi.addToCallQueue(new LocApiResponse(*mAdapter.getContext(), + [&mAdapter = mAdapter, mCount = mCount, mClient = mClient, mIds = mIds, + &mApi = mApi, errs, i] (LocationError err ) { + uint32_t hwId = 0; + errs[i] = mAdapter.getHwIdFromClient(mClient, mIds[i], hwId); + if (LOCATION_ERROR_SUCCESS == errs[i]) { + mApi.removeGeofence(hwId, mIds[i], + new LocApiResponse(*mAdapter.getContext(), + [&mAdapter = mAdapter, mCount = mCount, mClient = mClient, mIds = mIds, + hwId, errs, i] (LocationError err ) { + if (LOCATION_ERROR_SUCCESS == err) { + mAdapter.removeGeofenceItem(hwId); + } + errs[i] = err; + + // Send aggregated response on last item and cleanup + if (i == mCount-1) { + mAdapter.reportResponse(mClient, mCount, errs, mIds); + delete[] errs; + delete[] mIds; + } + })); + } else { + // Send aggregated response on last item and cleanup + if (i == mCount-1) { + mAdapter.reportResponse(mClient, mCount, errs, mIds); + delete[] errs; + delete[] mIds; + } + } + })); + } + } + }; + + if (0 == count) { + return; + } + uint32_t* idsCopy = new uint32_t[count]; + if (nullptr == idsCopy) { + LOC_LOGE("%s]: new failed to allocate idsCopy", __func__); + return; + } + COPY_IF_NOT_NULL(idsCopy, ids, count); + sendMsg(new MsgRemoveGeofences(*this, *mLocApi, client, count, idsCopy)); +} + +void +GeofenceAdapter::pauseGeofencesCommand(LocationAPI* client, size_t count, uint32_t* ids) +{ + LOC_LOGD("%s]: client %p count %zu", __func__, client, count); + + struct MsgPauseGeofences : public LocMsg { + GeofenceAdapter& mAdapter; + LocApiBase& mApi; + LocationAPI* mClient; + size_t mCount; + uint32_t* mIds; + inline MsgPauseGeofences(GeofenceAdapter& adapter, + LocApiBase& api, + LocationAPI* client, + size_t count, + uint32_t* ids) : + LocMsg(), + mAdapter(adapter), + mApi(api), + mClient(client), + mCount(count), + mIds(ids) {} + inline virtual void proc() const { + LocationError* errs = new LocationError[mCount]; + if (nullptr == errs) { + LOC_LOGE("%s]: new failed to allocate errs", __func__); + return; + } + for (size_t i=0; i < mCount; ++i) { + mApi.addToCallQueue(new LocApiResponse(*mAdapter.getContext(), + [&mAdapter = mAdapter, mCount = mCount, mClient = mClient, mIds = mIds, + &mApi = mApi, errs, i] (LocationError err ) { + uint32_t hwId = 0; + errs[i] = mAdapter.getHwIdFromClient(mClient, mIds[i], hwId); + if (LOCATION_ERROR_SUCCESS == errs[i]) { + mApi.pauseGeofence(hwId, mIds[i], new LocApiResponse(*mAdapter.getContext(), + [&mAdapter = mAdapter, mCount = mCount, mClient = mClient, mIds = mIds, + hwId, errs, i] (LocationError err ) { + if (LOCATION_ERROR_SUCCESS == err) { + mAdapter.pauseGeofenceItem(hwId); + } + errs[i] = err; + + // Send aggregated response on last item and cleanup + if (i == mCount-1) { + mAdapter.reportResponse(mClient, mCount, errs, mIds); + delete[] errs; + delete[] mIds; + } + })); + } else { + // Send aggregated response on last item and cleanup + if (i == mCount-1) { + mAdapter.reportResponse(mClient, mCount, errs, mIds); + delete[] errs; + delete[] mIds; + } + } + })); + } + } + }; + + if (0 == count) { + return; + } + uint32_t* idsCopy = new uint32_t[count]; + if (nullptr == idsCopy) { + LOC_LOGE("%s]: new failed to allocate idsCopy", __func__); + return; + } + COPY_IF_NOT_NULL(idsCopy, ids, count); + sendMsg(new MsgPauseGeofences(*this, *mLocApi, client, count, idsCopy)); +} + +void +GeofenceAdapter::resumeGeofencesCommand(LocationAPI* client, size_t count, uint32_t* ids) +{ + LOC_LOGD("%s]: client %p count %zu", __func__, client, count); + + struct MsgResumeGeofences : public LocMsg { + GeofenceAdapter& mAdapter; + LocApiBase& mApi; + LocationAPI* mClient; + size_t mCount; + uint32_t* mIds; + inline MsgResumeGeofences(GeofenceAdapter& adapter, + LocApiBase& api, + LocationAPI* client, + size_t count, + uint32_t* ids) : + LocMsg(), + mAdapter(adapter), + mApi(api), + mClient(client), + mCount(count), + mIds(ids) {} + inline virtual void proc() const { + LocationError* errs = new LocationError[mCount]; + if (nullptr == errs) { + LOC_LOGE("%s]: new failed to allocate errs", __func__); + return; + } + for (size_t i=0; i < mCount; ++i) { + mApi.addToCallQueue(new LocApiResponse(*mAdapter.getContext(), + [&mAdapter = mAdapter, mCount = mCount, mClient = mClient, mIds = mIds, + &mApi = mApi, errs, i] (LocationError err ) { + uint32_t hwId = 0; + errs[i] = mAdapter.getHwIdFromClient(mClient, mIds[i], hwId); + if (LOCATION_ERROR_SUCCESS == errs[i]) { + mApi.resumeGeofence(hwId, mIds[i], + new LocApiResponse(*mAdapter.getContext(), + [&mAdapter = mAdapter, mCount = mCount, mClient = mClient, hwId, + errs, mIds = mIds, i] (LocationError err ) { + if (LOCATION_ERROR_SUCCESS == err) { + errs[i] = err; + + mAdapter.resumeGeofenceItem(hwId); + // Send aggregated response on last item and cleanup + if (i == mCount-1) { + mAdapter.reportResponse(mClient, mCount, errs, mIds); + delete[] errs; + delete[] mIds; + } + } + })); + } else { + // Send aggregated response on last item and cleanup + if (i == mCount-1) { + mAdapter.reportResponse(mClient, mCount, errs, mIds); + delete[] errs; + delete[] mIds; + } + } + })); + } + } + }; + + if (0 == count) { + return; + } + uint32_t* idsCopy = new uint32_t[count]; + if (nullptr == idsCopy) { + LOC_LOGE("%s]: new failed to allocate idsCopy", __func__); + return; + } + COPY_IF_NOT_NULL(idsCopy, ids, count); + sendMsg(new MsgResumeGeofences(*this, *mLocApi, client, count, idsCopy)); +} + +void +GeofenceAdapter::modifyGeofencesCommand(LocationAPI* client, size_t count, uint32_t* ids, + GeofenceOption* options) +{ + LOC_LOGD("%s]: client %p count %zu", __func__, client, count); + + struct MsgModifyGeofences : public LocMsg { + GeofenceAdapter& mAdapter; + LocApiBase& mApi; + LocationAPI* mClient; + size_t mCount; + uint32_t* mIds; + GeofenceOption* mOptions; + inline MsgModifyGeofences(GeofenceAdapter& adapter, + LocApiBase& api, + LocationAPI* client, + size_t count, + uint32_t* ids, + GeofenceOption* options) : + LocMsg(), + mAdapter(adapter), + mApi(api), + mClient(client), + mCount(count), + mIds(ids), + mOptions(options) {} + inline virtual void proc() const { + LocationError* errs = new LocationError[mCount]; + if (nullptr == errs) { + LOC_LOGE("%s]: new failed to allocate errs", __func__); + return; + } + for (size_t i=0; i < mCount; ++i) { + if (NULL == mIds || NULL == mOptions) { + errs[i] = LOCATION_ERROR_INVALID_PARAMETER; + } else { + mApi.addToCallQueue(new LocApiResponse(*mAdapter.getContext(), + [&mAdapter = mAdapter, mCount = mCount, mClient = mClient, mIds = mIds, + &mApi = mApi, mOptions = mOptions, errs, i] (LocationError err ) { + uint32_t hwId = 0; + errs[i] = mAdapter.getHwIdFromClient(mClient, mIds[i], hwId); + if (LOCATION_ERROR_SUCCESS == errs[i]) { + mApi.modifyGeofence(hwId, mIds[i], mOptions[i], + new LocApiResponse(*mAdapter.getContext(), + [&mAdapter = mAdapter, mCount = mCount, mClient = mClient, + mIds = mIds, mOptions = mOptions, hwId, errs, i] + (LocationError err ) { + if (LOCATION_ERROR_SUCCESS == err) { + errs[i] = err; + + mAdapter.modifyGeofenceItem(hwId, mOptions[i]); + } + // Send aggregated response on last item and cleanup + if (i == mCount-1) { + mAdapter.reportResponse(mClient, mCount, errs, mIds); + delete[] errs; + delete[] mIds; + delete[] mOptions; + } + })); + } else { + // Send aggregated response on last item and cleanup + if (i == mCount-1) { + mAdapter.reportResponse(mClient, mCount, errs, mIds); + delete[] errs; + delete[] mIds; + delete[] mOptions; + } + } + })); + } + } + } + }; + + if (0 == count) { + return; + } + uint32_t* idsCopy = new uint32_t[count]; + if (nullptr == idsCopy) { + LOC_LOGE("%s]: new failed to allocate idsCopy", __func__); + return; + } + COPY_IF_NOT_NULL(idsCopy, ids, count); + GeofenceOption* optionsCopy; + if (options == NULL) { + optionsCopy = NULL; + } else { + optionsCopy = new GeofenceOption[count]; + if (nullptr == optionsCopy) { + LOC_LOGE("%s]: new failed to allocate optionsCopy", __func__); + return; + } + COPY_IF_NOT_NULL(optionsCopy, options, count); + } + + sendMsg(new MsgModifyGeofences(*this, *mLocApi, client, count, idsCopy, optionsCopy)); +} + +void +GeofenceAdapter::saveGeofenceItem(LocationAPI* client, uint32_t clientId, uint32_t hwId, + const GeofenceOption& options, const GeofenceInfo& info) +{ + LOC_LOGD("%s]: hwId %u client %p clientId %u", __func__, hwId, client, clientId); + GeofenceKey key(client, clientId); + GeofenceObject object = {key, + options.breachTypeMask, + options.responsiveness, + options.dwellTime, + info.latitude, + info.longitude, + info.radius, + false}; + mGeofences[hwId] = object; + mGeofenceIds[key] = hwId; + dump(); +} + +void +GeofenceAdapter::removeGeofenceItem(uint32_t hwId) +{ + GeofenceKey key; + LocationError err = getGeofenceKeyFromHwId(hwId, key); + if (LOCATION_ERROR_SUCCESS != err) { + LOC_LOGE("%s]: can not find the key for hwId %u", __func__, hwId); + } else { + auto it1 = mGeofenceIds.find(key); + if (it1 != mGeofenceIds.end()) { + mGeofenceIds.erase(it1); + + auto it2 = mGeofences.find(hwId); + if (it2 != mGeofences.end()) { + mGeofences.erase(it2); + dump(); + } else { + LOC_LOGE("%s]:geofence item to erase not found. hwId %u", __func__, hwId); + } + } else { + LOC_LOGE("%s]: geofence item to erase not found. hwId %u", __func__, hwId); + } + } +} + +void +GeofenceAdapter::pauseGeofenceItem(uint32_t hwId) +{ + auto it = mGeofences.find(hwId); + if (it != mGeofences.end()) { + it->second.paused = true; + dump(); + } else { + LOC_LOGE("%s]: geofence item to pause not found. hwId %u", __func__, hwId); + } +} + +void +GeofenceAdapter::resumeGeofenceItem(uint32_t hwId) +{ + auto it = mGeofences.find(hwId); + if (it != mGeofences.end()) { + it->second.paused = false; + dump(); + } else { + LOC_LOGE("%s]: geofence item to resume not found. hwId %u", __func__, hwId); + } +} + +void +GeofenceAdapter::modifyGeofenceItem(uint32_t hwId, const GeofenceOption& options) +{ + auto it = mGeofences.find(hwId); + if (it != mGeofences.end()) { + it->second.breachMask = options.breachTypeMask; + it->second.responsiveness = options.responsiveness; + it->second.dwellTime = options.dwellTime; + dump(); + } else { + LOC_LOGE("%s]: geofence item to modify not found. hwId %u", __func__, hwId); + } +} + + +void +GeofenceAdapter::geofenceBreachEvent(size_t count, uint32_t* hwIds, Location& location, + GeofenceBreachType breachType, uint64_t timestamp) +{ + + IF_LOC_LOGD { + std::string idsString = "["; + if (NULL != hwIds) { + for (size_t i=0; i < count; ++i) { + idsString += std::to_string(hwIds[i]) + " "; + } + } + idsString += "]"; + LOC_LOGD("%s]: breachType %u count %zu ids %s", + __func__, breachType, count, idsString.c_str()); + } + + if (0 == count || NULL == hwIds) + return; + + struct MsgGeofenceBreach : public LocMsg { + GeofenceAdapter& mAdapter; + size_t mCount; + uint32_t* mHwIds; + Location mLocation; + GeofenceBreachType mBreachType; + uint64_t mTimestamp; + inline MsgGeofenceBreach(GeofenceAdapter& adapter, + size_t count, + uint32_t* hwIds, + Location& location, + GeofenceBreachType breachType, + uint64_t timestamp) : + LocMsg(), + mAdapter(adapter), + mCount(count), + mHwIds(new uint32_t[count]), + mLocation(location), + mBreachType(breachType), + mTimestamp(timestamp) + { + if (nullptr == mHwIds) { + LOC_LOGE("%s]: new failed to allocate mHwIds", __func__); + return; + } + COPY_IF_NOT_NULL(mHwIds, hwIds, mCount); + } + inline virtual ~MsgGeofenceBreach() { + delete[] mHwIds; + } + inline virtual void proc() const { + mAdapter.geofenceBreach(mCount, mHwIds, mLocation, mBreachType, mTimestamp); + } + }; + + sendMsg(new MsgGeofenceBreach(*this, count, hwIds, location, breachType, timestamp)); + +} + +void +GeofenceAdapter::geofenceBreach(size_t count, uint32_t* hwIds, const Location& location, + GeofenceBreachType breachType, uint64_t timestamp) +{ + + for (auto it = mClientData.begin(); it != mClientData.end(); ++it) { + uint32_t* clientIds = new uint32_t[count]; + if (nullptr == clientIds) { + return; + } + uint32_t index = 0; + for (size_t i=0; i < count; ++i) { + GeofenceKey key; + LocationError err = getGeofenceKeyFromHwId(hwIds[i], key); + if (LOCATION_ERROR_SUCCESS == err) { + if (key.client == it->first) { + clientIds[index++] = key.id; + } + } + } + if (index > 0 && it->second.geofenceBreachCb != nullptr) { + GeofenceBreachNotification notify = {sizeof(GeofenceBreachNotification), + index, + clientIds, + location, + breachType, + timestamp}; + + it->second.geofenceBreachCb(notify); + } + delete[] clientIds; + } +} + +void +GeofenceAdapter::geofenceStatusEvent(GeofenceStatusAvailable available) +{ + LOC_LOGD("%s]: available %u ", __func__, available); + + struct MsgGeofenceStatus : public LocMsg { + GeofenceAdapter& mAdapter; + GeofenceStatusAvailable mAvailable; + inline MsgGeofenceStatus(GeofenceAdapter& adapter, + GeofenceStatusAvailable available) : + LocMsg(), + mAdapter(adapter), + mAvailable(available) {} + inline virtual void proc() const { + mAdapter.geofenceStatus(mAvailable); + } + }; + + sendMsg(new MsgGeofenceStatus(*this, available)); +} + +void +GeofenceAdapter::geofenceStatus(GeofenceStatusAvailable available) +{ + for (auto it = mClientData.begin(); it != mClientData.end(); ++it) { + if (it->second.geofenceStatusCb != nullptr) { + GeofenceStatusNotification notify = {sizeof(GeofenceStatusNotification), + available, + LOCATION_TECHNOLOGY_TYPE_GNSS}; + it->second.geofenceStatusCb(notify); + } + } +} + +void +GeofenceAdapter::dump() +{ + IF_LOC_LOGV { + LOC_LOGV( + "HAL | hwId | mask | respon | latitude | longitude | radius | paused | Id | client"); + for (auto it = mGeofences.begin(); it != mGeofences.end(); ++it) { + uint32_t hwId = it->first; + GeofenceObject object = it->second; + LOC_LOGV(" | %5u | %4u | %6u | %8.2f | %9.2f | %6.2f | %6u | %04x | %p ", + hwId, object.breachMask, object.responsiveness, + object.latitude, object.longitude, object.radius, + object.paused, object.key.id, object.key.client); + } + } +} + diff --git a/geofence/GeofenceAdapter.h b/geofence/GeofenceAdapter.h new file mode 100644 index 00000000..38f48230 --- /dev/null +++ b/geofence/GeofenceAdapter.h @@ -0,0 +1,136 @@ +/* Copyright (c) 2013-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 GEOFENCE_ADAPTER_H +#define GEOFENCE_ADAPTER_H + +#include +#include +#include +#include + +using namespace loc_core; + +#define COPY_IF_NOT_NULL(dest, src, len) do { \ + if (NULL!=dest && NULL!=src) { \ + for (size_t i=0; i GeofencesMap; //map of hwId to GeofenceObject +typedef std::map GeofenceIdMap; //map of GeofenceKey to hwId + +class GeofenceAdapter : public LocAdapterBase { + + /* ==== GEOFENCES ====================================================================== */ + GeofencesMap mGeofences; //map hwId to GeofenceObject + GeofenceIdMap mGeofenceIds; //map of GeofenceKey to hwId + +protected: + + /* ==== CLIENT ========================================================================= */ + virtual void updateClientsEventMask(); + virtual void stopClientSessions(LocationAPI* client); + +public: + + GeofenceAdapter(); + virtual ~GeofenceAdapter() {} + + /* ==== SSR ============================================================================ */ + /* ======== EVENTS ====(Called from QMI Thread)========================================= */ + virtual void handleEngineUpEvent(); + /* ======== UTILITIES ================================================================== */ + void restartGeofences(); + + /* ==== GEOFENCES ====================================================================== */ + /* ======== COMMANDS ====(Called from Client Thread)==================================== */ + uint32_t* addGeofencesCommand(LocationAPI* client, size_t count, + GeofenceOption* options, GeofenceInfo* info); + void removeGeofencesCommand(LocationAPI* client, size_t count, uint32_t* ids); + void pauseGeofencesCommand(LocationAPI* client, size_t count, uint32_t* ids); + void resumeGeofencesCommand(LocationAPI* client, size_t count, uint32_t* ids); + void modifyGeofencesCommand(LocationAPI* client, size_t count, uint32_t* ids, + GeofenceOption* options); + /* ======== RESPONSES ================================================================== */ + void reportResponse(LocationAPI* client, size_t count, LocationError* errs, uint32_t* ids); + /* ======== UTILITIES ================================================================== */ + void saveGeofenceItem(LocationAPI* client, + uint32_t clientId, + uint32_t hwId, + const GeofenceOption& options, + const GeofenceInfo& info); + void removeGeofenceItem(uint32_t hwId); + void pauseGeofenceItem(uint32_t hwId); + void resumeGeofenceItem(uint32_t hwId); + void modifyGeofenceItem(uint32_t hwId, const GeofenceOption& options); + LocationError getHwIdFromClient(LocationAPI* client, uint32_t clientId, uint32_t& hwId); + LocationError getGeofenceKeyFromHwId(uint32_t hwId, GeofenceKey& key); + void dump(); + + /* ==== REPORTS ======================================================================== */ + /* ======== EVENTS ====(Called from QMI Thread)========================================= */ + void geofenceBreachEvent(size_t count, uint32_t* hwIds, Location& location, + GeofenceBreachType breachType, uint64_t timestamp); + void geofenceStatusEvent(GeofenceStatusAvailable available); + /* ======== UTILITIES ================================================================== */ + void geofenceBreach(size_t count, uint32_t* hwIds, const Location& location, + GeofenceBreachType breachType, uint64_t timestamp); + void geofenceStatus(GeofenceStatusAvailable available); +}; + +#endif /* GEOFENCE_ADAPTER_H */ diff --git a/geofence/Makefile.am b/geofence/Makefile.am new file mode 100644 index 00000000..61883ff2 --- /dev/null +++ b/geofence/Makefile.am @@ -0,0 +1,50 @@ +AM_CFLAGS = -Wundef \ + -Wno-trigraphs \ + -g -O0 \ + -fno-inline \ + -fno-short-enums \ + -fpic \ + ${GPSUTILS_CFLAGS} \ + ${LOCCORE_CFLAGS} \ + $(LOCPLA_CFLAGS) \ + -D__func__=__PRETTY_FUNCTION__ \ + -std=c++1y + +AM_CPPFLAGS = $(AM_CFLAGS) + +ACLOCAL_AMFLAGS = -I m4 + +requiredlibs = \ + ${LOCCORE_LIBS} \ + $(GPSUTILS_LIBS) \ + -llog + +h_sources = \ + GeofenceAdapter.h + +c_sources = \ + GeofenceAdapter.cpp \ + location_geofence.cpp + +libgeofencing_la_SOURCES = $(c_sources) +if USE_GLIB +libgeofencing_la_CFLAGS = -DUSE_GLIB @GLIB_CFLAGS@ $(AM_CFLAGS) +libgeofencing_la_CPPFLAGS = -DUSE_GLIB @GLIB_CFLAGS@ $(AM_CFLAGS) $(AM_CPPFLAGS) +libgeofencing_la_LDFLAGS = -lstdc++ -Wl,-z,defs @GLIB_LIBS@ $(requiredlibs) -shared -version-info 1:0:0 +libgeofencing_la_LIBDADD = $(requiredlibs) -lstdc++ @GLIB_LIBS@ +else +libgeofencing_la_CFLAGS = $(AM_CFLAGS) +libgeofencing_la_CPPFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS) +libgeofencing_la_LDFLAGS = -lstdc++ -Wl,-z,defs $(requiredlibs) -shared -version-info 1:0:0 +libgeofencing_la_LIBDADD = $(requiredlibs) -lstdc++ +endif + +library_include_HEADERS = $(h_sources) + +library_includedir = $(pkgincludedir) + +lib_LTLIBRARIES = libgeofencing.la + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = location-geofence.pc +EXTRA_DIST = $(pkgconfig_DATA) diff --git a/geofence/configure.ac b/geofence/configure.ac new file mode 100644 index 00000000..8e3cd819 --- /dev/null +++ b/geofence/configure.ac @@ -0,0 +1,72 @@ +AC_PREREQ(2.61) +AC_INIT([location-geofence], 1.0.0) +AM_INIT_AUTOMAKE([foreign]) +AC_CONFIG_SRCDIR([Makefile.am]) +AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_MACRO_DIR([m4]) + +# Check 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 + +# Check 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]) + +AS_CASE([$host], + [arm*], [ARM=yes], + [ARM=no] +) + +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_SUBST([CFLAGS]) +AC_SUBST([CPPFLAGS]) +AC_SUBST([LIBS]) + +AC_CONFIG_FILES([ \ + Makefile \ + location-geofence.pc + ]) + +AC_OUTPUT diff --git a/geofence/location-geofence.pc.in b/geofence/location-geofence.pc.in new file mode 100644 index 00000000..6a0781f2 --- /dev/null +++ b/geofence/location-geofence.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: location-geofence +Description: QTI GPS Geofence +Version: @VERSION +Libs: -L${libdir} -lgeofencing +Cflags: -I${includedir}/location-geofence diff --git a/geofence/location_geofence.cpp b/geofence/location_geofence.cpp new file mode 100644 index 00000000..66729f44 --- /dev/null +++ b/geofence/location_geofence.cpp @@ -0,0 +1,145 @@ +/* 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 "GeofenceAdapter.h" +#include "location_interface.h" + +static GeofenceAdapter* gGeofenceAdapter = 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* addGeofences(LocationAPI* client, size_t count, GeofenceOption*, GeofenceInfo*); +static void removeGeofences(LocationAPI* client, size_t count, uint32_t* ids); +static void modifyGeofences(LocationAPI* client, size_t count, uint32_t* ids, + GeofenceOption* options); +static void pauseGeofences(LocationAPI* client, size_t count, uint32_t* ids); +static void resumeGeofences(LocationAPI* client, size_t count, uint32_t* ids); + +static const GeofenceInterface gGeofenceInterface = { + sizeof(GeofenceInterface), + initialize, + deinitialize, + addClient, + removeClient, + requestCapabilities, + addGeofences, + removeGeofences, + modifyGeofences, + pauseGeofences, + resumeGeofences +}; + +#ifndef DEBUG_X86 +extern "C" const GeofenceInterface* getGeofenceInterface() +#else +const GeofenceInterface* getGeofenceInterface() +#endif // DEBUG_X86 +{ + return &gGeofenceInterface; +} + +static void initialize() +{ + if (NULL == gGeofenceAdapter) { + gGeofenceAdapter = new GeofenceAdapter(); + } +} + +static void deinitialize() +{ + if (NULL != gGeofenceAdapter) { + delete gGeofenceAdapter; + gGeofenceAdapter = NULL; + } +} + +static void addClient(LocationAPI* client, const LocationCallbacks& callbacks) +{ + if (NULL != gGeofenceAdapter) { + gGeofenceAdapter->addClientCommand(client, callbacks); + } +} + +static void removeClient(LocationAPI* client, removeClientCompleteCallback rmClientCb) +{ + if (NULL != gGeofenceAdapter) { + gGeofenceAdapter->removeClientCommand(client, rmClientCb); + } +} + +static void requestCapabilities(LocationAPI* client) +{ + if (NULL != gGeofenceAdapter) { + gGeofenceAdapter->requestCapabilitiesCommand(client); + } +} + +static uint32_t* addGeofences(LocationAPI* client, size_t count, + GeofenceOption* options, GeofenceInfo* info) +{ + if (NULL != gGeofenceAdapter) { + return gGeofenceAdapter->addGeofencesCommand(client, count, options, info); + } else { + return NULL; + } +} + +static void removeGeofences(LocationAPI* client, size_t count, uint32_t* ids) +{ + if (NULL != gGeofenceAdapter) { + return gGeofenceAdapter->removeGeofencesCommand(client, count, ids); + } +} + +static void modifyGeofences(LocationAPI* client, size_t count, uint32_t* ids, + GeofenceOption* options) +{ + if (NULL != gGeofenceAdapter) { + return gGeofenceAdapter->modifyGeofencesCommand(client, count, ids, options); + } +} + +static void pauseGeofences(LocationAPI* client, size_t count, uint32_t* ids) +{ + if (NULL != gGeofenceAdapter) { + return gGeofenceAdapter->pauseGeofencesCommand(client, count, ids); + } +} + +static void resumeGeofences(LocationAPI* client, size_t count, uint32_t* ids) +{ + if (NULL != gGeofenceAdapter) { + return gGeofenceAdapter->resumeGeofencesCommand(client, count, ids); + } +} + diff --git a/gnss/GnssAdapter.cpp b/gnss/GnssAdapter.cpp index f6dff894..10f0255c 100644 --- a/gnss/GnssAdapter.cpp +++ b/gnss/GnssAdapter.cpp @@ -50,6 +50,7 @@ #define RAD2DEG (180.0 / M_PI) #define PROCESS_NAME_ENGINE_SERVICE "engine-service" +#define MIN_TRACKING_INTERVAL (100) // 100 msec using namespace loc_core; @@ -63,9 +64,9 @@ static void agpsCloseResultCb (bool isSuccess, AGpsExtType agpsType, void* userD GnssAdapter::GnssAdapter() : LocAdapterBase(0, - LocDualContext::getLocFgContext(NULL, + LocContext::getLocContext(NULL, NULL, - LocDualContext::mLocationHalName, + LocContext::mLocationHalName, false), true, nullptr), mEngHubProxy(new EngineHubProxyBase()), mLocPositionMode(), @@ -87,9 +88,13 @@ GnssAdapter::GnssAdapter() : mSystemStatus(SystemStatus::getInstance(mMsgTask)), mServerUrl(":"), mXtraObserver(mSystemStatus->getOsObserver(), mMsgTask), - mBlockCPIInfo{}, mLocSystemInfo{}, - mNfwCb(NULL) + mBlockCPIInfo{}, + mNfwCb(NULL), + mPowerOn(false), + mAllowFlpNetworkFixes(0), + mGnssEnergyConsumedCb(nullptr), + mPowerStateCb(nullptr) { LOC_LOGD("%s]: Constructor %p", __func__, this); mLocPositionMode.mode = LOC_POSITION_MODE_INVALID; @@ -569,8 +574,21 @@ GnssAdapter::readConfigCommand() mAdapter(adapter), mContext(context) {} inline virtual void proc() const { - // reads config into mContext->mGps_conf - mContext.readConfig(); + static bool confReadDone = false; + if (!confReadDone) { + confReadDone = true; + // reads config into mContext->mGps_conf + mContext.readConfig(); + + uint32_t allowFlpNetworkFixes = 0; + static const loc_param_s_type flp_conf_param_table[] = + { + {"ALLOW_NETWORK_FIXES", &allowFlpNetworkFixes, NULL, 'n'}, + }; + UTIL_READ_CONF(LOC_PATH_FLP_CONF, flp_conf_param_table); + LOC_LOGd("allowFlpNetworkFixes %u", allowFlpNetworkFixes); + mAdapter->setAllowFlpNetworkFixes(allowFlpNetworkFixes); + } } }; @@ -625,7 +643,10 @@ GnssAdapter::setConfigCommand() mAdapter(adapter), mApi(api) {} inline virtual void proc() const { - + if (!mAdapter.isEngineCapabilitiesKnown()) { + mAdapter.mPendingMsgs.push_back(new MsgSetConfig(*this)); + return; + } // set nmea mask type uint32_t mask = 0; if (NMEA_PROVIDER_MP == ContextBase::mGps_conf.NMEA_PROVIDER) { @@ -980,7 +1001,10 @@ GnssAdapter::gnssUpdateConfigCommand(GnssConfig config) } inline virtual void proc() const { - + if (!mAdapter.isEngineCapabilitiesKnown()) { + mAdapter.mPendingMsgs.push_back(new MsgGnssUpdateConfig(*this)); + return; + } GnssAdapter& adapter = mAdapter; size_t countOfConfigs = mCount; GnssConfig gnssConfigRequested = mConfig; @@ -1236,7 +1260,10 @@ GnssAdapter::gnssGetConfigCommand(GnssConfigFlagsMask configMask) { delete[] mIds; } inline virtual void proc() const { - + if (!mAdapter.isEngineCapabilitiesKnown()) { + mAdapter.mPendingMsgs.push_back(new MsgGnssGetConfig(*this)); + return; + } LocationError* errs = new LocationError[mCount]; LocationError err = LOCATION_ERROR_SUCCESS; uint32_t index = 0; @@ -1511,7 +1538,10 @@ GnssAdapter::gnssUpdateSvTypeConfigCommand(GnssSvTypeConfig config) mApi(api), mConfig(config) {} inline virtual void proc() const { - + if (!mAdapter->isEngineCapabilitiesKnown()) { + mAdapter->mPendingMsgs.push_back(new MsgGnssUpdateSvTypeConfig(*this)); + return; + } // Check if feature is supported if (!ContextBase::isFeatureSupported( LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) { @@ -1601,7 +1631,10 @@ GnssAdapter::gnssGetSvTypeConfigCommand(GnssSvTypeConfigCallback callback) mApi(api), mCallback(callback) {} inline virtual void proc() const { - + if (!mAdapter->isEngineCapabilitiesKnown()) { + mAdapter->mPendingMsgs.push_back(new MsgGnssGetSvTypeConfig(*this)); + return; + } if (!ContextBase::isFeatureSupported( LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) { LOC_LOGe("Feature not supported."); @@ -1630,7 +1663,10 @@ GnssAdapter::gnssResetSvTypeConfigCommand() mAdapter(adapter), mApi(api) {} inline virtual void proc() const { - + if (!mAdapter->isEngineCapabilitiesKnown()) { + mAdapter->mPendingMsgs.push_back(new MsgGnssResetSvTypeConfig(*this)); + return; + } if (!ContextBase::isFeatureSupported( LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) { LOC_LOGe("Feature not supported."); @@ -1876,44 +1912,33 @@ GnssAdapter::addClientCommand(LocationAPI* client, const LocationCallbacks& call sendMsg(new MsgAddClient(*this, client, callbacks)); } -void -GnssAdapter::removeClientCommand(LocationAPI* client, - removeClientCompleteCallback rmClientCb) -{ - LOC_LOGD("%s]: client %p", __func__, client); - - struct MsgRemoveClient : public LocMsg { - GnssAdapter& mAdapter; - LocationAPI* mClient; - removeClientCompleteCallback mRmClientCb; - inline MsgRemoveClient(GnssAdapter& adapter, - LocationAPI* client, - removeClientCompleteCallback rmCb) : - LocMsg(), - mAdapter(adapter), - mClient(client), - mRmClientCb(rmCb){} - inline virtual void proc() const { - mAdapter.stopClientSessions(mClient); - mAdapter.eraseClient(mClient); - if (nullptr != mRmClientCb) { - mRmClientCb(mClient); - } - } - }; - - sendMsg(new MsgRemoveClient(*this, client, rmClientCb)); -} - void GnssAdapter::stopClientSessions(LocationAPI* client) { LOC_LOGD("%s]: client %p", __func__, client); - for (auto it = mTrackingSessions.begin(); it != mTrackingSessions.end();) { + + /* Time-based Tracking */ + std::vector vTimeBasedTrackingClient; + for (auto it : mTimeBasedTrackingSessions) { + if (client == it.first.client) { + vTimeBasedTrackingClient.emplace_back(it.first.client, it.first.id); + } + } + for (auto key : vTimeBasedTrackingClient) { + stopTimeBasedTrackingMultiplex(key.client, key.id); + } + + /* Distance-based Tracking */ + for (auto it = mDistanceBasedTrackingSessions.begin(); + it != mDistanceBasedTrackingSessions.end(); /* no increment here*/) { if (client == it->first.client) { - stopTrackingMultiplex(it->first.client, it->first.id); - it = mTrackingSessions.erase(it); - continue; + mLocApi->stopDistanceBasedTracking(it->first.id, new LocApiResponse(*getContext(), + [this, client, id=it->first.id] (LocationError err) { + if (LOCATION_ERROR_SUCCESS == err) { + eraseTrackingSession(client, id); + } + } + )); } ++it; // increment only when not erasing an iterator } @@ -1993,11 +2018,15 @@ GnssAdapter::handleEngineUpEvent() LocMsg(), mAdapter(adapter) {} virtual void proc() const { + mAdapter.setEngineCapabilitiesKnown(true); mAdapter.broadcastCapabilities(mAdapter.getCapabilities()); - // restart sessions mAdapter.restartSessions(); mAdapter.gnssSvIdConfigUpdate(); mAdapter.gnssSvTypeConfigUpdate(); + for (auto msg: mAdapter.mPendingMsgs) { + mAdapter.sendMsg(msg); + } + mAdapter.mPendingMsgs.clear(); } }; @@ -2014,132 +2043,37 @@ GnssAdapter::restartSessions() // odcpi session is no longer active after restart mOdcpiRequestActive = false; - if (mTrackingSessions.empty()) { - return; - } - - // get the LocationOptions that has the smallest interval, which should be the active one - TrackingOptions smallestIntervalOptions; // size is zero until set for the first time - TrackingOptions highestPowerTrackingOptions; - memset(&smallestIntervalOptions, 0, sizeof(smallestIntervalOptions)); - memset(&highestPowerTrackingOptions, 0, sizeof(highestPowerTrackingOptions)); - for (auto it = mTrackingSessions.begin(); it != mTrackingSessions.end(); ++it) { - // size of zero means we havent set it yet - if (0 == smallestIntervalOptions.size || - it->second.minInterval < smallestIntervalOptions.minInterval) { - smallestIntervalOptions = it->second; - } - GnssPowerMode powerMode = it->second.powerMode; - // Size of zero means we havent set it yet - if (0 == highestPowerTrackingOptions.size || - (GNSS_POWER_MODE_INVALID != powerMode && - powerMode < highestPowerTrackingOptions.powerMode)) { - highestPowerTrackingOptions = it->second; - } - } - - LocPosMode locPosMode = {}; - highestPowerTrackingOptions.setLocationOptions(smallestIntervalOptions); - convertOptions(locPosMode, highestPowerTrackingOptions); - mLocApi->startFix(locPosMode, nullptr); -} - -void -GnssAdapter::requestCapabilitiesCommand(LocationAPI* client) -{ - LOC_LOGD("%s]: ", __func__); - - struct MsgRequestCapabilities : public LocMsg { - GnssAdapter& mAdapter; - LocationAPI* mClient; - inline MsgRequestCapabilities(GnssAdapter& adapter, - LocationAPI* client) : - LocMsg(), - mAdapter(adapter), - mClient(client) {} - inline virtual void proc() const { - LocationCallbacks callbacks = mAdapter.getClientCallbacks(mClient); - if (callbacks.capabilitiesCb == nullptr) { - LOC_LOGE("%s]: capabilitiesCb is NULL", __func__); - return; + if (!mTimeBasedTrackingSessions.empty()) { + // get the LocationOptions that has the smallest interval, which should be the active one + TrackingOptions smallestIntervalOptions; // size is zero until set for the first time + TrackingOptions highestPowerTrackingOptions; + memset(&smallestIntervalOptions, 0, sizeof(smallestIntervalOptions)); + memset(&highestPowerTrackingOptions, 0, sizeof(highestPowerTrackingOptions)); + for (auto it = mTimeBasedTrackingSessions.begin(); it != mTimeBasedTrackingSessions.end(); ++it) { + // size of zero means we havent set it yet + if (0 == smallestIntervalOptions.size || + it->second.minInterval < smallestIntervalOptions.minInterval) { + smallestIntervalOptions = it->second; + } + GnssPowerMode powerMode = it->second.powerMode; + // Size of zero means we havent set it yet + if (0 == highestPowerTrackingOptions.size || + (GNSS_POWER_MODE_INVALID != powerMode && + powerMode < highestPowerTrackingOptions.powerMode)) { + highestPowerTrackingOptions = it->second; } - - LocationCapabilitiesMask mask = mAdapter.getCapabilities(); - callbacks.capabilitiesCb(mask); } - }; - if (ContextBase::isEngineCapabilitiesKnown()) { - sendMsg(new MsgRequestCapabilities(*this, client)); + highestPowerTrackingOptions.setLocationOptions(smallestIntervalOptions); + mLocApi->startTimeBasedTracking(highestPowerTrackingOptions, nullptr); } -} -LocationCapabilitiesMask -GnssAdapter::getCapabilities() -{ - LocationCapabilitiesMask mask = 0; - uint32_t carrierCapabilities = ContextBase::getCarrierCapabilities(); - // time based tracking always supported - mask |= LOCATION_CAPABILITIES_TIME_BASED_TRACKING_BIT; - // geofence always supported - mask |= LOCATION_CAPABILITIES_GEOFENCE_BIT; - if (carrierCapabilities & LOC_GPS_CAPABILITY_MSB) { - mask |= LOCATION_CAPABILITIES_GNSS_MSB_BIT; + for (auto it = mDistanceBasedTrackingSessions.begin(); + it != mDistanceBasedTrackingSessions.end(); ++it) { + mLocApi->startDistanceBasedTracking(it->first.id, it->second, + new LocApiResponse(*getContext(), + [] (LocationError /*err*/) {})); } - if (LOC_GPS_CAPABILITY_MSA & carrierCapabilities) { - mask |= LOCATION_CAPABILITIES_GNSS_MSA_BIT; - } - if (ContextBase::isMessageSupported(LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_LOCATION_BATCHING)) { - mask |= LOCATION_CAPABILITIES_TIME_BASED_BATCHING_BIT | - LOCATION_CAPABILITIES_DISTANCE_BASED_BATCHING_BIT; - } - if (ContextBase::isMessageSupported(LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_TRACKING)) { - mask |= LOCATION_CAPABILITIES_DISTANCE_BASED_TRACKING_BIT; - } - if (ContextBase::isMessageSupported(LOC_API_ADAPTER_MESSAGE_OUTDOOR_TRIP_BATCHING)) { - mask |= LOCATION_CAPABILITIES_OUTDOOR_TRIP_BATCHING_BIT; - } - if (ContextBase::gnssConstellationConfig()) { - mask |= LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT; - } - if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02)) { - mask |= LOCATION_CAPABILITIES_DEBUG_NMEA_BIT; - } - if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) { - mask |= LOCATION_CAPABILITIES_CONSTELLATION_ENABLEMENT_BIT; - } - if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_AGPM_V02)) { - mask |= LOCATION_CAPABILITIES_AGPM_BIT; - } - return mask; -} - -void -GnssAdapter::broadcastCapabilities(LocationCapabilitiesMask mask) -{ - for (auto clientData : mClientData) { - if (nullptr != clientData.second.capabilitiesCb) { - clientData.second.capabilitiesCb(mask); - } - } -} - -LocationCallbacks -GnssAdapter::getClientCallbacks(LocationAPI* client) -{ - LocationCallbacks callbacks = {}; - auto it = mClientData.find(client); - if (it != mClientData.end()) { - callbacks = it->second; - } - return callbacks; -} - -void -GnssAdapter::saveClient(LocationAPI* client, const LocationCallbacks& callbacks) -{ - mClientData[client] = callbacks; - updateClientsEventMask(); } void @@ -2171,16 +2105,6 @@ GnssAdapter::notifyClientOfCachedLocationSystemInfo( } } -void -GnssAdapter::eraseClient(LocationAPI* client) -{ - auto it = mClientData.find(client); - if (it != mClientData.end()) { - mClientData.erase(it); - } - updateClientsEventMask(); -} - bool GnssAdapter::hasTrackingCallback(LocationAPI* client) { @@ -2188,6 +2112,20 @@ GnssAdapter::hasTrackingCallback(LocationAPI* client) return (it != mClientData.end() && (it->second.trackingCb || it->second.gnssLocationInfoCb)); } +bool +GnssAdapter::isTimeBasedTrackingSession(LocationAPI* client, uint32_t sessionId) +{ + LocationSessionKey key(client, sessionId); + return (mTimeBasedTrackingSessions.find(key) != mTimeBasedTrackingSessions.end()); +} + +bool +GnssAdapter::isDistanceBasedTrackingSession(LocationAPI* client, uint32_t sessionId) +{ + LocationSessionKey key(client, sessionId); + return (mDistanceBasedTrackingSessions.find(key) != mDistanceBasedTrackingSessions.end()); +} + bool GnssAdapter::hasMeasurementsCallback(LocationAPI* client) { @@ -2199,27 +2137,75 @@ bool GnssAdapter::isTrackingSession(LocationAPI* client, uint32_t sessionId) { LocationSessionKey key(client, sessionId); - return (mTrackingSessions.find(key) != mTrackingSessions.end()); + return (mTimeBasedTrackingSessions.find(key) != mTimeBasedTrackingSessions.end()); +} + +void +GnssAdapter::reportPowerStateIfChanged() +{ + bool newPowerOn = !mTimeBasedTrackingSessions.empty() || + !mDistanceBasedTrackingSessions.empty(); + if (newPowerOn != mPowerOn) { + mPowerOn = newPowerOn; + if (mPowerStateCb != nullptr) { + mPowerStateCb(mPowerOn); + } + } +} + +void +GnssAdapter::getPowerStateChangesCommand(void* powerStateCb) +{ + LOC_LOGD("%s]: ", __func__); + + struct MsgReportLocation : public LocMsg { + GnssAdapter& mAdapter; + powerStateCallback mPowerStateCb; + inline MsgReportLocation(GnssAdapter& adapter, + powerStateCallback powerStateCb) : + LocMsg(), + mAdapter(adapter), + mPowerStateCb(powerStateCb) {} + inline virtual void proc() const { + mAdapter.savePowerStateCallback(mPowerStateCb); + mPowerStateCb(mAdapter.getPowerState()); + } + }; + + sendMsg(new MsgReportLocation(*this, (powerStateCallback)powerStateCb)); } void GnssAdapter::saveTrackingSession(LocationAPI* client, uint32_t sessionId, - const TrackingOptions& trackingOptions) + const TrackingOptions& options) { LocationSessionKey key(client, sessionId); - mTrackingSessions[key] = trackingOptions; + if ((options.minDistance > 0) && + ContextBase::isMessageSupported(LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_TRACKING)) { + mDistanceBasedTrackingSessions[key] = options; + } else { + mTimeBasedTrackingSessions[key] = options; + } + reportPowerStateIfChanged(); } void GnssAdapter::eraseTrackingSession(LocationAPI* client, uint32_t sessionId) { LocationSessionKey key(client, sessionId); - auto itr = mTrackingSessions.find(key); - if (itr != mTrackingSessions.end()) { - mTrackingSessions.erase(itr); + auto it = mTimeBasedTrackingSessions.find(key); + if (it != mTimeBasedTrackingSessions.end()) { + mTimeBasedTrackingSessions.erase(it); + } else { + auto itr = mDistanceBasedTrackingSessions.find(key); + if (itr != mDistanceBasedTrackingSessions.end()) { + mDistanceBasedTrackingSessions.erase(itr); + } } + reportPowerStateIfChanged(); } + bool GnssAdapter::setLocPositionMode(const LocPosMode& mode) { if (!mLocPositionMode.equals(mode)) { mLocPositionMode = mode; @@ -2293,48 +2279,62 @@ GnssAdapter::startTrackingCommand(LocationAPI* client, TrackingOptions& options) LocApiBase& mApi; LocationAPI* mClient; uint32_t mSessionId; - mutable TrackingOptions mTrackingOptions; + mutable TrackingOptions mOptions; inline MsgStartTracking(GnssAdapter& adapter, LocApiBase& api, LocationAPI* client, uint32_t sessionId, - TrackingOptions trackingOptions) : + TrackingOptions options) : LocMsg(), mAdapter(adapter), mApi(api), mClient(client), mSessionId(sessionId), - mTrackingOptions(trackingOptions) {} + mOptions(options) {} inline virtual void proc() const { + // distance based tracking will need to know engine capabilities before it can start + if (!mAdapter.isEngineCapabilitiesKnown() && mOptions.minDistance > 0) { + mAdapter.mPendingMsgs.push_back(new MsgStartTracking(*this)); + return; + } LocationError err = LOCATION_ERROR_SUCCESS; if (!mAdapter.hasTrackingCallback(mClient) && !mAdapter.hasMeasurementsCallback(mClient)) { err = LOCATION_ERROR_CALLBACK_MISSING; - } else if (0 == mTrackingOptions.size) { + } else if (0 == mOptions.size) { err = LOCATION_ERROR_INVALID_PARAMETER; } else { - if (GNSS_POWER_MODE_INVALID != mTrackingOptions.powerMode && - !ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_AGPM_V02)) { - LOC_LOGv("Ignoring power mode, feature not supported."); - mTrackingOptions.powerMode = GNSS_POWER_MODE_INVALID; + if (mOptions.minInterval < MIN_TRACKING_INTERVAL) { + mOptions.minInterval = MIN_TRACKING_INTERVAL; } - if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_AGPM_V02) && - GNSS_POWER_MODE_M4 == mTrackingOptions.powerMode && - mTrackingOptions.tbm > TRACKING_TBM_THRESHOLD_MILLIS) { - LOC_LOGd("TBM (%d) > %d Falling back to M2 power mode", - mTrackingOptions.tbm, TRACKING_TBM_THRESHOLD_MILLIS); - mTrackingOptions.powerMode = GNSS_POWER_MODE_M2; - } - if (mTrackingOptions.minInterval < MIN_TRACKING_INTERVAL) { - mTrackingOptions.minInterval = MIN_TRACKING_INTERVAL; - } - // Api doesn't support multiple clients for time based tracking, so mutiplex - bool reportToClientWithNoWait = - mAdapter.startTrackingMultiplex(mClient, mSessionId, mTrackingOptions); - mAdapter.saveTrackingSession(mClient, mSessionId, mTrackingOptions); + if (mOptions.minDistance > 0 && + ContextBase::isMessageSupported( + LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_TRACKING)) { + mAdapter.saveTrackingSession(mClient, mSessionId, mOptions); + mApi.startDistanceBasedTracking(mSessionId, mOptions, + new LocApiResponse(*mAdapter.getContext(), + [&mAdapter = mAdapter, mSessionId = mSessionId, mClient = mClient] + (LocationError err) { + if (LOCATION_ERROR_SUCCESS != err) { + mAdapter.eraseTrackingSession(mClient, mSessionId); + } + mAdapter.reportResponse(mClient, err, mSessionId); + })); + } else { + if (GNSS_POWER_MODE_M4 == mOptions.powerMode && + mOptions.tbm > TRACKING_TBM_THRESHOLD_MILLIS) { + LOC_LOGd("TBM (%d) > %d Falling back to M2 power mode", + mOptions.tbm, TRACKING_TBM_THRESHOLD_MILLIS); + mOptions.powerMode = GNSS_POWER_MODE_M2; + } + // Api doesn't support multiple clients for time based tracking, so mutiplex + bool reportToClientWithNoWait = + mAdapter.startTimeBasedTrackingMultiplex(mClient, mSessionId, mOptions); + mAdapter.saveTrackingSession(mClient, mSessionId, mOptions); - if (reportToClientWithNoWait) { - mAdapter.reportResponse(mClient, LOCATION_ERROR_SUCCESS, mSessionId); + if (reportToClientWithNoWait) { + mAdapter.reportResponse(mClient, LOCATION_ERROR_SUCCESS, mSessionId); + } } } } @@ -2346,13 +2346,13 @@ GnssAdapter::startTrackingCommand(LocationAPI* client, TrackingOptions& options) } bool -GnssAdapter::startTrackingMultiplex(LocationAPI* client, uint32_t sessionId, - const TrackingOptions& options) +GnssAdapter::startTimeBasedTrackingMultiplex(LocationAPI* client, uint32_t sessionId, + const TrackingOptions& options) { bool reportToClientWithNoWait = true; - if (mTrackingSessions.empty()) { - startTracking(client, sessionId, options); + if (mTimeBasedTrackingSessions.empty()) { + startTimeBasedTracking(client, sessionId, options); // need to wait for QMI callback reportToClientWithNoWait = false; } else { @@ -2360,7 +2360,7 @@ GnssAdapter::startTrackingMultiplex(LocationAPI* client, uint32_t sessionId, TrackingOptions multiplexedOptions = {}; // size is 0 until set for the first time GnssPowerMode multiplexedPowerMode = GNSS_POWER_MODE_INVALID; memset(&multiplexedOptions, 0, sizeof(multiplexedOptions)); - for (auto it = mTrackingSessions.begin(); it != mTrackingSessions.end(); ++it) { + for (auto it = mTimeBasedTrackingSessions.begin(); it != mTimeBasedTrackingSessions.end(); ++it) { // if not set or there is a new smallest interval, then set the new interval if (0 == multiplexedOptions.size || it->second.minInterval < multiplexedOptions.minInterval) { @@ -2387,7 +2387,7 @@ GnssAdapter::startTrackingMultiplex(LocationAPI* client, uint32_t sessionId, if (updateOptions) { // restart time based tracking with the newly updated options - startTracking(client, sessionId, multiplexedOptions); + startTimeBasedTracking(client, sessionId, multiplexedOptions); // need to wait for QMI callback reportToClientWithNoWait = false; } @@ -2398,12 +2398,12 @@ GnssAdapter::startTrackingMultiplex(LocationAPI* client, uint32_t sessionId, } void -GnssAdapter::startTracking(LocationAPI* client, uint32_t sessionId, +GnssAdapter::startTimeBasedTracking(LocationAPI* client, uint32_t sessionId, const TrackingOptions& trackingOptions) { LOC_LOGd("minInterval %u minDistance %u mode %u powermode %u tbm %u", - trackingOptions.minInterval, trackingOptions.minDistance, - trackingOptions.mode, trackingOptions.powerMode, trackingOptions.tbm); + trackingOptions.minInterval, trackingOptions.minDistance, + trackingOptions.mode, trackingOptions.powerMode, trackingOptions.tbm); LocPosMode locPosMode = {}; convertOptions(locPosMode, trackingOptions); @@ -2412,7 +2412,7 @@ GnssAdapter::startTracking(LocationAPI* client, uint32_t sessionId, mEngHubProxy->gnssSetFixMode(locPosMode); mEngHubProxy->gnssStartFix(); - mLocApi->startFix(locPosMode, new LocApiResponse(*getContext(), + mLocApi->startTimeBasedTracking(trackingOptions, new LocApiResponse(*getContext(), [this, client, sessionId] (LocationError err) { if (LOCATION_ERROR_SUCCESS != err) { eraseTrackingSession(client, sessionId); @@ -2434,7 +2434,7 @@ GnssAdapter::updateTracking(LocationAPI* client, uint32_t sessionId, mEngHubProxy->gnssSetFixMode(locPosMode); mEngHubProxy->gnssStartFix(); - mLocApi->startFix(locPosMode, new LocApiResponse(*getContext(), + mLocApi->startTimeBasedTracking(updatedOptions, new LocApiResponse(*getContext(), [this, client, sessionId, oldOptions] (LocationError err) { if (LOCATION_ERROR_SUCCESS != err) { // restore the old LocationOptions @@ -2446,35 +2446,6 @@ GnssAdapter::updateTracking(LocationAPI* client, uint32_t sessionId, )); } -void -GnssAdapter::setPositionModeCommand(LocPosMode& locPosMode) -{ - LOC_LOGD("%s]: min_interval %u mode %u", - __func__, locPosMode.min_interval, locPosMode.mode); - - struct MsgSetPositionMode : public LocMsg { - GnssAdapter& mAdapter; - LocApiBase& mApi; - LocPosMode mLocPosMode; - inline MsgSetPositionMode(GnssAdapter& adapter, - LocApiBase& api, - LocPosMode& locPosMode) : - LocMsg(), - mAdapter(adapter), - mApi(api), - mLocPosMode(locPosMode) {} - inline virtual void proc() const { - // saves the mode in adapter to be used when startTrackingCommand is called from ULP - if (mAdapter.setLocPositionMode(mLocPosMode)) { - mAdapter.mEngHubProxy->gnssSetFixMode(mLocPosMode); - mApi.setPositionMode(mLocPosMode); - } - } - }; - - sendMsg(new MsgSetPositionMode(*this, *mLocApi, locPosMode)); -} - void GnssAdapter::updateTrackingOptionsCommand(LocationAPI* client, uint32_t id, TrackingOptions& options) @@ -2487,52 +2458,108 @@ GnssAdapter::updateTrackingOptionsCommand(LocationAPI* client, uint32_t id, LocApiBase& mApi; LocationAPI* mClient; uint32_t mSessionId; - mutable TrackingOptions mTrackingOptions; + mutable TrackingOptions mOptions; inline MsgUpdateTracking(GnssAdapter& adapter, LocApiBase& api, LocationAPI* client, uint32_t sessionId, - TrackingOptions trackingOptions) : + TrackingOptions options) : LocMsg(), mAdapter(adapter), mApi(api), mClient(client), mSessionId(sessionId), - mTrackingOptions(trackingOptions) {} + mOptions(options) {} inline virtual void proc() const { - if (mAdapter.isTrackingSession(mClient, mSessionId)) { - LocationError err = LOCATION_ERROR_SUCCESS; - if (0 == mTrackingOptions.size) { - err = LOCATION_ERROR_INVALID_PARAMETER; - } else { - if (GNSS_POWER_MODE_INVALID != mTrackingOptions.powerMode && - !ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_AGPM_V02)) { - LOC_LOGv("Ignoring power mode, feature not supported."); - mTrackingOptions.powerMode = GNSS_POWER_MODE_INVALID; - } - if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_AGPM_V02) && - GNSS_POWER_MODE_M4 == mTrackingOptions.powerMode && - mTrackingOptions.tbm > TRACKING_TBM_THRESHOLD_MILLIS) { - LOC_LOGd("TBM (%d) > %d Falling back to M2 power mode", - mTrackingOptions.tbm, TRACKING_TBM_THRESHOLD_MILLIS); - mTrackingOptions.powerMode = GNSS_POWER_MODE_M2; - } - if (mTrackingOptions.minInterval < MIN_TRACKING_INTERVAL) { - mTrackingOptions.minInterval = MIN_TRACKING_INTERVAL; - } + // distance based tracking will need to know engine capabilities before it can start + if (!mAdapter.isEngineCapabilitiesKnown() && mOptions.minDistance > 0) { + mAdapter.mPendingMsgs.push_back(new MsgUpdateTracking(*this)); + return; + } + LocationError err = LOCATION_ERROR_SUCCESS; + bool isTimeBased = mAdapter.isTimeBasedTrackingSession(mClient, mSessionId); + bool isDistanceBased = mAdapter.isDistanceBasedTrackingSession(mClient, mSessionId); + if (!isTimeBased && !isDistanceBased) { + err = LOCATION_ERROR_ID_UNKNOWN; + } else if (0 == mOptions.size) { + err = LOCATION_ERROR_INVALID_PARAMETER; + } + if (LOCATION_ERROR_SUCCESS != err) { + mAdapter.reportResponse(mClient, err, mSessionId); + } else { + if (GNSS_POWER_MODE_M4 == mOptions.powerMode && + mOptions.tbm > TRACKING_TBM_THRESHOLD_MILLIS) { + LOC_LOGd("TBM (%d) > %d Falling back to M2 power mode", + mOptions.tbm, TRACKING_TBM_THRESHOLD_MILLIS); + mOptions.powerMode = GNSS_POWER_MODE_M2; + } + if (mOptions.minInterval < MIN_TRACKING_INTERVAL) { + mOptions.minInterval = MIN_TRACKING_INTERVAL; + } + // Now update session as required + if (isTimeBased && mOptions.minDistance > 0) { + // switch from time based to distance based // Api doesn't support multiple clients for time based tracking, so mutiplex bool reportToClientWithNoWait = - mAdapter.updateTrackingMultiplex(mClient, mSessionId, mTrackingOptions); - mAdapter.saveTrackingSession(mClient, mSessionId, mTrackingOptions); + mAdapter.stopTimeBasedTrackingMultiplex(mClient, mSessionId); + // erases the time based Session + mAdapter.eraseTrackingSession(mClient, mSessionId); + if (reportToClientWithNoWait) { + mAdapter.reportResponse(mClient, LOCATION_ERROR_SUCCESS, mSessionId); + } + // saves as distance based Session + mAdapter.saveTrackingSession(mClient, mSessionId, mOptions); + mApi.startDistanceBasedTracking(mSessionId, mOptions, + new LocApiResponse(*mAdapter.getContext(), + [] (LocationError /*err*/) {})); + } else if (isDistanceBased && mOptions.minDistance == 0) { + // switch from distance based to time based + mAdapter.eraseTrackingSession(mClient, mSessionId); + mApi.stopDistanceBasedTracking(mSessionId, new LocApiResponse( + *mAdapter.getContext(), + [&mAdapter = mAdapter, mSessionId = mSessionId, mOptions = mOptions, + mClient = mClient] (LocationError /*err*/) { + // Api doesn't support multiple clients for time based tracking, + // so mutiplex + bool reportToClientWithNoWait = + mAdapter.startTimeBasedTrackingMultiplex(mClient, mSessionId, + mOptions); + mAdapter.saveTrackingSession(mClient, mSessionId, mOptions); + + if (reportToClientWithNoWait) { + mAdapter.reportResponse(mClient, LOCATION_ERROR_SUCCESS, mSessionId); + } + })); + } else if (isTimeBased) { + // update time based tracking + // Api doesn't support multiple clients for time based tracking, so mutiplex + bool reportToClientWithNoWait = + mAdapter.updateTrackingMultiplex(mClient, mSessionId, mOptions); + mAdapter.saveTrackingSession(mClient, mSessionId, mOptions); if (reportToClientWithNoWait) { mAdapter.reportResponse(mClient, err, mSessionId); } + } else if (isDistanceBased) { + // restart distance based tracking + mApi.stopDistanceBasedTracking(mSessionId, new LocApiResponse( + *mAdapter.getContext(), + [&mAdapter = mAdapter, mSessionId = mSessionId, mOptions = mOptions, + mClient = mClient, &mApi = mApi] (LocationError err) { + if (LOCATION_ERROR_SUCCESS == err) { + mApi.startDistanceBasedTracking(mSessionId, mOptions, + new LocApiResponse(*mAdapter.getContext(), + [&mAdapter, mClient, mSessionId, mOptions] + (LocationError err) { + if (LOCATION_ERROR_SUCCESS == err) { + mAdapter.saveTrackingSession(mClient, mSessionId, mOptions); + } + mAdapter.reportResponse(mClient, err, mSessionId); + })); + } + })); } } - // we do not reportResponse for the case where there is no existing tracking session - // for the client and id being used, since updateTrackingCommand can be sent to both - // GnssAdapter & FlpAdapter by LocationAPI and we want to avoid incorrect error response } }; @@ -2547,19 +2574,21 @@ GnssAdapter::updateTrackingMultiplex(LocationAPI* client, uint32_t id, LocationSessionKey key(client, id); // get the session we are updating - auto it = mTrackingSessions.find(key); + auto it = mTimeBasedTrackingSessions.find(key); // cache the clients existing LocationOptions TrackingOptions oldOptions = it->second; // if session we are updating exists and the minInterval or powerMode has changed - if (it != mTrackingSessions.end() && (it->second.minInterval != trackingOptions.minInterval || + if (it != mTimeBasedTrackingSessions.end() && + (it->second.minInterval != trackingOptions.minInterval || it->second.powerMode != trackingOptions.powerMode)) { // find the smallest interval and powerMode, other than the session we are updating TrackingOptions multiplexedOptions = {}; // size is 0 until set for the first time GnssPowerMode multiplexedPowerMode = GNSS_POWER_MODE_INVALID; memset(&multiplexedOptions, 0, sizeof(multiplexedOptions)); - for (auto it2 = mTrackingSessions.begin(); it2 != mTrackingSessions.end(); ++it2) { + for (auto it2 = mTimeBasedTrackingSessions.begin(); + it2 != mTimeBasedTrackingSessions.end(); ++it2) { // if session is not the one we are updating and either interval // is not set or there is a new smallest interval, then set the new interval if (it2->first != key && (0 == multiplexedOptions.size || @@ -2586,7 +2615,7 @@ GnssAdapter::updateTrackingMultiplex(LocationAPI* client, uint32_t id, updateOptions = true; } // if only one session exists, then tracking should be updated with it - if (1 == mTrackingSessions.size()) { + if (1 == mTimeBasedTrackingSessions.size()) { multiplexedOptions = trackingOptions; updateOptions = true; } @@ -2621,19 +2650,33 @@ GnssAdapter::stopTrackingCommand(LocationAPI* client, uint32_t id) mClient(client), mSessionId(sessionId) {} inline virtual void proc() const { - if (mAdapter.isTrackingSession(mClient, mSessionId)) { - // Api doesn't support multiple clients for time based tracking, so mutiplex - bool reportToClientWithNoWait = - mAdapter.stopTrackingMultiplex(mClient, mSessionId); - mAdapter.eraseTrackingSession(mClient, mSessionId); + bool isTimeBased = mAdapter.isTimeBasedTrackingSession(mClient, mSessionId); + bool isDistanceBased = mAdapter.isDistanceBasedTrackingSession(mClient, mSessionId); + if (isTimeBased || isDistanceBased) { + if (isTimeBased) { + // Api doesn't support multiple clients for time based tracking, so mutiplex + bool reportToClientWithNoWait = + mAdapter.stopTimeBasedTrackingMultiplex(mClient, mSessionId); + mAdapter.eraseTrackingSession(mClient, mSessionId); - if (reportToClientWithNoWait) { - mAdapter.reportResponse(mClient, LOCATION_ERROR_SUCCESS, mSessionId); + if (reportToClientWithNoWait) { + mAdapter.reportResponse(mClient, LOCATION_ERROR_SUCCESS, mSessionId); + } + } else if (isDistanceBased) { + mApi.stopDistanceBasedTracking(mSessionId, new LocApiResponse( + *mAdapter.getContext(), + [&mAdapter = mAdapter, mSessionId = mSessionId, mClient = mClient] + (LocationError err) { + if (LOCATION_ERROR_SUCCESS == err) { + mAdapter.eraseTrackingSession(mClient, mSessionId); + } + mAdapter.reportResponse(mClient, err, mSessionId); + })); } + } else { + mAdapter.reportResponse(mClient, LOCATION_ERROR_ID_UNKNOWN, mSessionId); } - // we do not reportResponse for the case where there is no existing tracking session - // for the client and id being used, since stopTrackingCommand can be sent to both - // GnssAdapter & FlpAdapter by LocationAPI and we want to avoid incorrect error response + } }; @@ -2641,11 +2684,11 @@ GnssAdapter::stopTrackingCommand(LocationAPI* client, uint32_t id) } bool -GnssAdapter::stopTrackingMultiplex(LocationAPI* client, uint32_t id) +GnssAdapter::stopTimeBasedTrackingMultiplex(LocationAPI* client, uint32_t id) { bool reportToClientWithNoWait = true; - if (1 == mTrackingSessions.size()) { + if (1 == mTimeBasedTrackingSessions.size()) { stopTracking(client, id); // need to wait for QMI callback reportToClientWithNoWait = false; @@ -2653,13 +2696,14 @@ GnssAdapter::stopTrackingMultiplex(LocationAPI* client, uint32_t id) LocationSessionKey key(client, id); // get the session we are stopping - auto it = mTrackingSessions.find(key); - if (it != mTrackingSessions.end()) { + auto it = mTimeBasedTrackingSessions.find(key); + if (it != mTimeBasedTrackingSessions.end()) { // find the smallest interval and powerMode, other than the session we are stopping TrackingOptions multiplexedOptions = {}; // size is 0 until set for the first time GnssPowerMode multiplexedPowerMode = GNSS_POWER_MODE_INVALID; memset(&multiplexedOptions, 0, sizeof(multiplexedOptions)); - for (auto it2 = mTrackingSessions.begin(); it2 != mTrackingSessions.end(); ++it2) { + for (auto it2 = mTimeBasedTrackingSessions.begin(); + it2 != mTimeBasedTrackingSessions.end(); ++it2) { // if session is not the one we are stopping and either interval // is not set or there is a new smallest interval, then set the new interval if (it2->first != key && (0 == multiplexedOptions.size || @@ -2679,7 +2723,7 @@ GnssAdapter::stopTrackingMultiplex(LocationAPI* client, uint32_t id) it->second.powerMode < multiplexedPowerMode) { multiplexedOptions.powerMode = multiplexedPowerMode; // restart time based tracking with the newly updated options - startTracking(client, id, multiplexedOptions); + startTimeBasedTracking(client, id, multiplexedOptions); // need to wait for QMI callback reportToClientWithNoWait = false; } @@ -2798,7 +2842,6 @@ GnssAdapter::gnssNiResponseCommand(GnssNiResponse response, void* rawRequest) inline virtual ~MsgGnssNiResponse() { } inline virtual void proc() const { - const void *rawPayload = mPayload; mApi.informNiResponse(mResponse, mPayload); } }; @@ -3001,9 +3044,9 @@ GnssAdapter::reportPositionEvent(const UlpLocation& ulpLocation, } bool -GnssAdapter::needReport(const UlpLocation& ulpLocation, - enum loc_sess_status status, - LocPosTechMask techMask) { +GnssAdapter::needReportForGnssClient(const UlpLocation& ulpLocation, + enum loc_sess_status status, + LocPosTechMask techMask) { bool reported = false; // if engine hub is enabled, aka, any of the engine services is enabled, @@ -3016,47 +3059,77 @@ GnssAdapter::needReport(const UlpLocation& ulpLocation, return reported; } +bool +GnssAdapter::needReportForFlpClient(enum loc_sess_status status, + LocPosTechMask techMask) { + if ((status == LOC_SESS_INTERMEDIATE) && + !(techMask & LOC_POS_TECH_MASK_SENSORS) && + (!getAllowFlpNetworkFixes())) { + return false; + } else { + return true; + } +} + +bool +GnssAdapter::isFlpClient(LocationCallbacks& locationCallbacks) +{ + return (locationCallbacks.gnssLocationInfoCb == nullptr && + locationCallbacks.gnssSvCb == nullptr && + locationCallbacks.gnssNmeaCb == nullptr && + locationCallbacks.gnssDataCb == nullptr && + locationCallbacks.gnssMeasurementsCb == nullptr); +} + void GnssAdapter::reportPosition(const UlpLocation& ulpLocation, const GpsLocationExtended& locationExtended, enum loc_sess_status status, LocPosTechMask techMask) { - bool reported = needReport(ulpLocation, status, techMask); - mGnssSvIdUsedInPosAvail = false; - if (reported) { - if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_GNSS_SV_USED_DATA) { - mGnssSvIdUsedInPosAvail = true; - mGnssSvIdUsedInPosition = locationExtended.gnss_sv_used_ids; - } + bool reportToGnssClient = needReportForGnssClient(ulpLocation, status, techMask); + bool reportToFlpClient = needReportForFlpClient(status, techMask); + if (reportToGnssClient || reportToFlpClient) { GnssLocationInfoNotification locationInfo = {}; convertLocationInfo(locationInfo, locationExtended); convertLocation(locationInfo.location, ulpLocation, locationExtended, techMask); for (auto it=mClientData.begin(); it != mClientData.end(); ++it) { - if (nullptr != it->second.gnssLocationInfoCb) { - it->second.gnssLocationInfoCb(locationInfo); - } else if (nullptr != it->second.trackingCb) { - it->second.trackingCb(locationInfo.location); + if ((reportToFlpClient && isFlpClient(it->second)) || + (reportToGnssClient && !isFlpClient(it->second))) { + if (nullptr != it->second.gnssLocationInfoCb) { + it->second.gnssLocationInfoCb(locationInfo); + } else if (nullptr != it->second.trackingCb) { + it->second.trackingCb(locationInfo.location); + } } } - // if engine hub is running and the fix is from sensor, e.g.: DRE, - // inject DRE fix to modem - if ((1 == ContextBase::mGps_conf.POSITION_ASSISTED_CLOCK_ESTIMATOR_ENABLED) && - (true == initEngHubProxy()) && (LOC_POS_TECH_MASK_SENSORS & techMask)) { - mLocApi->injectPosition(locationInfo, false); + mGnssSvIdUsedInPosAvail = false; + if (reportToGnssClient) { + if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_GNSS_SV_USED_DATA) { + mGnssSvIdUsedInPosAvail = true; + mGnssSvIdUsedInPosition = locationExtended.gnss_sv_used_ids; + } + + // if engine hub is running and the fix is from sensor, e.g.: DRE, + // inject DRE fix to modem + if ((1 == ContextBase::mGps_conf.POSITION_ASSISTED_CLOCK_ESTIMATOR_ENABLED) && + (true == initEngHubProxy()) && (LOC_POS_TECH_MASK_SENSORS & techMask)) { + mLocApi->injectPosition(locationInfo, false); + } } } - if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER && !mTrackingSessions.empty()) { + if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER && + !mTimeBasedTrackingSessions.empty()) { /*Only BlankNMEA sentence needs to be processed and sent, if both lat, long is 0 & horReliability is not set. */ bool blank_fix = ((0 == ulpLocation.gpsLocation.latitude) && (0 == ulpLocation.gpsLocation.longitude) && (LOC_RELIABILITY_NOT_SET == locationExtended.horizontal_reliability)); - uint8_t generate_nmea = (reported && status != LOC_SESS_FAILURE && !blank_fix); + uint8_t generate_nmea = (reportToGnssClient && status != LOC_SESS_FAILURE && !blank_fix); std::vector nmeaArraystr; loc_nmea_generate_pos(ulpLocation, locationExtended, mLocSystemInfo, generate_nmea, nmeaArraystr); @@ -3153,7 +3226,8 @@ GnssAdapter::reportSv(GnssSvNotification& svNotify) } } - if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER && !mTrackingSessions.empty()) { + if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER && + !mTimeBasedTrackingSessions.empty()) { std::vector nmeaArraystr; loc_nmea_generate_sv(svNotify, nmeaArraystr); stringstream ss; @@ -3348,8 +3422,8 @@ GnssAdapter::reportLocationSystemInfo(const LocationSystemInfo & locationSystemI LEAP_SECOND_SYS_INFO_CURRENT_LEAP_SECONDS_BIT; dstLeapSecondSysInfo.leapSecondCurrent = srcLeapSecondSysInfo.leapSecondCurrent; } - // once leap second change event is complete, modem may send up event invalidate the leap second - // change info while AP is still processing report during leap second transition + // once leap second change event is complete, modem may send up event invalidate the leap + // second change info while AP is still processing report during leap second transition // so, we choose to keep this info around even though it is old if (srcLeapSecondSysInfo.leapSecondInfoMask & LEAP_SECOND_SYS_INFO_LEAP_SECOND_CHANGE_BIT) { dstLeapSecondSysInfo.leapSecondInfoMask |= LEAP_SECOND_SYS_INFO_LEAP_SECOND_CHANGE_BIT; diff --git a/gnss/GnssAdapter.h b/gnss/GnssAdapter.h index e304fe6e..1ed11517 100644 --- a/gnss/GnssAdapter.h +++ b/gnss/GnssAdapter.h @@ -30,13 +30,14 @@ #define GNSS_ADAPTER_H #include -#include +#include #include #include #include #include #include #include +#include #define MAX_URL_LEN 256 #define NMEA_SENTENCE_MAX_LENGTH 200 @@ -48,6 +49,9 @@ class GnssAdapter; +typedef std::map LocationSessionMap; +typedef std::map TrackingOptionsMap; + class OdcpiTimer : public LocTimer { public: OdcpiTimer(GnssAdapter* adapter) : @@ -128,19 +132,16 @@ typedef std::function GnssEnergyConsumedCallback; -typedef void (*removeClientCompleteCallback)(LocationAPI* client); +typedef void (*powerStateCallback)(bool on); class GnssAdapter : public LocAdapterBase { /* ==== Engine Hub ===================================================================== */ EngineHubProxyBase* mEngHubProxy; - /* ==== CLIENT ========================================================================= */ - typedef std::map ClientDataMap; - ClientDataMap mClientData; - /* ==== TRACKING ======================================================================= */ - TrackingOptionsMap mTrackingSessions; + TrackingOptionsMap mTimeBasedTrackingSessions; + LocationSessionMap mDistanceBasedTrackingSessions; LocPosMode mLocPositionMode; GnssSvUsedInPosition mGnssSvIdUsedInPosition; bool mGnssSvIdUsedInPosAvail; @@ -185,9 +186,12 @@ class GnssAdapter : public LocAdapterBase { /* === Misc ===================================================================== */ BlockCPIInfo mBlockCPIInfo; + bool mPowerOn; + uint32_t mAllowFlpNetworkFixes; /* === Misc callback from QMI LOC API ============================================== */ GnssEnergyConsumedCallback mGnssEnergyConsumedCb; + powerStateCallback mPowerStateCb; /*==== CONVERSION ===================================================================*/ static void convertOptions(LocPosMode& out, const TrackingOptions& trackingOptions); @@ -200,6 +204,13 @@ class GnssAdapter : public LocAdapterBase { /* ======== UTILITIES ================================================================== */ inline void initOdcpi(const OdcpiRequestCallback& callback); inline void injectOdcpi(const Location& location); + static bool isFlpClient(LocationCallbacks& locationCallbacks); + +protected: + + /* ==== CLIENT ========================================================================= */ + virtual void updateClientsEventMask(); + virtual void stopClientSessions(LocationAPI* client); public: @@ -214,21 +225,7 @@ public: /* ==== CLIENT ========================================================================= */ /* ======== COMMANDS ====(Called from Client Thread)==================================== */ - void addClientCommand(LocationAPI* client, const LocationCallbacks& callbacks); - void removeClientCommand(LocationAPI* client, - removeClientCompleteCallback rmClientCb); - void requestCapabilitiesCommand(LocationAPI* client); - /* ======== UTILITIES ================================================================== */ - void saveClient(LocationAPI* client, const LocationCallbacks& callbacks); - void eraseClient(LocationAPI* client); - void notifyClientOfCachedLocationSystemInfo(LocationAPI* client, - const LocationCallbacks& callbacks); - void updateClientsEventMask(); - void stopClientSessions(LocationAPI* client); - LocationCallbacks getClientCallbacks(LocationAPI* client); - LocationCapabilitiesMask getCapabilities(); - void broadcastCapabilities(LocationCapabilitiesMask); - void setSuplHostServer(const char* server, int port, LocServerType type); + virtual void addClientCommand(LocationAPI* client, const LocationCallbacks& callbacks); /* ==== TRACKING ======================================================================= */ /* ======== COMMANDS ====(Called from Client Thread)==================================== */ @@ -237,11 +234,12 @@ public: void updateTrackingOptionsCommand( LocationAPI* client, uint32_t id, TrackingOptions& trackingOptions); void stopTrackingCommand(LocationAPI* client, uint32_t id); - virtual void setPositionModeCommand(LocPosMode& locPosMode); /* ======== RESPONSES ================================================================== */ void reportResponse(LocationAPI* client, LocationError err, uint32_t sessionId); /* ======== UTILITIES ================================================================== */ bool hasTrackingCallback(LocationAPI* client); + bool isTimeBasedTrackingSession(LocationAPI* client, uint32_t sessionId); + bool isDistanceBasedTrackingSession(LocationAPI* client, uint32_t sessionId); bool hasMeasurementsCallback(LocationAPI* client); bool isTrackingSession(LocationAPI* client, uint32_t sessionId); void saveTrackingSession(LocationAPI* client, uint32_t sessionId, @@ -251,16 +249,16 @@ public: bool setLocPositionMode(const LocPosMode& mode); LocPosMode& getLocPositionMode() { return mLocPositionMode; } - bool startTrackingMultiplex(LocationAPI* client, uint32_t sessionId, - const TrackingOptions& trackingOptions); - void startTracking(LocationAPI* client, uint32_t sessionId, - const TrackingOptions& trackingOptions); - bool stopTrackingMultiplex(LocationAPI* client, uint32_t id); + bool startTimeBasedTrackingMultiplex(LocationAPI* client, uint32_t sessionId, + const TrackingOptions& trackingOptions); + void startTimeBasedTracking(LocationAPI* client, uint32_t sessionId, + const TrackingOptions& trackingOptions); + bool stopTimeBasedTrackingMultiplex(LocationAPI* client, uint32_t id); void stopTracking(LocationAPI* client, uint32_t id); bool updateTrackingMultiplex(LocationAPI* client, uint32_t id, - const TrackingOptions& trackingOptions); + const TrackingOptions& trackingOptions); void updateTracking(LocationAPI* client, uint32_t sessionId, - const TrackingOptions& updatedOptions, const TrackingOptions& oldOptions); + const TrackingOptions& updatedOptions, const TrackingOptions& oldOptions); /* ==== NI ============================================================================= */ /* ======== COMMANDS ====(Called from Client Thread)==================================== */ @@ -335,7 +333,9 @@ public: { mControlCallbacks = controlCallbacks; } void setAfwControlId(uint32_t id) { mPowerVoteId = id; } uint32_t getAfwControlId() { return mPowerVoteId; } - virtual bool isInSession() { return !mTrackingSessions.empty(); } + void setPowerVoteId(uint32_t id) { mPowerVoteId = id; } + uint32_t getPowerVoteId() { return mPowerVoteId; } + virtual bool isInSession() { return !mTimeBasedTrackingSessions.empty(); } void initDefaultAgps(); bool initEngHubProxy(); void odcpiTimerExpireEvent(); @@ -374,8 +374,9 @@ public: virtual void reportNfwNotificationEvent(GnssNfwNotification& notification); /* ======== UTILITIES ================================================================= */ - bool needReport(const UlpLocation& ulpLocation, + bool needReportForGnssClient(const UlpLocation& ulpLocation, enum loc_sess_status status, LocPosTechMask techMask); + bool needReportForFlpClient(enum loc_sess_status status, LocPosTechMask techMask); void reportPosition(const UlpLocation &ulpLocation, const GpsLocationExtended &locationExtended, enum loc_sess_status status, @@ -433,6 +434,19 @@ public: void injectTimeCommand(int64_t time, int64_t timeReference, int32_t uncertainty); void blockCPICommand(double latitude, double longitude, float accuracy, int blockDurationMsec, double latLonDiffThreshold); + + /* ==== MISCELLANEOUS ================================================================== */ + /* ======== COMMANDS ====(Called from Client Thread)==================================== */ + void getPowerStateChangesCommand(void* powerStateCb); + /* ======== UTILITIES ================================================================== */ + void reportPowerStateIfChanged(); + void savePowerStateCallback(powerStateCallback powerStateCb){ mPowerStateCb = powerStateCb; } + bool getPowerState() { return mPowerOn; } + void setAllowFlpNetworkFixes(uint32_t allow) { mAllowFlpNetworkFixes = allow; } + uint32_t getAllowFlpNetworkFixes() { return mAllowFlpNetworkFixes; } + void setSuplHostServer(const char* server, int port, LocServerType type); + void notifyClientOfCachedLocationSystemInfo(LocationAPI* client, + const LocationCallbacks& callbacks); }; #endif //GNSS_ADAPTER_H diff --git a/gnss/XtraSystemStatusObserver.h b/gnss/XtraSystemStatusObserver.h index cbbeda61..24f9776c 100644 --- a/gnss/XtraSystemStatusObserver.h +++ b/gnss/XtraSystemStatusObserver.h @@ -46,7 +46,7 @@ public : inline XtraSystemStatusObserver(IOsObserver* sysStatObs, const MsgTask* msgTask): mSystemStatusObsrvr(sysStatObs), mMsgTask(msgTask), mGpsLock(-1), mConnections(~0), mXtraThrottle(true), mReqStatusReceived(false), - mDelayLocTimer(*this), mIsConnectivityStatusKnown (false) { + mIsConnectivityStatusKnown (false), mDelayLocTimer(*this) { subscribe(true); startListeningNonBlocking(LOC_IPC_HAL); mDelayLocTimer.start(100 /*.1 sec*/, false); diff --git a/gnss/location_gnss.cpp b/gnss/location_gnss.cpp index 45ad292c..23ec2cf1 100644 --- a/gnss/location_gnss.cpp +++ b/gnss/location_gnss.cpp @@ -70,6 +70,7 @@ static void getGnssEnergyConsumed(GnssEnergyConsumedCallback energyConsumedCb); static void enableNfwLocationAccess(bool enable); static void nfwInit(const NfwCbInfo& cbInfo); static uint8_t getGpsLock(); +static void getPowerStateChanges(void* powerStateCb); static void odcpiInit(const OdcpiRequestCallback& callback); static void odcpiInject(const Location& location); @@ -112,7 +113,8 @@ static const GnssInterface gGnssInterface = { getGnssEnergyConsumed, enableNfwLocationAccess, nfwInit, - getGpsLock + getGpsLock, + getPowerStateChanges }; #ifndef DEBUG_X86 @@ -378,3 +380,10 @@ static uint8_t getGpsLock() { } } +static void getPowerStateChanges(void* powerStateCb) +{ + if (NULL != gGnssAdapter) { + gGnssAdapter->getPowerStateChangesCommand(powerStateCb); + } +} + diff --git a/gps_vendor_product.mk b/gps_vendor_product.mk index c21a2827..6e938b35 100644 --- a/gps_vendor_product.mk +++ b/gps_vendor_product.mk @@ -10,3 +10,5 @@ PRODUCT_PACKAGES += libloc_core PRODUCT_PACKAGES += libgnss PRODUCT_PACKAGES += liblocation_api PRODUCT_PACKAGES += libgps.utils +PRODUCT_PACKAGES += libbatching +PRODUCT_PACKAGES += libgeofencing diff --git a/location/LocationAPI.cpp b/location/LocationAPI.cpp index e9f2ee4d..f3088bcd 100644 --- a/location/LocationAPI.cpp +++ b/location/LocationAPI.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2017 The Linux Foundation. All rights reserved. +/* 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 @@ -57,24 +57,15 @@ typedef struct { LocationControlCallbacks controlCallbacks; GnssInterface* gnssInterface; GeofenceInterface* geofenceInterface; - FlpInterface* flpInterface; + BatchingInterface* batchingInterface; } LocationAPIData; static LocationAPIData gData = {}; static pthread_mutex_t gDataMutex = PTHREAD_MUTEX_INITIALIZER; static bool gGnssLoadFailed = false; -static bool gFlpLoadFailed = false; +static bool gBatchingLoadFailed = false; static bool gGeofenceLoadFailed = false; -static bool needsGnssTrackingInfo(LocationCallbacks& locationCallbacks) -{ - return (locationCallbacks.gnssLocationInfoCb != nullptr || - locationCallbacks.gnssSvCb != nullptr || - locationCallbacks.gnssNmeaCb != nullptr || - locationCallbacks.gnssDataCb != nullptr || - locationCallbacks.gnssMeasurementsCb != nullptr); -} - static bool isGnssClient(LocationCallbacks& locationCallbacks) { return (locationCallbacks.gnssNiCb != nullptr || @@ -83,10 +74,9 @@ static bool isGnssClient(LocationCallbacks& locationCallbacks) locationCallbacks.gnssMeasurementsCb != nullptr); } -static bool isFlpClient(LocationCallbacks& locationCallbacks) +static bool isBatchingClient(LocationCallbacks& locationCallbacks) { - return (locationCallbacks.trackingCb != nullptr || - locationCallbacks.batchingCb != nullptr); + return (locationCallbacks.batchingCb != nullptr); } static bool isGeofenceClient(LocationCallbacks& locationCallbacks) @@ -153,9 +143,9 @@ void onGnssRemoveClientCompleteCb (LocationAPI* client) client->onRemoveClientCompleteCb (LOCATION_ADAPTER_GNSS_TYPE_BIT); } -void onFlpRemoveClientCompleteCb (LocationAPI* client) +void onBatchingRemoveClientCompleteCb (LocationAPI* client) { - client->onRemoveClientCompleteCb (LOCATION_ADAPTER_FLP_TYPE_BIT); + client->onRemoveClientCompleteCb (LOCATION_ADAPTER_BATCHING_TYPE_BIT); } void onGeofenceRemoveClientCompleteCb (LocationAPI* client) @@ -197,21 +187,21 @@ LocationAPI::createInstance(LocationCallbacks& locationCallbacks) } } - if (isFlpClient(locationCallbacks)) { - if (NULL == gData.flpInterface && !gFlpLoadFailed) { - gData.flpInterface = - (FlpInterface*)loadLocationInterface("libflp.so", "getFlpInterface"); - if (NULL == gData.flpInterface) { - gFlpLoadFailed = true; - LOC_LOGW("%s:%d]: No flp interface available", __func__, __LINE__); + if (isBatchingClient(locationCallbacks)) { + if (NULL == gData.batchingInterface && !gBatchingLoadFailed) { + gData.batchingInterface = + (BatchingInterface*)loadLocationInterface("libbatching.so", "getBatchingInterface"); + if (NULL == gData.batchingInterface) { + gBatchingLoadFailed = true; + LOC_LOGW("%s:%d]: No batching interface available", __func__, __LINE__); } else { - gData.flpInterface->initialize(); + gData.batchingInterface->initialize(); } } - if (NULL != gData.flpInterface) { - gData.flpInterface->addClient(newLocationAPI, locationCallbacks); + if (NULL != gData.batchingInterface) { + gData.batchingInterface->addClient(newLocationAPI, locationCallbacks); if (!requestedCapabilities) { - gData.flpInterface->requestCapabilities(newLocationAPI); + gData.batchingInterface->requestCapabilities(newLocationAPI); requestedCapabilities = true; } } @@ -220,7 +210,7 @@ LocationAPI::createInstance(LocationCallbacks& locationCallbacks) if (isGeofenceClient(locationCallbacks)) { if (NULL == gData.geofenceInterface && !gGeofenceLoadFailed) { gData.geofenceInterface = - (GeofenceInterface*)loadLocationInterface("libgeofence.so", "getGeofenceInterface"); + (GeofenceInterface*)loadLocationInterface("libgeofencing.so", "getGeofenceInterface"); if (NULL == gData.geofenceInterface) { gGeofenceLoadFailed = true; LOC_LOGW("%s:%d]: No geofence interface available", __func__, __LINE__); @@ -254,13 +244,14 @@ LocationAPI::destroy(locationApiDestroyCompleteCallback destroyCompleteCb) if (it != gData.clientData.end()) { bool removeFromGnssInf = (isGnssClient(it->second) && NULL != gData.gnssInterface); - bool removeFromFlpInf = - (isFlpClient(it->second) && NULL != gData.flpInterface); + bool removeFromBatchingInf = + (isBatchingClient(it->second) && NULL != gData.batchingInterface); bool removeFromGeofenceInf = (isGeofenceClient(it->second) && NULL != gData.geofenceInterface); - bool needToWait = (removeFromGnssInf || removeFromFlpInf || removeFromGeofenceInf); - LOC_LOGe("removeFromGnssInf: %d, removeFromFlpInf: %d, removeFromGeofenceInf: %d, need %d", - removeFromGnssInf, removeFromFlpInf, removeFromGeofenceInf, needToWait); + bool needToWait = (removeFromGnssInf || removeFromBatchingInf || removeFromGeofenceInf); + LOC_LOGe("removeFromGnssInf: %d, removeFromBatchingInf: %d, removeFromGeofenceInf: %d," + "need %d", removeFromGnssInf, removeFromBatchingInf, removeFromGeofenceInf, + needToWait); if ((NULL != destroyCompleteCb) && (true == needToWait)) { LocationAPIDestroyCbData destroyCbData = {}; @@ -271,7 +262,7 @@ LocationAPI::destroy(locationApiDestroyCompleteCallback destroyCompleteCb) destroyCbData.waitAdapterMask = (removeFromGnssInf ? LOCATION_ADAPTER_GNSS_TYPE_BIT : 0); destroyCbData.waitAdapterMask |= - (removeFromFlpInf ? LOCATION_ADAPTER_FLP_TYPE_BIT : 0); + (removeFromBatchingInf ? LOCATION_ADAPTER_BATCHING_TYPE_BIT : 0); destroyCbData.waitAdapterMask |= (removeFromGeofenceInf ? LOCATION_ADAPTER_GEOFENCE_TYPE_BIT : 0); gData.destroyClientData[this] = destroyCbData; @@ -282,9 +273,9 @@ LocationAPI::destroy(locationApiDestroyCompleteCallback destroyCompleteCb) gData.gnssInterface->removeClient(it->first, onGnssRemoveClientCompleteCb); } - if (removeFromFlpInf) { - gData.flpInterface->removeClient(it->first, - onFlpRemoveClientCompleteCb); + if (removeFromBatchingInf) { + gData.batchingInterface->removeClient(it->first, + onBatchingRemoveClientCompleteCb); } if (removeFromGeofenceInf) { gData.geofenceInterface->removeClient(it->first, @@ -347,27 +338,27 @@ LocationAPI::updateCallbacks(LocationCallbacks& locationCallbacks) } } - if (isFlpClient(locationCallbacks)) { - if (NULL == gData.flpInterface && !gFlpLoadFailed) { - gData.flpInterface = - (FlpInterface*)loadLocationInterface("libflp.so", "getFlpInterface"); - if (NULL == gData.flpInterface) { - gFlpLoadFailed = true; - LOC_LOGW("%s:%d]: No flp interface available", __func__, __LINE__); + if (isBatchingClient(locationCallbacks)) { + if (NULL == gData.batchingInterface && !gBatchingLoadFailed) { + gData.batchingInterface = + (BatchingInterface*)loadLocationInterface("libbatching.so", "getBatchingInterface"); + if (NULL == gData.batchingInterface) { + gBatchingLoadFailed = true; + LOC_LOGW("%s:%d]: No batching interface available", __func__, __LINE__); } else { - gData.flpInterface->initialize(); + gData.batchingInterface->initialize(); } } - if (NULL != gData.flpInterface) { + if (NULL != gData.batchingInterface) { // either adds new Client or updates existing Client - gData.flpInterface->addClient(this, locationCallbacks); + gData.batchingInterface->addClient(this, locationCallbacks); } } if (isGeofenceClient(locationCallbacks)) { if (NULL == gData.geofenceInterface && !gGeofenceLoadFailed) { gData.geofenceInterface = - (GeofenceInterface*)loadLocationInterface("libgeofence.so", "getGeofenceInterface"); + (GeofenceInterface*)loadLocationInterface("libgeofencing.so", "getGeofenceInterface"); if (NULL == gData.geofenceInterface) { gGeofenceLoadFailed = true; LOC_LOGW("%s:%d]: No geofence interface available", __func__, __LINE__); @@ -394,16 +385,10 @@ LocationAPI::startTracking(TrackingOptions& trackingOptions) auto it = gData.clientData.find(this); if (it != gData.clientData.end()) { - if (NULL != gData.flpInterface && trackingOptions.minDistance > 0) { - id = gData.flpInterface->startTracking(this, trackingOptions); - } else if (NULL != gData.gnssInterface && needsGnssTrackingInfo(it->second)) { - id = gData.gnssInterface->startTracking(this, trackingOptions); - } else if (NULL != gData.flpInterface) { - id = gData.flpInterface->startTracking(this, trackingOptions); - } else if (NULL != gData.gnssInterface) { + if (NULL != gData.gnssInterface) { id = gData.gnssInterface->startTracking(this, trackingOptions); } else { - LOC_LOGE("%s:%d]: No gnss/flp interface available for Location API client %p ", + LOC_LOGE("%s:%d]: No gnss interface available for Location API client %p ", __func__, __LINE__, this); } } else { @@ -422,16 +407,10 @@ LocationAPI::stopTracking(uint32_t id) auto it = gData.clientData.find(this); if (it != gData.clientData.end()) { - // we don't know if tracking was started on flp or gnss, so we call stop on both, where - // stopTracking call to the incorrect interface will fail without response back to client if (gData.gnssInterface != NULL) { gData.gnssInterface->stopTracking(this, id); - } - if (gData.flpInterface != NULL) { - gData.flpInterface->stopTracking(this, id); - } - if (gData.flpInterface == NULL && gData.gnssInterface == NULL) { - LOC_LOGE("%s:%d]: No gnss/flp interface available for Location API client %p ", + } else { + LOC_LOGE("%s:%d]: No gnss interface available for Location API client %p ", __func__, __LINE__, this); } } else { @@ -450,16 +429,10 @@ LocationAPI::updateTrackingOptions( auto it = gData.clientData.find(this); if (it != gData.clientData.end()) { - // we don't know if tracking was started on flp or gnss, so we call update on both, where - // updateTracking call to the incorrect interface will fail without response back to client if (gData.gnssInterface != NULL) { gData.gnssInterface->updateTrackingOptions(this, id, trackingOptions); - } - if (gData.flpInterface != NULL) { - gData.flpInterface->updateTrackingOptions(this, id, trackingOptions); - } - if (gData.flpInterface == NULL && gData.gnssInterface == NULL) { - LOC_LOGE("%s:%d]: No gnss/flp interface available for Location API client %p ", + } else { + LOC_LOGE("%s:%d]: No gnss interface available for Location API client %p ", __func__, __LINE__, this); } } else { @@ -476,10 +449,10 @@ LocationAPI::startBatching(BatchingOptions &batchingOptions) uint32_t id = 0; pthread_mutex_lock(&gDataMutex); - if (NULL != gData.flpInterface) { - id = gData.flpInterface->startBatching(this, batchingOptions); + if (NULL != gData.batchingInterface) { + id = gData.batchingInterface->startBatching(this, batchingOptions); } else { - LOC_LOGE("%s:%d]: No flp interface available for Location API client %p ", + LOC_LOGE("%s:%d]: No batching interface available for Location API client %p ", __func__, __LINE__, this); } @@ -492,10 +465,10 @@ LocationAPI::stopBatching(uint32_t id) { pthread_mutex_lock(&gDataMutex); - if (NULL != gData.flpInterface) { - gData.flpInterface->stopBatching(this, id); + if (NULL != gData.batchingInterface) { + gData.batchingInterface->stopBatching(this, id); } else { - LOC_LOGE("%s:%d]: No flp interface available for Location API client %p ", + LOC_LOGE("%s:%d]: No batching interface available for Location API client %p ", __func__, __LINE__, this); } @@ -507,10 +480,10 @@ LocationAPI::updateBatchingOptions(uint32_t id, BatchingOptions& batchOptions) { pthread_mutex_lock(&gDataMutex); - if (NULL != gData.flpInterface) { - gData.flpInterface->updateBatchingOptions(this, id, batchOptions); + if (NULL != gData.batchingInterface) { + gData.batchingInterface->updateBatchingOptions(this, id, batchOptions); } else { - LOC_LOGE("%s:%d]: No flp interface available for Location API client %p ", + LOC_LOGE("%s:%d]: No batching interface available for Location API client %p ", __func__, __LINE__, this); } @@ -522,10 +495,10 @@ LocationAPI::getBatchedLocations(uint32_t id, size_t count) { pthread_mutex_lock(&gDataMutex); - if (gData.flpInterface != NULL) { - gData.flpInterface->getBatchedLocations(this, id, count); + if (gData.batchingInterface != NULL) { + gData.batchingInterface->getBatchedLocations(this, id, count); } else { - LOC_LOGE("%s:%d]: No flp interface available for Location API client %p ", + LOC_LOGE("%s:%d]: No batching interface available for Location API client %p ", __func__, __LINE__, this); } diff --git a/location/LocationDataTypes.h b/location/LocationDataTypes.h index 0a2c0608..1cb63fe3 100644 --- a/location/LocationDataTypes.h +++ b/location/LocationDataTypes.h @@ -1336,7 +1336,7 @@ typedef std::function