diff options
author | Robin Peng <robinpeng@google.com> | 2019-05-02 14:59:06 +0800 |
---|---|---|
committer | Robin Peng <robinpeng@google.com> | 2019-05-02 15:03:31 +0800 |
commit | 46d54eed524a863536da3390830b74be03f79282 (patch) | |
tree | 16974137e59c2831a45947e11bad87d79fd60cd2 | |
parent | c28ceeeaf9d5085b36146e6930d23aa1c0d34d17 (diff) | |
parent | bd25bb0ea834034debd4935d31647ba226e7ffd7 (diff) | |
download | gps-46d54eed524a863536da3390830b74be03f79282.tar.gz |
Merge remote-tracking branch 'goog/qcom/release/LA.UM.8.1.R1.09.00.00.529.037' into qt-dev
Bug: 131580615
Change-Id: Iaf60110b0da8b16bba6f135ebc962804bd2e33d8
113 files changed, 10838 insertions, 1427 deletions
diff --git a/android/1.0/Android.mk b/android/1.0/Android.mk index 434b432..122ff8d 100644 --- a/android/1.0/Android.mk +++ b/android/1.0/Android.mk @@ -81,4 +81,9 @@ LOCAL_SHARED_LIBRARIES += \ android.hardware.gnss@1.0 \ LOCAL_CFLAGS += $(GNSS_CFLAGS) + +ifneq ($(LOC_HIDL_VERSION),) +LOCAL_CFLAGS += -DLOC_HIDL_VERSION='"$(LOC_HIDL_VERSION)"' +endif + include $(BUILD_EXECUTABLE) diff --git a/android/1.0/Gnss.cpp b/android/1.0/Gnss.cpp index 6e34f1e..93b320b 100644 --- a/android/1.0/Gnss.cpp +++ b/android/1.0/Gnss.cpp @@ -27,7 +27,7 @@ #include "Gnss.h" #include <LocationUtil.h> -typedef void* (getLocationInterface)(); +typedef const GnssInterface* (getLocationInterface)(); namespace android { namespace hardware { @@ -84,7 +84,7 @@ GnssAPIClient* Gnss::getApi() { return mApi; } -GnssInterface* Gnss::getGnssInterface() { +const GnssInterface* Gnss::getGnssInterface() { static bool getGnssInterfaceFailed = false; if (nullptr == mGnssInterface && !getGnssInterfaceFailed) { LOC_LOGD("%s]: loading libgnss.so::getGnssInterface ...", __func__); @@ -105,7 +105,7 @@ GnssInterface* Gnss::getGnssInterface() { if (NULL == getter) { getGnssInterfaceFailed = true; } else { - mGnssInterface = (GnssInterface*)(*getter)(); + mGnssInterface = (const GnssInterface*)(*getter)(); } } return mGnssInterface; @@ -238,7 +238,7 @@ Return<bool> Gnss::injectLocation(double latitudeDegrees, double longitudeDegrees, float accuracyMeters) { ENTRY_LOG_CALLFLOW(); - GnssInterface* gnssInterface = getGnssInterface(); + const GnssInterface* gnssInterface = getGnssInterface(); if (nullptr != gnssInterface) { gnssInterface->injectLocation(latitudeDegrees, longitudeDegrees, accuracyMeters); return true; @@ -250,7 +250,7 @@ Return<bool> Gnss::injectLocation(double latitudeDegrees, Return<bool> Gnss::injectTime(int64_t timeMs, int64_t timeReferenceMs, int32_t uncertaintyMs) { ENTRY_LOG_CALLFLOW(); - GnssInterface* gnssInterface = getGnssInterface(); + const GnssInterface* gnssInterface = getGnssInterface(); if (nullptr != gnssInterface) { gnssInterface->injectTime(timeMs, timeReferenceMs, uncertaintyMs); return true; diff --git a/android/1.0/Gnss.h b/android/1.0/Gnss.h index c23b337..900a510 100644 --- a/android/1.0/Gnss.h +++ b/android/1.0/Gnss.h @@ -99,7 +99,7 @@ struct Gnss : public IGnss { GnssAPIClient* getApi(); Return<bool> setGnssNiCb(const sp<IGnssNiCallback>& niCb); Return<bool> updateConfiguration(GnssConfig& gnssConfig); - GnssInterface* getGnssInterface(); + const GnssInterface* getGnssInterface(); // Callback for ODCPI request void odcpiRequestCb(const OdcpiRequestInfo& request); @@ -129,7 +129,7 @@ struct Gnss : public IGnss { sp<V1_0::IGnssCallback> mGnssCbIface = nullptr; sp<V1_0::IGnssNiCallback> mGnssNiCbIface = nullptr; GnssConfig mPendingConfig; - GnssInterface* mGnssInterface = nullptr; + const GnssInterface* mGnssInterface = nullptr; }; extern "C" IGnss* HIDL_FETCH_IGnss(const char* name); diff --git a/android/1.0/location_api/GnssAPIClient.cpp b/android/1.0/location_api/GnssAPIClient.cpp index d04939e..a36d2b4 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 <LocDualContext.h> +#include <LocContext.h> namespace android { namespace hardware { @@ -110,9 +110,9 @@ void GnssAPIClient::gnssUpdateCallbacks(const sp<IGnssCallback>& 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.0/service.cpp b/android/1.0/service.cpp index ee61a10..04bb8ab 100644 --- a/android/1.0/service.cpp +++ b/android/1.0/service.cpp @@ -22,22 +22,63 @@ #include <android/hardware/gnss/1.0/IGnss.h> #include <hidl/LegacySupport.h> - #include "loc_cfg.h" +#include "loc_misc_utils.h" + extern "C" { #include "vndfwk-detect.h" } +#ifdef ARCH_ARM_32 +#define DEFAULT_HW_BINDER_MEM_SIZE 65536 +#endif + using android::hardware::gnss::V1_0::IGnss; -using android::hardware::defaultPassthroughServiceImplementation; + +using android::hardware::configureRpcThreadpool; +using android::hardware::registerPassthroughServiceImplementation; +using android::hardware::joinRpcThreadpool; + +using android::status_t; +using android::OK; + +typedef int vendorEnhancedServiceMain(int /* argc */, char* /* argv */ []); int main() { + + ALOGI("%s", __FUNCTION__); + bool vendorEnhanced = isRunningWithVendorEnhancedFramework(); setVendorEnhanced(vendorEnhanced); - if (!vendorEnhanced) { - return defaultPassthroughServiceImplementation<IGnss>(); +#ifdef ARCH_ARM_32 + android::hardware::ProcessState::initWithMmapSize((size_t)(DEFAULT_HW_BINDER_MEM_SIZE)); +#endif + configureRpcThreadpool(1, true); + status_t status; + + status = registerPassthroughServiceImplementation<IGnss>(); + if (status == OK) { + if (vendorEnhanced) { + #ifdef LOC_HIDL_VERSION + #define VENDOR_ENHANCED_LIB "vendor.qti.gnss@" LOC_HIDL_VERSION "-service.so" + + void* libHandle = NULL; + vendorEnhancedServiceMain* vendorEnhancedMainMethod = (vendorEnhancedServiceMain*) + dlGetSymFromLib(libHandle, VENDOR_ENHANCED_LIB, "main"); + if (NULL != vendorEnhancedMainMethod) { + (*vendorEnhancedMainMethod)(0, NULL); + } + #else + ALOGE("LOC_HIDL_VERSION not defined."); + #endif + } + + joinRpcThreadpool(); + } else { - return -1; + ALOGE("Error while registering IGnss 1.0 service: %d", status); } + + return 0; } diff --git a/android/1.1/Android.mk b/android/1.1/Android.mk index 33e5b0d..5c97f40 100644 --- a/android/1.1/Android.mk +++ b/android/1.1/Android.mk @@ -83,4 +83,9 @@ LOCAL_SHARED_LIBRARIES += \ android.hardware.gnss@1.1 \ LOCAL_CFLAGS += $(GNSS_CFLAGS) + +ifneq ($(LOC_HIDL_VERSION),) +LOCAL_CFLAGS += -DLOC_HIDL_VERSION='"$(LOC_HIDL_VERSION)"' +endif + include $(BUILD_EXECUTABLE) diff --git a/android/1.1/Gnss.cpp b/android/1.1/Gnss.cpp index fca72e6..8d5d8a8 100644 --- a/android/1.1/Gnss.cpp +++ b/android/1.1/Gnss.cpp @@ -27,7 +27,7 @@ #include "Gnss.h" #include <LocationUtil.h> -typedef void* (getLocationInterface)(); +typedef const GnssInterface* (getLocationInterface)(); #define IMAGES_INFO_FILE "/sys/devices/soc0/images" #define DELIMITER ";" @@ -124,7 +124,7 @@ GnssAPIClient* Gnss::getApi() { return mApi; } -GnssInterface* Gnss::getGnssInterface() { +const GnssInterface* Gnss::getGnssInterface() { static bool getGnssInterfaceFailed = false; if (nullptr == mGnssInterface && !getGnssInterfaceFailed) { LOC_LOGD("%s]: loading libgnss.so::getGnssInterface ...", __func__); @@ -145,7 +145,7 @@ GnssInterface* Gnss::getGnssInterface() { if (NULL == getter) { getGnssInterfaceFailed = true; } else { - mGnssInterface = (GnssInterface*)(*getter)(); + mGnssInterface = (const GnssInterface*)(*getter)(); } } return mGnssInterface; @@ -278,7 +278,7 @@ Return<bool> Gnss::injectLocation(double latitudeDegrees, double longitudeDegrees, float accuracyMeters) { ENTRY_LOG_CALLFLOW(); - GnssInterface* gnssInterface = getGnssInterface(); + const GnssInterface* gnssInterface = getGnssInterface(); if (nullptr != gnssInterface) { gnssInterface->injectLocation(latitudeDegrees, longitudeDegrees, accuracyMeters); return true; @@ -290,7 +290,7 @@ Return<bool> Gnss::injectLocation(double latitudeDegrees, Return<bool> Gnss::injectTime(int64_t timeMs, int64_t timeReferenceMs, int32_t uncertaintyMs) { ENTRY_LOG_CALLFLOW(); - GnssInterface* gnssInterface = getGnssInterface(); + const GnssInterface* gnssInterface = getGnssInterface(); if (nullptr != gnssInterface) { gnssInterface->injectTime(timeMs, timeReferenceMs, uncertaintyMs); return true; @@ -375,7 +375,7 @@ Return<bool> Gnss::setCallback_1_1(const sp<V1_1::IGnssCallback>& callback) { ENTRY_LOG_CALLFLOW(); callback->gnssNameCb(getVersionString()); mGnssCbIface_1_1 = callback; - GnssInterface* gnssInterface = getGnssInterface(); + const GnssInterface* gnssInterface = getGnssInterface(); if (nullptr != gnssInterface) { OdcpiRequestCallback cb = [this](const OdcpiRequestInfo& odcpiRequest) { odcpiRequestCb(odcpiRequest); @@ -419,7 +419,7 @@ Return<sp<V1_1::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_1_1() { Return<bool> Gnss::injectBestLocation(const GnssLocation& gnssLocation) { ENTRY_LOG_CALLFLOW(); - GnssInterface* gnssInterface = getGnssInterface(); + const GnssInterface* gnssInterface = getGnssInterface(); if (nullptr != gnssInterface) { Location location = {}; convertGnssLocation(gnssLocation, location); @@ -446,9 +446,9 @@ void Gnss::odcpiRequestCb(const OdcpiRequestInfo& request) { } } -IGnss* HIDL_FETCH_IGnss(const char* hal) { +V1_0::IGnss* HIDL_FETCH_IGnss(const char* hal) { ENTRY_LOG_CALLFLOW(); - IGnss* iface = nullptr; + V1_0::IGnss* iface = nullptr; iface = new Gnss(); if (iface == nullptr) { LOC_LOGE("%s]: failed to get %s", __FUNCTION__, hal); diff --git a/android/1.1/Gnss.h b/android/1.1/Gnss.h index 4c0c8b0..15645eb 100644 --- a/android/1.1/Gnss.h +++ b/android/1.1/Gnss.h @@ -109,7 +109,7 @@ struct Gnss : public IGnss { GnssAPIClient* getApi(); Return<bool> setGnssNiCb(const sp<IGnssNiCallback>& niCb); Return<bool> updateConfiguration(GnssConfig& gnssConfig); - GnssInterface* getGnssInterface(); + const GnssInterface* getGnssInterface(); // Callback for ODCPI request void odcpiRequestCb(const OdcpiRequestInfo& request); @@ -140,10 +140,10 @@ struct Gnss : public IGnss { sp<V1_1::IGnssCallback> mGnssCbIface_1_1 = nullptr; sp<V1_0::IGnssNiCallback> mGnssNiCbIface = nullptr; GnssConfig mPendingConfig; - GnssInterface* mGnssInterface = nullptr; + const GnssInterface* mGnssInterface = nullptr; }; -extern "C" IGnss* HIDL_FETCH_IGnss(const char* name); +extern "C" V1_0::IGnss* HIDL_FETCH_IGnss(const char* name); } // namespace implementation } // namespace V1_1 diff --git a/android/1.1/location_api/GnssAPIClient.cpp b/android/1.1/location_api/GnssAPIClient.cpp index fcef459..89877e5 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 <LocDualContext.h> +#include <LocContext.h> namespace android { namespace hardware { @@ -110,9 +110,9 @@ void GnssAPIClient::gnssUpdateCallbacks(const sp<IGnssCallback>& 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/MeasurementAPIClient.cpp b/android/1.1/location_api/MeasurementAPIClient.cpp index 7017e52..6f25067 100644 --- a/android/1.1/location_api/MeasurementAPIClient.cpp +++ b/android/1.1/location_api/MeasurementAPIClient.cpp @@ -309,6 +309,18 @@ static void convertGnssData_1_1(GnssMeasurementsNotification& in, out.measurements.resize(in.count); for (size_t i = 0; i < in.count; i++) { convertGnssMeasurement(in.measurements[i], out.measurements[i].v1_0); + if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_VALID_BIT) + out.measurements[i].accumulatedDeltaRangeState |= + IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_VALID; + if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_RESET_BIT) + out.measurements[i].accumulatedDeltaRangeState |= + IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_RESET; + if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_CYCLE_SLIP_BIT) + out.measurements[i].accumulatedDeltaRangeState |= + IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_CYCLE_SLIP; + if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_HALF_CYCLE_RESOLVED_BIT) + out.measurements[i].accumulatedDeltaRangeState |= + IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_HALF_CYCLE_RESOLVED; } convertGnssClock(in.clock, out.clock); } diff --git a/android/1.1/service.cpp b/android/1.1/service.cpp index c1bc6b0..bf7ad07 100644 --- a/android/1.1/service.cpp +++ b/android/1.1/service.cpp @@ -22,22 +22,63 @@ #include <android/hardware/gnss/1.1/IGnss.h> #include <hidl/LegacySupport.h> - #include "loc_cfg.h" +#include "loc_misc_utils.h" + extern "C" { #include "vndfwk-detect.h" } +#ifdef ARCH_ARM_32 +#define DEFAULT_HW_BINDER_MEM_SIZE 65536 +#endif + using android::hardware::gnss::V1_1::IGnss; -using android::hardware::defaultPassthroughServiceImplementation; + +using android::hardware::configureRpcThreadpool; +using android::hardware::registerPassthroughServiceImplementation; +using android::hardware::joinRpcThreadpool; + +using android::status_t; +using android::OK; + +typedef int vendorEnhancedServiceMain(int /* argc */, char* /* argv */ []); int main() { + + ALOGI("%s", __FUNCTION__); + bool vendorEnhanced = isRunningWithVendorEnhancedFramework(); setVendorEnhanced(vendorEnhanced); - if (!vendorEnhanced) { - return defaultPassthroughServiceImplementation<IGnss>(); +#ifdef ARCH_ARM_32 + android::hardware::ProcessState::initWithMmapSize((size_t)(DEFAULT_HW_BINDER_MEM_SIZE)); +#endif + configureRpcThreadpool(1, true); + status_t status; + + status = registerPassthroughServiceImplementation<IGnss>(); + if (status == OK) { + if (vendorEnhanced) { + #ifdef LOC_HIDL_VERSION + #define VENDOR_ENHANCED_LIB "vendor.qti.gnss@" LOC_HIDL_VERSION "-service.so" + + void* libHandle = NULL; + vendorEnhancedServiceMain* vendorEnhancedMainMethod = (vendorEnhancedServiceMain*) + dlGetSymFromLib(libHandle, VENDOR_ENHANCED_LIB, "main"); + if (NULL != vendorEnhancedMainMethod) { + (*vendorEnhancedMainMethod)(0, NULL); + } + #else + ALOGE("LOC_HIDL_VERSION not defined."); + #endif + } + + joinRpcThreadpool(); + } else { - return -1; + ALOGE("Error while registering IGnss 1.1 service: %d", status); } + + return 0; } diff --git a/android/2.0/AGnss.cpp b/android/2.0/AGnss.cpp new file mode 100644 index 0000000..7bd015e --- /dev/null +++ b/android/2.0/AGnss.cpp @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Not a Contribution + */ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "LocSvc_AGnssInterface" + +#include <log_util.h> +#include "Gnss.h" +#include "AGnss.h" + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +static AGnss* spAGnss = nullptr; + +AGnss::AGnss(Gnss* gnss) : mGnss(gnss) { + spAGnss = this; +} + +AGnss::~AGnss() { + spAGnss = nullptr; +} + +void AGnss::agnssStatusIpV4Cb(AGnssExtStatusIpV4 status) { + if (nullptr != spAGnss) { + spAGnss->statusCb(status.type, status.status); + } +} + +void AGnss::statusCb(AGpsExtType type, LocAGpsStatusValue status) { + + V2_0::IAGnssCallback::AGnssType aType; + IAGnssCallback::AGnssStatusValue aStatus; + + switch (type) { + case LOC_AGPS_TYPE_SUPL: + aType = IAGnssCallback::AGnssType::SUPL; + break; + case LOC_AGPS_TYPE_SUPL_ES: + aType = IAGnssCallback::AGnssType::SUPL_EIMS; + break; + default: + LOC_LOGE("invalid type: %d", type); + return; + } + + switch (status) { + case LOC_GPS_REQUEST_AGPS_DATA_CONN: + aStatus = IAGnssCallback::AGnssStatusValue::REQUEST_AGNSS_DATA_CONN; + break; + case LOC_GPS_RELEASE_AGPS_DATA_CONN: + aStatus = IAGnssCallback::AGnssStatusValue::RELEASE_AGNSS_DATA_CONN; + break; + case LOC_GPS_AGPS_DATA_CONNECTED: + aStatus = IAGnssCallback::AGnssStatusValue::AGNSS_DATA_CONNECTED; + break; + case LOC_GPS_AGPS_DATA_CONN_DONE: + aStatus = IAGnssCallback::AGnssStatusValue::AGNSS_DATA_CONN_DONE; + break; + case LOC_GPS_AGPS_DATA_CONN_FAILED: + aStatus = IAGnssCallback::AGnssStatusValue::AGNSS_DATA_CONN_FAILED; + break; + default: + LOC_LOGE("invalid status: %d", status); + return; + } + + if (mAGnssCbIface != nullptr) { + auto r = mAGnssCbIface->agnssStatusCb(aType, aStatus); + if (!r.isOk()) { + LOC_LOGw("Error invoking AGNSS status cb %s", r.description().c_str()); + } + } + else { + LOC_LOGw("setCallback has not been called yet"); + } +} + +Return<void> AGnss::setCallback(const sp<V2_0::IAGnssCallback>& callback) { + + if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){ + LOC_LOGE("Null GNSS interface"); + return Void(); + } + + // Save the interface + mAGnssCbIface = callback; + + AgpsCbInfo cbInfo = {}; + cbInfo.statusV4Cb = (void*)agnssStatusIpV4Cb; + cbInfo.cbPriority = AGPS_CB_PRIORITY_HIGH; + + mGnss->getGnssInterface()->agpsInit(cbInfo); + return Void(); +} + +Return<bool> AGnss::dataConnClosed() { + + if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){ + LOC_LOGE("Null GNSS interface"); + return false; + } + + mGnss->getGnssInterface()->agpsDataConnClosed(LOC_AGPS_TYPE_SUPL); + return true; +} + +Return<bool> AGnss::dataConnFailed() { + + if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){ + LOC_LOGE("Null GNSS interface"); + return false; + } + + mGnss->getGnssInterface()->agpsDataConnFailed(LOC_AGPS_TYPE_SUPL); + return true; +} + +Return<bool> AGnss::dataConnOpen(uint64_t /*networkHandle*/, const hidl_string& apn, + V2_0::IAGnss::ApnIpType apnIpType) { + + if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){ + LOC_LOGE("Null GNSS interface"); + return false; + } + + /* Validate */ + if(apn.empty()){ + LOC_LOGE("Invalid APN"); + return false; + } + + LOC_LOGD("dataConnOpen APN name = [%s]", apn.c_str()); + + AGpsBearerType bearerType; + switch (apnIpType) { + case IAGnss::ApnIpType::IPV4: + bearerType = AGPS_APN_BEARER_IPV4; + break; + case IAGnss::ApnIpType::IPV6: + bearerType = AGPS_APN_BEARER_IPV6; + break; + case IAGnss::ApnIpType::IPV4V6: + bearerType = AGPS_APN_BEARER_IPV4V6; + break; + default: + bearerType = AGPS_APN_BEARER_IPV4; + break; + } + + mGnss->getGnssInterface()->agpsDataConnOpen( + LOC_AGPS_TYPE_SUPL, apn.c_str(), apn.size(), (int)bearerType); + return true; +} + +Return<bool> AGnss::setServer(V2_0::IAGnssCallback::AGnssType type, + const hidl_string& hostname, + int32_t port) { + if (mGnss == nullptr) { + LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__); + return false; + } + + GnssConfig config; + memset(&config, 0, sizeof(GnssConfig)); + config.size = sizeof(GnssConfig); + config.flags = GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT; + config.assistanceServer.size = sizeof(GnssConfigSetAssistanceServer); + if (type == IAGnssCallback::AGnssType::SUPL) { + config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_SUPL; + } else if (type == IAGnssCallback::AGnssType::C2K) { + config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_C2K; + } else if (type == IAGnssCallback::AGnssType::SUPL_EIMS) { + config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_SUPL_EIMS; + } else if (type == IAGnssCallback::AGnssType::SUPL_IMS) { + config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_SUPL_IMS; + } else { + LOC_LOGE("%s]: invalid AGnssType: %d", __FUNCTION__, static_cast<uint8_t>(type)); + return false; + } + config.assistanceServer.hostName = strdup(hostname.c_str()); + config.assistanceServer.port = port; + return mGnss->updateConfiguration(config); +} + +} // namespace implementation +} // namespace V2_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/android/2.0/AGnss.h b/android/2.0/AGnss.h new file mode 100644 index 0000000..c442327 --- /dev/null +++ b/android/2.0/AGnss.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Not a Contribution + */ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_GNSS_V2_0_AGNSS_H +#define ANDROID_HARDWARE_GNSS_V2_0_AGNSS_H + +#include <android/hardware/gnss/2.0/IAGnss.h> +#include <hidl/Status.h> +#include <gps_extended_c.h> + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::hidl_vec; +using ::android::hardware::hidl_string; +using ::android::sp; + +struct Gnss; +struct AGnss : public V2_0::IAGnss { + + AGnss(Gnss* gnss); + ~AGnss(); + /* + * Methods from ::android::hardware::gnss::V2_0::IAGnss interface follow. + * These declarations were generated from IAGnss.hal. + */ + Return<void> setCallback(const sp<V2_0::IAGnssCallback>& callback) override; + + Return<bool> dataConnClosed() override; + + Return<bool> dataConnFailed() override; + + Return<bool> dataConnOpen(uint64_t networkHandle, const hidl_string& apn, + V2_0::IAGnss::ApnIpType apnIpType) override; + + Return<bool> setServer(V2_0::IAGnssCallback::AGnssType type, + const hidl_string& hostname, int32_t port) override; + + void statusCb(AGpsExtType type, LocAGpsStatusValue status); + + /* Data call setup callback passed down to GNSS HAL implementation */ + static void agnssStatusIpV4Cb(AGnssExtStatusIpV4 status); + + private: + Gnss* mGnss = nullptr; + sp<IAGnssCallback> mAGnssCbIface = nullptr; +}; + +} // namespace implementation +} // namespace V2_0 +} // namespace gnss +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GNSS_V2_0_AGNSS_H diff --git a/android/2.0/AGnssRil.cpp b/android/2.0/AGnssRil.cpp new file mode 100644 index 0000000..9de8b7d --- /dev/null +++ b/android/2.0/AGnssRil.cpp @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Not a Contribution + */ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "LocSvc__AGnssRilInterface" + +#include <log_util.h> +#include <dlfcn.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <sstream> +#include <string> +#include "Gnss.h" +#include "AGnssRil.h" +#include <DataItemConcreteTypesBase.h> + +typedef void* (getLocationInterface)(); + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + + +AGnssRil::AGnssRil(Gnss* gnss) : mGnss(gnss) { + ENTRY_LOG_CALLFLOW(); +} + +AGnssRil::~AGnssRil() { + ENTRY_LOG_CALLFLOW(); +} + +Return<bool> AGnssRil::updateNetworkState(bool connected, NetworkType type, bool /*roaming*/) { + ENTRY_LOG_CALLFLOW(); + // Extra NetworkTypes not available in IAgnssRil enums + const int NetworkType_BLUETOOTH = 7; + const int NetworkType_ETHERNET = 9; + const int NetworkType_PROXY = 16; + + // for XTRA + if (nullptr != mGnss && ( nullptr != mGnss->getGnssInterface() )) { + int8_t typeout = loc_core::NetworkInfoDataItemBase::TYPE_UNKNOWN; + switch(type) + { + case IAGnssRil::NetworkType::MOBILE: + typeout = loc_core::NetworkInfoDataItemBase::TYPE_MOBILE; + break; + case IAGnssRil::NetworkType::WIFI: + typeout = loc_core::NetworkInfoDataItemBase::TYPE_WIFI; + break; + case IAGnssRil::NetworkType::MMS: + typeout = loc_core::NetworkInfoDataItemBase::TYPE_MMS; + break; + case IAGnssRil::NetworkType::SUPL: + typeout = loc_core::NetworkInfoDataItemBase::TYPE_SUPL; + break; + case IAGnssRil::NetworkType::DUN: + typeout = loc_core::NetworkInfoDataItemBase::TYPE_DUN; + break; + case IAGnssRil::NetworkType::HIPRI: + typeout = loc_core::NetworkInfoDataItemBase::TYPE_HIPRI; + break; + case IAGnssRil::NetworkType::WIMAX: + typeout = loc_core::NetworkInfoDataItemBase::TYPE_WIMAX; + break; + default: + { + int networkType = (int) type; + // Handling network types not available in IAgnssRil + switch(networkType) + { + case NetworkType_BLUETOOTH: + typeout = loc_core::NetworkInfoDataItemBase::TYPE_BLUETOOTH; + break; + case NetworkType_ETHERNET: + typeout = loc_core::NetworkInfoDataItemBase::TYPE_ETHERNET; + break; + case NetworkType_PROXY: + typeout = loc_core::NetworkInfoDataItemBase::TYPE_PROXY; + break; + default: + typeout = loc_core::NetworkInfoDataItemBase::TYPE_UNKNOWN; + } + } + break; + } + mGnss->getGnssInterface()->updateConnectionStatus(connected, false, typeout, 0); + } + return true; +} +Return<bool> AGnssRil::updateNetworkState_2_0(const V2_0::IAGnssRil::NetworkAttributes& attributes) { + ENTRY_LOG_CALLFLOW(); + + if (nullptr != mGnss && (nullptr != mGnss->getGnssInterface())) { + int8_t typeout = loc_core::NetworkInfoDataItemBase::TYPE_UNKNOWN; + bool roaming = false; + if (attributes.capabilities & IAGnssRil::NetworkCapability::NOT_METERED) { + typeout = loc_core::NetworkInfoDataItemBase::TYPE_WIFI; + } else { + typeout = loc_core::NetworkInfoDataItemBase::TYPE_MOBILE; + } + if (attributes.capabilities & IAGnssRil::NetworkCapability::NOT_ROAMING) { + roaming = false; + } + mGnss->getGnssInterface()->updateConnectionStatus(attributes.isConnected, + typeout, roaming, (NetworkHandle) attributes.networkHandle); + } + return true; +} + +} // namespace implementation +} // namespace V2_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/android/2.0/AGnssRil.h b/android/2.0/AGnssRil.h new file mode 100644 index 0000000..a04d8aa --- /dev/null +++ b/android/2.0/AGnssRil.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Not a Contribution + */ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_GNSS_V2_0_AGNSSRIL_H_ +#define ANDROID_HARDWARE_GNSS_V2_0_AGNSSRIL_H_ + +#include <android/hardware/gnss/2.0/IAGnssRil.h> +#include <hidl/Status.h> +#include <location_interface.h> + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::hidl_vec; +using ::android::hardware::hidl_string; +using ::android::sp; + +struct Gnss; +/* + * Extended interface for AGNSS RIL support. An Assisted GNSS Radio Interface Layer interface + * allows the GNSS chipset to request radio interface layer information from Android platform. + * Examples of such information are reference location, unique subscriber ID, phone number string + * and network availability changes. Also contains wrapper methods to allow methods from + * IAGnssiRilCallback interface to be passed into the conventional implementation of the GNSS HAL. + */ +struct AGnssRil : public V2_0::IAGnssRil { + AGnssRil(Gnss* gnss); + ~AGnssRil(); + + /* + * Methods from ::android::hardware::gnss::V1_0::IAGnssRil follow. + * These declarations were generated from IAGnssRil.hal. + */ + Return<void> setCallback(const sp<V1_0::IAGnssRilCallback>& /*callback*/) override { + return Void(); + } + Return<void> setRefLocation(const V1_0::IAGnssRil::AGnssRefLocation& /*agnssReflocation*/) override { + return Void(); + } + Return<bool> setSetId(V1_0::IAGnssRil::SetIDType /*type*/, const hidl_string& /*setid*/) override { + return false; + } + Return<bool> updateNetworkAvailability(bool /*available*/, + const hidl_string& /*apn*/) override { + return false; + } + Return<bool> updateNetworkState(bool connected, V1_0::IAGnssRil::NetworkType type, bool roaming) override; + + // Methods from ::android::hardware::gnss::V2_0::IAGnssRil follow + Return<bool> updateNetworkState_2_0(const V2_0::IAGnssRil::NetworkAttributes& attributes) override; + + private: + Gnss* mGnss = nullptr; +}; + +} // namespace implementation +} // namespace V2_0 +} // namespace gnss +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GNSS_V2_0_AGNSSRIL_H_ diff --git a/android/2.0/Android.mk b/android/2.0/Android.mk new file mode 100644 index 0000000..2000bb8 --- /dev/null +++ b/android/2.0/Android.mk @@ -0,0 +1,102 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE := android.hardware.gnss@2.0-impl-qti +LOCAL_VENDOR_MODULE := true +LOCAL_MODULE_RELATIVE_PATH := hw +LOCAL_SRC_FILES := \ + AGnss.cpp \ + Gnss.cpp \ + AGnssRil.cpp \ + GnssMeasurement.cpp \ + GnssConfiguration.cpp \ + GnssBatching.cpp \ + GnssGeofencing.cpp \ + GnssNi.cpp \ + GnssDebug.cpp \ + ../measurement_corrections/1.0/MeasurementCorrections.cpp \ + ../visibility_control/1.0/GnssVisibilityControl.cpp + +LOCAL_SRC_FILES += \ + location_api/GnssAPIClient.cpp \ + location_api/MeasurementAPIClient.cpp \ + location_api/GeofenceAPIClient.cpp \ + location_api/BatchingAPIClient.cpp \ + location_api/LocationUtil.cpp \ + +ifeq ($(GNSS_HIDL_LEGACY_MEASURMENTS),true) +LOCAL_CFLAGS += \ + -DGNSS_HIDL_LEGACY_MEASURMENTS +endif + +LOCAL_C_INCLUDES:= \ + $(LOCAL_PATH)/location_api \ + $(LOCAL_PATH)/../measurement_corrections/1.0 \ + $(LOCAL_PATH)/../visibility_control/1.0 +LOCAL_HEADER_LIBRARIES := \ + libgps.utils_headers \ + libloc_core_headers \ + libloc_pla_headers \ + liblocation_api_headers + +LOCAL_SHARED_LIBRARIES := \ + liblog \ + libhidlbase \ + libhidltransport \ + libhwbinder \ + libcutils \ + libutils \ + android.hardware.gnss@1.0 \ + android.hardware.gnss@1.1 \ + android.hardware.gnss@2.0 \ + android.hardware.gnss.measurement_corrections@1.0 \ + android.hardware.gnss.visibility_control@1.0 + +LOCAL_SHARED_LIBRARIES += \ + libloc_core \ + libgps.utils \ + libdl \ + liblocation_api \ + +LOCAL_CFLAGS += $(GNSS_CFLAGS) +include $(BUILD_SHARED_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := android.hardware.gnss@2.0-service-qti +LOCAL_VENDOR_MODULE := true +LOCAL_MODULE_RELATIVE_PATH := hw +LOCAL_INIT_RC := android.hardware.gnss@2.0-service-qti.rc +LOCAL_SRC_FILES := \ + service.cpp \ + +LOCAL_HEADER_LIBRARIES := \ + libgps.utils_headers \ + libloc_core_headers \ + libloc_pla_headers \ + liblocation_api_headers + + +LOCAL_SHARED_LIBRARIES := \ + liblog \ + libcutils \ + libdl \ + libbase \ + libutils \ + libgps.utils \ + libqti_vndfwk_detect \ + +LOCAL_SHARED_LIBRARIES += \ + libhwbinder \ + libhidlbase \ + libhidltransport \ + android.hardware.gnss@1.0 \ + android.hardware.gnss@1.1 \ + android.hardware.gnss@2.0 \ + +LOCAL_CFLAGS += $(GNSS_CFLAGS) + +ifneq ($(LOC_HIDL_VERSION),) +LOCAL_CFLAGS += -DLOC_HIDL_VERSION='"$(LOC_HIDL_VERSION)"' +endif + +include $(BUILD_EXECUTABLE) diff --git a/android/2.0/Gnss.cpp b/android/2.0/Gnss.cpp new file mode 100644 index 0000000..1021938 --- /dev/null +++ b/android/2.0/Gnss.cpp @@ -0,0 +1,538 @@ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Not a Contribution + */ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "LocSvc_GnssInterface" + +#include <fstream> +#include <log_util.h> +#include <dlfcn.h> +#include <cutils/properties.h> +#include "Gnss.h" +#include "LocationUtil.h" + +typedef const GnssInterface* (getLocationInterface)(); + +#define IMAGES_INFO_FILE "/sys/devices/soc0/images" +#define DELIMITER ";" + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +using ::android::hardware::gnss::visibility_control::V1_0::implementation::GnssVisibilityControl; + +static std::string getVersionString() { + static std::string version; + if (!version.empty()) + return version; + + char value[PROPERTY_VALUE_MAX] = {0}; + property_get("ro.hardware", value, "unknown"); + version.append(value).append(DELIMITER); + + std::ifstream in(IMAGES_INFO_FILE); + std::string s; + while(getline(in, s)) { + std::size_t found = s.find("CRM:"); + if (std::string::npos == found) { + continue; + } + + // skip over space characters after "CRM:" + const char* substr = s.c_str(); + found += 4; + while (0 != substr[found] && isspace(substr[found])) { + found++; + } + if (s.find("11:") != found) { + continue; + } + s.erase(0, found + 3); + + found = s.find_first_of("\r\n"); + if (std::string::npos != found) { + s.erase(s.begin() + found, s.end()); + } + version.append(s).append(DELIMITER); + } + return version; +} + +void Gnss::GnssDeathRecipient::serviceDied(uint64_t cookie, const wp<IBase>& who) { + LOC_LOGE("%s] service died. cookie: %llu, who: %p", + __FUNCTION__, static_cast<unsigned long long>(cookie), &who); + if (mGnss != nullptr) { + mGnss->stop(); + mGnss->cleanup(); + } +} + +Gnss::Gnss() { + ENTRY_LOG_CALLFLOW(); + // clear pending GnssConfig + memset(&mPendingConfig, 0, sizeof(GnssConfig)); + mGnssDeathRecipient = new GnssDeathRecipient(this); +} + +Gnss::~Gnss() { + ENTRY_LOG_CALLFLOW(); + if (mApi != nullptr) { + delete mApi; + mApi = nullptr; + } +} + +GnssAPIClient* Gnss::getApi() { + if (mApi == nullptr && (mGnssCbIface != nullptr || mGnssNiCbIface != nullptr)) { + mApi = new GnssAPIClient(mGnssCbIface, mGnssNiCbIface); + if (mApi == nullptr) { + LOC_LOGE("%s] faild to create GnssAPIClient", __FUNCTION__); + return mApi; + } + + if (mPendingConfig.size == sizeof(GnssConfig)) { + // we have pending GnssConfig + mApi->gnssConfigurationUpdate(mPendingConfig); + // clear size to invalid mPendingConfig + mPendingConfig.size = 0; + if (mPendingConfig.assistanceServer.hostName != nullptr) { + free((void*)mPendingConfig.assistanceServer.hostName); + } + } + } + if (mApi == nullptr) { + LOC_LOGW("%s] GnssAPIClient is not ready", __FUNCTION__); + } + return mApi; +} + +const GnssInterface* Gnss::getGnssInterface() { + static bool getGnssInterfaceFailed = false; + if (nullptr == mGnssInterface && !getGnssInterfaceFailed) { + LOC_LOGD("%s]: loading libgnss.so::getGnssInterface ...", __func__); + getLocationInterface* getter = NULL; + const char *error = NULL; + dlerror(); + void *handle = dlopen("libgnss.so", RTLD_NOW); + if (NULL == handle || (error = dlerror()) != NULL) { + LOC_LOGW("dlopen for libgnss.so failed, error = %s", error); + } else { + getter = (getLocationInterface*)dlsym(handle, "getGnssInterface"); + if ((error = dlerror()) != NULL) { + LOC_LOGW("dlsym for libgnss.so::getGnssInterface failed, error = %s", error); + getter = NULL; + } + } + + if (NULL == getter) { + getGnssInterfaceFailed = true; + } else { + mGnssInterface = (const GnssInterface*)(*getter)(); + } + } + return mGnssInterface; +} + +Return<bool> Gnss::setCallback(const sp<V1_0::IGnssCallback>& callback) { + ENTRY_LOG_CALLFLOW(); + if (mGnssCbIface != nullptr) { + mGnssCbIface->unlinkToDeath(mGnssDeathRecipient); + } + mGnssCbIface = callback; + if (mGnssCbIface != nullptr) { + mGnssCbIface->linkToDeath(mGnssDeathRecipient, 0 /*cookie*/); + } + + GnssAPIClient* api = getApi(); + if (api != nullptr) { + api->gnssUpdateCallbacks(mGnssCbIface, mGnssNiCbIface); + api->gnssEnable(LOCATION_TECHNOLOGY_TYPE_GNSS); + api->requestCapabilities(); + } + return true; +} + +Return<bool> Gnss::setGnssNiCb(const sp<IGnssNiCallback>& callback) { + ENTRY_LOG_CALLFLOW(); + mGnssNiCbIface = callback; + GnssAPIClient* api = getApi(); + if (api != nullptr) { + api->gnssUpdateCallbacks(mGnssCbIface, mGnssNiCbIface); + } + return true; +} + +Return<bool> Gnss::updateConfiguration(GnssConfig& gnssConfig) { + ENTRY_LOG_CALLFLOW(); + GnssAPIClient* api = getApi(); + if (api) { + api->gnssConfigurationUpdate(gnssConfig); + } else if (gnssConfig.flags != 0) { + // api is not ready yet, update mPendingConfig with gnssConfig + mPendingConfig.size = sizeof(GnssConfig); + + if (gnssConfig.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) { + mPendingConfig.flags |= GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT; + mPendingConfig.gpsLock = gnssConfig.gpsLock; + } + if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) { + mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT; + mPendingConfig.suplVersion = gnssConfig.suplVersion; + } + if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) { + mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT; + mPendingConfig.assistanceServer.size = sizeof(GnssConfigSetAssistanceServer); + mPendingConfig.assistanceServer.type = gnssConfig.assistanceServer.type; + if (mPendingConfig.assistanceServer.hostName != nullptr) { + free((void*)mPendingConfig.assistanceServer.hostName); + mPendingConfig.assistanceServer.hostName = + strdup(gnssConfig.assistanceServer.hostName); + } + mPendingConfig.assistanceServer.port = gnssConfig.assistanceServer.port; + } + if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) { + mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT; + mPendingConfig.lppProfile = gnssConfig.lppProfile; + } + if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) { + mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT; + mPendingConfig.lppeControlPlaneMask = gnssConfig.lppeControlPlaneMask; + } + if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) { + mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT; + mPendingConfig.lppeUserPlaneMask = gnssConfig.lppeUserPlaneMask; + } + if (gnssConfig.flags & GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) { + mPendingConfig.flags |= GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT; + mPendingConfig.aGlonassPositionProtocolMask = gnssConfig.aGlonassPositionProtocolMask; + } + if (gnssConfig.flags & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) { + mPendingConfig.flags |= GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT; + mPendingConfig.emergencyPdnForEmergencySupl = gnssConfig.emergencyPdnForEmergencySupl; + } + if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) { + mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT; + mPendingConfig.suplEmergencyServices = gnssConfig.suplEmergencyServices; + } + if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) { + mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_MODE_BIT; + mPendingConfig.suplModeMask = gnssConfig.suplModeMask; + } + if (gnssConfig.flags & GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT) { + mPendingConfig.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT; + mPendingConfig.blacklistedSvIds = gnssConfig.blacklistedSvIds; + } + if (gnssConfig.flags & GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT) { + mPendingConfig.flags |= GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT; + mPendingConfig.emergencyExtensionSeconds = gnssConfig.emergencyExtensionSeconds; + } + } + return true; +} + +Return<bool> Gnss::start() { + ENTRY_LOG_CALLFLOW(); + bool retVal = false; + GnssAPIClient* api = getApi(); + if (api) { + retVal = api->gnssStart(); + } + return retVal; +} + +Return<bool> Gnss::stop() { + ENTRY_LOG_CALLFLOW(); + bool retVal = false; + GnssAPIClient* api = getApi(); + if (api) { + retVal = api->gnssStop(); + } + return retVal; +} + +Return<void> Gnss::cleanup() { + ENTRY_LOG_CALLFLOW(); + + if (mApi != nullptr) { + mApi->gnssDisable(); + } + + return Void(); +} + +Return<bool> Gnss::injectLocation(double latitudeDegrees, + double longitudeDegrees, + float accuracyMeters) { + ENTRY_LOG_CALLFLOW(); + const GnssInterface* gnssInterface = getGnssInterface(); + if (nullptr != gnssInterface) { + gnssInterface->injectLocation(latitudeDegrees, longitudeDegrees, accuracyMeters); + return true; + } else { + return false; + } +} + +Return<bool> Gnss::injectTime(int64_t timeMs, int64_t timeReferenceMs, + int32_t uncertaintyMs) { + ENTRY_LOG_CALLFLOW(); + const GnssInterface* gnssInterface = getGnssInterface(); + if (nullptr != gnssInterface) { + gnssInterface->injectTime(timeMs, timeReferenceMs, uncertaintyMs); + return true; + } else { + return false; + } +} + +Return<void> Gnss::deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) { + ENTRY_LOG_CALLFLOW(); + GnssAPIClient* api = getApi(); + if (api) { + api->gnssDeleteAidingData(aidingDataFlags); + } + return Void(); +} + +Return<bool> Gnss::setPositionMode(V1_0::IGnss::GnssPositionMode mode, + V1_0::IGnss::GnssPositionRecurrence recurrence, + uint32_t minIntervalMs, + uint32_t preferredAccuracyMeters, + uint32_t preferredTimeMs) { + ENTRY_LOG_CALLFLOW(); + bool retVal = false; + GnssAPIClient* api = getApi(); + if (api) { + retVal = api->gnssSetPositionMode(mode, recurrence, minIntervalMs, + preferredAccuracyMeters, preferredTimeMs); + } + return retVal; +} + +Return<sp<V1_0::IAGnss>> Gnss::getExtensionAGnss() { + ENTRY_LOG_CALLFLOW(); + //mAGnssIface = new ::android::hardware::gnss::V1_1::implementation::AGnss(this); //need V1_1 AGnss + //return mAGnssIface; + return nullptr; +} + +Return<sp<V1_0::IGnssNi>> Gnss::getExtensionGnssNi() { + ENTRY_LOG_CALLFLOW(); + mGnssNi = new GnssNi(this); + return mGnssNi; +} + +Return<sp<V1_0::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement() { + ENTRY_LOG_CALLFLOW(); + if (mGnssMeasurement == nullptr) + mGnssMeasurement = new GnssMeasurement(); + return mGnssMeasurement; +} + +Return<sp<V1_0::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration() { + ENTRY_LOG_CALLFLOW(); + mGnssConfig = new GnssConfiguration(this); + return mGnssConfig; +} + +Return<sp<V1_0::IGnssGeofencing>> Gnss::getExtensionGnssGeofencing() { + ENTRY_LOG_CALLFLOW(); + mGnssGeofencingIface = new GnssGeofencing(); + return mGnssGeofencingIface; +} + +Return<sp<V1_0::IGnssBatching>> Gnss::getExtensionGnssBatching() { + ENTRY_LOG_CALLFLOW(); + mGnssBatching = new GnssBatching(); + return mGnssBatching; +} + +Return<sp<V1_0::IGnssDebug>> Gnss::getExtensionGnssDebug() { + ENTRY_LOG_CALLFLOW(); + mGnssDebug = new GnssDebug(this); + return mGnssDebug; +} + +Return<sp<V1_0::IAGnssRil>> Gnss::getExtensionAGnssRil() { + ENTRY_LOG_CALLFLOW(); + mGnssRil = new AGnssRil(this); + return mGnssRil; +} + +// Methods from ::android::hardware::gnss::V1_1::IGnss follow. +Return<bool> Gnss::setCallback_1_1(const sp<V1_1::IGnssCallback>& callback) { + ENTRY_LOG_CALLFLOW(); + callback->gnssNameCb(getVersionString()); + mGnssCbIface_1_1 = callback; + const GnssInterface* gnssInterface = getGnssInterface(); + if (nullptr != gnssInterface) { + OdcpiRequestCallback cb = [this](const OdcpiRequestInfo& odcpiRequest) { + odcpiRequestCb(odcpiRequest); + }; + gnssInterface->odcpiInit(cb); + } + return setCallback(callback); +} + +Return<bool> Gnss::setPositionMode_1_1(V1_0::IGnss::GnssPositionMode mode, + V1_0::IGnss::GnssPositionRecurrence recurrence, + uint32_t minIntervalMs, + uint32_t preferredAccuracyMeters, + uint32_t preferredTimeMs, + bool lowPowerMode) { + ENTRY_LOG_CALLFLOW(); + bool retVal = false; + GnssAPIClient* api = getApi(); + if (api) { + GnssPowerMode powerMode = lowPowerMode? + GNSS_POWER_MODE_M4 : GNSS_POWER_MODE_M2; + retVal = api->gnssSetPositionMode(mode, recurrence, minIntervalMs, + preferredAccuracyMeters, preferredTimeMs, powerMode, minIntervalMs); + } + return retVal; +} + +Return<sp<V1_1::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_1_1() { + ENTRY_LOG_CALLFLOW(); +#ifdef GNSS_HIDL_LEGACY_MEASURMENTS + return nullptr; +#else + if (mGnssMeasurement == nullptr) + mGnssMeasurement = new GnssMeasurement(); + return mGnssMeasurement; +#endif +} + +Return<sp<V1_1::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_1_1() { + ENTRY_LOG_CALLFLOW(); + if (mGnssConfig == nullptr) + mGnssConfig = new GnssConfiguration(this); + return mGnssConfig; +} + +Return<bool> Gnss::injectBestLocation(const GnssLocation& gnssLocation) { + ENTRY_LOG_CALLFLOW(); + const GnssInterface* gnssInterface = getGnssInterface(); + if (nullptr != gnssInterface) { + Location location = {}; + convertGnssLocation(gnssLocation, location); + gnssInterface->odcpiInject(location); + } + return true; +} + +void Gnss::odcpiRequestCb(const OdcpiRequestInfo& request) { + ENTRY_LOG_CALLFLOW(); + if (mGnssCbIface_1_1 != nullptr) { + // For emergency mode, request DBH (Device based hybrid) location + // Mark Independent from GNSS flag to false. + if (ODCPI_REQUEST_TYPE_START == request.type) { + auto r = mGnssCbIface_1_1->gnssRequestLocationCb(!request.isEmergencyMode); + if (!r.isOk()) { + LOC_LOGe("Error invoking gnssRequestLocationCb %s", r.description().c_str()); + } + } else { + LOC_LOGv("Unsupported ODCPI request type: %d", request.type); + } + } else { + LOC_LOGe("ODCPI request not supported."); + } +} + +// Methods from ::android::hardware::gnss::V2_0::IGnss follow. +Return<bool> Gnss::setCallback_2_0(const sp<V2_0::IGnssCallback>& callback) { + ENTRY_LOG_CALLFLOW(); + return setCallback_1_1(callback); +} +Return<sp<V2_0::IAGnss>> Gnss::getExtensionAGnss_2_0() { + ENTRY_LOG_CALLFLOW(); + mAGnssIface_2_0 = new AGnss(this); + return mAGnssIface_2_0; +} +Return<sp<V2_0::IAGnssRil>> Gnss::getExtensionAGnssRil_2_0() { + mGnssRil = new AGnssRil(this); + return mGnssRil; +} + +Return<sp<V2_0::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_2_0() { + ENTRY_LOG_CALLFLOW(); + mGnssConfig = new GnssConfiguration(this); + return mGnssConfig; +} +Return<sp<V2_0::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_2_0() { + ENTRY_LOG_CALLFLOW(); +#ifdef GNSS_HIDL_LEGACY_MEASURMENTS + return nullptr; +#else + if (mGnssMeasurement == nullptr) + mGnssMeasurement = new GnssMeasurement(); + return mGnssMeasurement; +#endif +} +Return<sp<::android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections>> + Gnss::getExtensionMeasurementCorrections() { + if (mGnssMeasCorr == nullptr) { + mGnssMeasCorr = new MeasurementCorrections(); + } + return mGnssMeasCorr; +} +Return<sp<::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl>> + Gnss::getExtensionVisibilityControl() { + ENTRY_LOG_CALLFLOW(); + if (mVisibCtrl == nullptr) { + mVisibCtrl = new GnssVisibilityControl(this); + } + return mVisibCtrl; +} + +Return<bool> Gnss::injectBestLocation_2_0( + const ::android::hardware::gnss::V2_0::GnssLocation& location) { + ENTRY_LOG_CALLFLOW(); + /* TBD */ + return false; +} + +Return<sp<V2_0::IGnssBatching>> Gnss::getExtensionGnssBatching_2_0() { + ENTRY_LOG_CALLFLOW(); + return nullptr; +} + +Return<sp<V2_0::IGnssDebug>> Gnss::getExtensionGnssDebug_2_0() { + ENTRY_LOG_CALLFLOW(); + return nullptr; +} + +V1_0::IGnss* HIDL_FETCH_IGnss(const char* hal) { + ENTRY_LOG_CALLFLOW(); + V1_0::IGnss* iface = nullptr; + iface = new Gnss(); + if (iface == nullptr) { + LOC_LOGE("%s]: failed to get %s", __FUNCTION__, hal); + } + return iface; +} + +} // namespace implementation +} // namespace V2_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/android/2.0/Gnss.h b/android/2.0/Gnss.h new file mode 100644 index 0000000..df62901 --- /dev/null +++ b/android/2.0/Gnss.h @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Not a Contribution + */ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_GNSS_V2_0_GNSS_H +#define ANDROID_HARDWARE_GNSS_V2_0_GNSS_H + +#include <AGnss.h> +#include <AGnssRil.h> +#include <GnssConfiguration.h> +#include <GnssMeasurement.h> +#include <GnssBatching.h> +#include <GnssGeofencing.h> +#include <GnssNi.h> +#include <GnssDebug.h> + +#include <android/hardware/gnss/2.0/IGnss.h> +#include <MeasurementCorrections.h> +#include <GnssVisibilityControl.h> +#include <hidl/MQDescriptor.h> +#include <hidl/Status.h> + +#include "GnssAPIClient.h" + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +using ::android::hardware::hidl_array; +using ::android::hardware::hidl_memory; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::sp; +using ::android::hardware::gnss::V1_0::GnssLocation; +using ::android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections; +using ::android::hardware::gnss::measurement_corrections::V1_0::implementation::MeasurementCorrections; +using ::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl; + +struct Gnss : public IGnss { + Gnss(); + ~Gnss(); + + /* + * Methods from ::android::hardware::gnss::V1_0::IGnss follow. + * These declarations were generated from Gnss.hal. + */ + Return<bool> setCallback(const sp<V1_0::IGnssCallback>& callback) override; + Return<bool> start() override; + Return<bool> stop() override; + Return<void> cleanup() override; + Return<bool> injectLocation(double latitudeDegrees, + double longitudeDegrees, + float accuracyMeters) override; + Return<bool> injectTime(int64_t timeMs, + int64_t timeReferenceMs, + int32_t uncertaintyMs) override; + Return<void> deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) override; + Return<bool> setPositionMode(V1_0::IGnss::GnssPositionMode mode, + V1_0::IGnss::GnssPositionRecurrence recurrence, + uint32_t minIntervalMs, + uint32_t preferredAccuracyMeters, + uint32_t preferredTimeMs) override; + Return<sp<V1_0::IAGnss>> getExtensionAGnss() override; + Return<sp<V1_0::IGnssNi>> getExtensionGnssNi() override; + Return<sp<V1_0::IGnssMeasurement>> getExtensionGnssMeasurement() override; + Return<sp<V1_0::IGnssConfiguration>> getExtensionGnssConfiguration() override; + Return<sp<V1_0::IGnssGeofencing>> getExtensionGnssGeofencing() override; + Return<sp<V1_0::IGnssBatching>> getExtensionGnssBatching() override; + + Return<sp<V1_0::IAGnssRil>> getExtensionAGnssRil() override; + + inline Return<sp<V1_0::IGnssNavigationMessage>> getExtensionGnssNavigationMessage() override { + return nullptr; + } + + inline Return<sp<V1_0::IGnssXtra>> getExtensionXtra() override { + return nullptr; + } + + Return<sp<V1_0::IGnssDebug>> getExtensionGnssDebug() override; + + // Methods from ::android::hardware::gnss::V1_1::IGnss follow. + Return<bool> setCallback_1_1(const sp<V1_1::IGnssCallback>& callback) override; + Return<bool> setPositionMode_1_1(V1_0::IGnss::GnssPositionMode mode, + V1_0::IGnss::GnssPositionRecurrence recurrence, + uint32_t minIntervalMs, uint32_t preferredAccuracyMeters, + uint32_t preferredTimeMs, bool lowPowerMode) override; + Return<sp<V1_1::IGnssMeasurement>> getExtensionGnssMeasurement_1_1() override; + Return<sp<V1_1::IGnssConfiguration>> getExtensionGnssConfiguration_1_1() override; + Return<bool> injectBestLocation(const GnssLocation& location) override; + + // Methods from ::android::hardware::gnss::V2_0::IGnss follow. + Return<bool> setCallback_2_0(const sp<V2_0::IGnssCallback>& callback) override; + Return<sp<V2_0::IAGnss>> getExtensionAGnss_2_0() override; + Return<sp<V2_0::IAGnssRil>> getExtensionAGnssRil_2_0() override; + + Return<sp<V2_0::IGnssConfiguration>> getExtensionGnssConfiguration_2_0() override; + Return<sp<::android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections>> + getExtensionMeasurementCorrections() override; + Return<sp<V2_0::IGnssMeasurement>> getExtensionGnssMeasurement_2_0() override; + + Return<bool> injectBestLocation_2_0(const ::android::hardware::gnss::V2_0::GnssLocation& location) override; + + Return<sp<V2_0::IGnssBatching>> getExtensionGnssBatching_2_0() override; + Return<sp<V2_0::IGnssDebug>> getExtensionGnssDebug_2_0() override; + + + /** + * This method returns the IGnssVisibilityControl interface. + * + * @return visibilityControlIface Handle to the IGnssVisibilityControl interface. + */ + Return<sp<::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl>> + getExtensionVisibilityControl() override; + + + // These methods are not part of the IGnss base class. + GnssAPIClient* getApi(); + Return<bool> setGnssNiCb(const sp<IGnssNiCallback>& niCb); + Return<bool> updateConfiguration(GnssConfig& gnssConfig); + const GnssInterface* getGnssInterface(); + + // Callback for ODCPI request + void odcpiRequestCb(const OdcpiRequestInfo& request); + private: + struct GnssDeathRecipient : hidl_death_recipient { + GnssDeathRecipient(sp<Gnss> gnss) : mGnss(gnss) { + } + ~GnssDeathRecipient() = default; + virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override; + sp<Gnss> mGnss; + }; + + private: + sp<GnssDeathRecipient> mGnssDeathRecipient = nullptr; + + sp<V1_0::IGnssNi> mGnssNi = nullptr; + sp<V1_0::IGnssGeofencing> mGnssGeofencingIface = nullptr; + sp<V1_0::IGnssBatching> mGnssBatching = nullptr; + sp<V1_0::IGnssDebug> mGnssDebug = nullptr; + sp<V1_0::IAGnss> mAGnssIface = nullptr; + sp<V1_0::IGnssCallback> mGnssCbIface = nullptr; + sp<V1_0::IGnssNiCallback> mGnssNiCbIface = nullptr; + sp<V1_1::IGnssCallback> mGnssCbIface_1_1 = nullptr; + sp<V2_0::IAGnss> mAGnssIface_2_0 = nullptr; + sp<V2_0::IAGnssRil> mGnssRil = nullptr; + sp<V2_0::IGnssMeasurement> mGnssMeasurement = nullptr; + sp<V2_0::IGnssConfiguration> mGnssConfig = nullptr; + sp<IMeasurementCorrections> mGnssMeasCorr = nullptr; + sp<IGnssVisibilityControl> mVisibCtrl = nullptr; + + GnssAPIClient* mApi = nullptr; + GnssConfig mPendingConfig; + const GnssInterface* mGnssInterface = nullptr; +}; + +extern "C" V1_0::IGnss* HIDL_FETCH_IGnss(const char* name); + +} // namespace implementation +} // namespace V2_0 +} // namespace gnss +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GNSS_V2_0_GNSS_H diff --git a/android/2.0/GnssBatching.cpp b/android/2.0/GnssBatching.cpp new file mode 100644 index 0000000..cf215ea --- /dev/null +++ b/android/2.0/GnssBatching.cpp @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Not a Contribution + */ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "LocSvc_GnssBatchingInterface" + +#include <log_util.h> +#include <BatchingAPIClient.h> +#include "GnssBatching.h" + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +void GnssBatching::GnssBatchingDeathRecipient::serviceDied( + uint64_t cookie, const wp<IBase>& who) { + LOC_LOGE("%s] service died. cookie: %llu, who: %p", + __FUNCTION__, static_cast<unsigned long long>(cookie), &who); + if (mGnssBatching != nullptr) { + mGnssBatching->stop(); + mGnssBatching->cleanup(); + } +} + +GnssBatching::GnssBatching() : mApi(nullptr) { + mGnssBatchingDeathRecipient = new GnssBatchingDeathRecipient(this); +} + +GnssBatching::~GnssBatching() { + if (mApi != nullptr) { + delete mApi; + mApi = nullptr; + } +} + + +// Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow. +Return<bool> GnssBatching::init(const sp<IGnssBatchingCallback>& callback) { + if (mApi != nullptr) { + LOC_LOGD("%s]: mApi is NOT nullptr, delete it first", __FUNCTION__); + delete mApi; + mApi = nullptr; + } + + mApi = new BatchingAPIClient(callback); + if (mApi == nullptr) { + LOC_LOGE("%s]: failed to create mApi", __FUNCTION__); + return false; + } + + if (mGnssBatchingCbIface != nullptr) { + mGnssBatchingCbIface->unlinkToDeath(mGnssBatchingDeathRecipient); + } + mGnssBatchingCbIface = callback; + if (mGnssBatchingCbIface != nullptr) { + mGnssBatchingCbIface->linkToDeath(mGnssBatchingDeathRecipient, 0 /*cookie*/); + } + + return true; +} + +Return<uint16_t> GnssBatching::getBatchSize() { + uint16_t ret = 0; + if (mApi == nullptr) { + LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); + } else { + ret = mApi->getBatchSize(); + } + return ret; +} + +Return<bool> GnssBatching::start(const IGnssBatching::Options& options) { + bool ret = false; + if (mApi == nullptr) { + LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); + } else { + ret = mApi->startSession(options); + } + return ret; +} + +Return<void> GnssBatching::flush() { + if (mApi == nullptr) { + LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); + } else { + mApi->flushBatchedLocations(); + } + return Void(); +} + +Return<bool> GnssBatching::stop() { + bool ret = false; + if (mApi == nullptr) { + LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); + } else { + ret = mApi->stopSession(); + } + return ret; +} + +Return<void> GnssBatching::cleanup() { + if (mGnssBatchingCbIface != nullptr) { + mGnssBatchingCbIface->unlinkToDeath(mGnssBatchingDeathRecipient); + } + return Void(); +} + +} // namespace implementation +} // namespace V2_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/android/2.0/GnssBatching.h b/android/2.0/GnssBatching.h new file mode 100644 index 0000000..f7dc65b --- /dev/null +++ b/android/2.0/GnssBatching.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Not a Contribution + */ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_GNSS_V2_0_GNSSBATCHING_H +#define ANDROID_HARDWARE_GNSS_V2_0_GNSSBATCHING_H + +#include <android/hardware/gnss/1.0/IGnssBatching.h> +#include <hidl/Status.h> + + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +using ::android::hardware::gnss::V1_0::IGnssBatching; +using ::android::hardware::gnss::V1_0::IGnssBatchingCallback; +using ::android::hidl::base::V1_0::IBase; +using ::android::hardware::hidl_array; +using ::android::hardware::hidl_memory; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::sp; + +class BatchingAPIClient; +struct GnssBatching : public IGnssBatching { + GnssBatching(); + ~GnssBatching(); + + // Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow. + Return<bool> init(const sp<IGnssBatchingCallback>& callback) override; + Return<uint16_t> getBatchSize() override; + Return<bool> start(const IGnssBatching::Options& options ) override; + Return<void> flush() override; + Return<bool> stop() override; + Return<void> cleanup() override; + + private: + struct GnssBatchingDeathRecipient : hidl_death_recipient { + GnssBatchingDeathRecipient(sp<GnssBatching> gnssBatching) : + mGnssBatching(gnssBatching) { + } + ~GnssBatchingDeathRecipient() = default; + virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override; + sp<GnssBatching> mGnssBatching; + }; + + private: + sp<GnssBatchingDeathRecipient> mGnssBatchingDeathRecipient = nullptr; + sp<IGnssBatchingCallback> mGnssBatchingCbIface = nullptr; + BatchingAPIClient* mApi = nullptr; +}; + +} // namespace implementation +} // namespace V2_0 +} // namespace gnss +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GNSS_V2_0_GNSSBATCHING_H diff --git a/android/2.0/GnssConfiguration.cpp b/android/2.0/GnssConfiguration.cpp new file mode 100644 index 0000000..eb98be1 --- /dev/null +++ b/android/2.0/GnssConfiguration.cpp @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Not a Contribution + */ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "LocSvc_GnssConfigurationInterface" + +#include <log_util.h> +#include "Gnss.h" +#include "GnssConfiguration.h" +#include <android/hardware/gnss/1.0/types.h> + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +using ::android::hardware::gnss::V1_0::GnssConstellationType; + +GnssConfiguration::GnssConfiguration(Gnss* gnss) : mGnss(gnss) { +} + +// Methods from ::android::hardware::gps::V1_0::IGnssConfiguration follow. +Return<bool> GnssConfiguration::setSuplEs(bool enabled) { + if (mGnss == nullptr) { + LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__); + return false; + } + + GnssConfig config; + memset(&config, 0, sizeof(GnssConfig)); + config.size = sizeof(GnssConfig); + config.flags = GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT; + config.suplEmergencyServices = (enabled ? + GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_YES : + GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_NO); + + return mGnss->updateConfiguration(config); +} + +Return<bool> GnssConfiguration::setSuplVersion(uint32_t version) { + if (mGnss == nullptr) { + LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__); + return false; + } + + GnssConfig config; + memset(&config, 0, sizeof(GnssConfig)); + config.size = sizeof(GnssConfig); + config.flags = GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT; + switch (version) { + case 0x00020002: + config.suplVersion = GNSS_CONFIG_SUPL_VERSION_2_0_2; + break; + case 0x00020000: + config.suplVersion = GNSS_CONFIG_SUPL_VERSION_2_0_0; + break; + case 0x00010000: + config.suplVersion = GNSS_CONFIG_SUPL_VERSION_1_0_0; + break; + default: + LOC_LOGE("%s]: invalid version: 0x%x.", __FUNCTION__, version); + return false; + break; + } + + return mGnss->updateConfiguration(config); +} + +Return<bool> GnssConfiguration::setSuplMode(uint8_t mode) { + if (mGnss == nullptr) { + LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__); + return false; + } + + GnssConfig config; + memset(&config, 0, sizeof(GnssConfig)); + config.size = sizeof(GnssConfig); + config.flags = GNSS_CONFIG_FLAGS_SUPL_MODE_BIT; + switch (mode) { + case 0: + config.suplModeMask = 0; // STANDALONE ONLY + break; + case 1: + config.suplModeMask = GNSS_CONFIG_SUPL_MODE_MSB_BIT; + break; + case 2: + config.suplModeMask = GNSS_CONFIG_SUPL_MODE_MSA_BIT; + break; + case 3: + config.suplModeMask = GNSS_CONFIG_SUPL_MODE_MSB_BIT | GNSS_CONFIG_SUPL_MODE_MSA_BIT; + break; + default: + LOC_LOGE("%s]: invalid mode: %d.", __FUNCTION__, mode); + return false; + break; + } + + return mGnss->updateConfiguration(config); +} + +Return<bool> GnssConfiguration::setLppProfile(uint8_t lppProfile) { + if (mGnss == nullptr) { + LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__); + return false; + } + + GnssConfig config; + memset(&config, 0, sizeof(GnssConfig)); + config.size = sizeof(GnssConfig); + config.flags = GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT; + switch (lppProfile) { + case 0: + config.lppProfile = GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE; + break; + case 1: + config.lppProfile = GNSS_CONFIG_LPP_PROFILE_USER_PLANE; + break; + case 2: + config.lppProfile = GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE; + break; + case 3: + config.lppProfile = GNSS_CONFIG_LPP_PROFILE_USER_PLANE_AND_CONTROL_PLANE; + break; + default: + LOC_LOGE("%s]: invalid lppProfile: %d.", __FUNCTION__, lppProfile); + return false; + break; + } + + return mGnss->updateConfiguration(config); +} + +Return<bool> GnssConfiguration::setGlonassPositioningProtocol(uint8_t protocol) { + if (mGnss == nullptr) { + LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__); + return false; + } + + GnssConfig config; + memset(&config, 0, sizeof(GnssConfig)); + config.size = sizeof(GnssConfig); + + config.flags = GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT; + if (protocol & (1<<0)) { + config.aGlonassPositionProtocolMask |= GNSS_CONFIG_RRC_CONTROL_PLANE_BIT; + } + if (protocol & (1<<1)) { + config.aGlonassPositionProtocolMask |= GNSS_CONFIG_RRLP_USER_PLANE_BIT; + } + if (protocol & (1<<2)) { + config.aGlonassPositionProtocolMask |= GNSS_CONFIG_LLP_USER_PLANE_BIT; + } + if (protocol & (1<<3)) { + config.aGlonassPositionProtocolMask |= GNSS_CONFIG_LLP_CONTROL_PLANE_BIT; + } + + return mGnss->updateConfiguration(config); +} + +Return<bool> GnssConfiguration::setGpsLock(uint8_t lock) { + /* we no longer set GPS lock here, there is + visibility control for this */ + return true; +} + +Return<bool> GnssConfiguration::setEmergencySuplPdn(bool enabled) { + if (mGnss == nullptr) { + LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__); + return false; + } + + GnssConfig config; + memset(&config, 0, sizeof(GnssConfig)); + config.size = sizeof(GnssConfig); + config.flags = GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT; + config.emergencyPdnForEmergencySupl = (enabled ? + GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_YES : + GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_NO); + + return mGnss->updateConfiguration(config); +} + +// Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow. +Return<bool> GnssConfiguration::setBlacklist( + const hidl_vec<GnssConfiguration::BlacklistedSource>& blacklist) { + + ENTRY_LOG_CALLFLOW(); + if (nullptr == mGnss) { + LOC_LOGe("mGnss is null"); + return false; + } + + // blValid is true if blacklist is empty, i.e. clearing the BL; + // if blacklist is not empty, blValid is initialied to false, and later + // updated in the for loop to become true only if there is at least + // one {constellation, svid} in the list that is valid. + bool blValid = (0 == blacklist.size()); + GnssConfig config; + memset(&config, 0, sizeof(GnssConfig)); + config.size = sizeof(GnssConfig); + config.flags = GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT; + config.blacklistedSvIds.clear(); + + GnssSvIdSource source = {}; + for (int idx = 0; idx < (int)blacklist.size(); idx++) { + // Set blValid true if any one source is valid + blValid = setBlacklistedSource(source, blacklist[idx]) || blValid; + config.blacklistedSvIds.push_back(source); + } + + // Update configuration only if blValid is true + // i.e. only if atleast one source is valid for blacklisting + return (blValid && mGnss->updateConfiguration(config)); +} + +bool GnssConfiguration::setBlacklistedSource( + GnssSvIdSource& copyToSource, + const GnssConfiguration::BlacklistedSource& copyFromSource) { + + bool retVal = true; + uint16_t svIdOffset = 0; + copyToSource.size = sizeof(GnssSvIdSource); + copyToSource.svId = copyFromSource.svid; + + switch(copyFromSource.constellation) { + case GnssConstellationType::GPS: + copyToSource.constellation = GNSS_SV_TYPE_GPS; + LOC_LOGe("GPS SVs can't be blacklisted."); + retVal = false; + break; + case GnssConstellationType::SBAS: + copyToSource.constellation = GNSS_SV_TYPE_SBAS; + LOC_LOGe("SBAS SVs can't be blacklisted."); + retVal = false; + break; + case GnssConstellationType::GLONASS: + copyToSource.constellation = GNSS_SV_TYPE_GLONASS; + svIdOffset = GNSS_SV_CONFIG_GLO_INITIAL_SV_ID - 1; + break; + case GnssConstellationType::QZSS: + copyToSource.constellation = GNSS_SV_TYPE_QZSS; + svIdOffset = 0; + break; + case GnssConstellationType::BEIDOU: + copyToSource.constellation = GNSS_SV_TYPE_BEIDOU; + svIdOffset = GNSS_SV_CONFIG_BDS_INITIAL_SV_ID - 1; + break; + case GnssConstellationType::GALILEO: + copyToSource.constellation = GNSS_SV_TYPE_GALILEO; + svIdOffset = GNSS_SV_CONFIG_GAL_INITIAL_SV_ID - 1; + break; + default: + copyToSource.constellation = GNSS_SV_TYPE_UNKNOWN; + LOC_LOGe("Invalid constellation %d", copyFromSource.constellation); + retVal = false; + break; + } + + if (copyToSource.svId > 0 && svIdOffset > 0) { + copyToSource.svId += svIdOffset; + } + + return retVal; +} + +// Methods from ::android::hardware::gnss::V2_0::IGnssConfiguration follow. +Return<bool> GnssConfiguration::setEsExtensionSec(uint32_t emergencyExtensionSeconds) { + ENTRY_LOG_CALLFLOW(); + if (mGnss == nullptr) { + LOC_LOGe("mGnss is nullptr"); + return false; + } + + GnssConfig config; + memset(&config, 0, sizeof(GnssConfig)); + config.size = sizeof(GnssConfig); + config.flags = GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT; + config.emergencyExtensionSeconds = emergencyExtensionSeconds; + + return mGnss->updateConfiguration(config); +} + +} // namespace implementation +} // namespace V2_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/android/2.0/GnssConfiguration.h b/android/2.0/GnssConfiguration.h new file mode 100644 index 0000000..202a9fd --- /dev/null +++ b/android/2.0/GnssConfiguration.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Not a Contribution + */ + + /* Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#ifndef ANDROID_HARDWARE_GNSS_V2_0_GNSSCONFIGURATION_H +#define ANDROID_HARDWARE_GNSS_V2_0_GNSSCONFIGURATION_H + +#include <android/hardware/gnss/2.0/IGnssConfiguration.h> +#include <hidl/Status.h> + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::hidl_vec; +using ::android::hardware::hidl_string; +using ::android::sp; + +/* + * Interface for passing GNSS configuration info from platform to HAL. + */ +struct Gnss; +struct GnssConfiguration : public V2_0::IGnssConfiguration { + GnssConfiguration(Gnss* gnss); + ~GnssConfiguration() = default; + + /* + * Methods from ::android::hardware::gnss::V1_0::IGnssConfiguration follow. + * These declarations were generated from IGnssConfiguration.hal. + */ + Return<bool> setSuplVersion(uint32_t version) override; + Return<bool> setSuplMode(uint8_t mode) override; + Return<bool> setSuplEs(bool enabled) override; + Return<bool> setLppProfile(uint8_t lppProfile) override; + Return<bool> setGlonassPositioningProtocol(uint8_t protocol) override; + Return<bool> setEmergencySuplPdn(bool enable) override; + Return<bool> setGpsLock(uint8_t lock) override; + + // Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow. + Return<bool> setBlacklist( + const hidl_vec<GnssConfiguration::BlacklistedSource>& blacklist) override; + + // Methods from ::android::hardware::gnss::V2_0::IGnssConfiguration follow. + Return<bool> setEsExtensionSec(uint32_t emergencyExtensionSeconds) override; + + private: + Gnss* mGnss = nullptr; + bool setBlacklistedSource( + GnssSvIdSource& copyToSource, + const GnssConfiguration::BlacklistedSource& copyFromSource); +}; + +} // namespace implementation +} // namespace V2_0 +} // namespace gnss +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GNSS_V2_0_GNSSCONFIGURATION_H diff --git a/android/2.0/GnssDebug.cpp b/android/2.0/GnssDebug.cpp new file mode 100644 index 0000000..582acc9 --- /dev/null +++ b/android/2.0/GnssDebug.cpp @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Not a Contribution + */ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "LocSvc_GnssDebugInterface" + +#include <log/log.h> +#include <log_util.h> +#include "Gnss.h" +#include "GnssDebug.h" +#include "LocationUtil.h" + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +using ::android::hardware::hidl_vec; + +#define GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS (20000000) +#define GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS (20000) +#define GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC (500) +#define GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG (180) + +#define GNSS_DEBUG_UNKNOWN_UTC_TIME (1483228800000LL) // 1/1/2017 00:00 GMT +#define GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC (1.57783680E17) // 5 years in ns +#define GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC (2.0e5) // ppm + +GnssDebug::GnssDebug(Gnss* gnss) : mGnss(gnss) +{ +} + +/* + * This methods requests position, time and satellite ephemeris debug information + * from the HAL. + * + * @return void +*/ +Return<void> GnssDebug::getDebugData(getDebugData_cb _hidl_cb) +{ + LOC_LOGD("%s]: ", __func__); + + DebugData data = { }; + + if((nullptr == mGnss) || (nullptr == mGnss->getGnssInterface())){ + LOC_LOGE("GnssDebug - Null GNSS interface"); + _hidl_cb(data); + return Void(); + } + + // get debug report snapshot via hal interface + GnssDebugReport reports = { }; + mGnss->getGnssInterface()->getDebugReport(reports); + + // location block + if (reports.mLocation.mValid) { + data.position.valid = true; + data.position.latitudeDegrees = reports.mLocation.mLocation.latitude; + data.position.longitudeDegrees = reports.mLocation.mLocation.longitude; + data.position.altitudeMeters = reports.mLocation.mLocation.altitude; + + data.position.speedMetersPerSec = + (double)(reports.mLocation.mLocation.speed); + data.position.bearingDegrees = + (double)(reports.mLocation.mLocation.bearing); + data.position.horizontalAccuracyMeters = + (double)(reports.mLocation.mLocation.accuracy); + data.position.verticalAccuracyMeters = + reports.mLocation.verticalAccuracyMeters; + data.position.speedAccuracyMetersPerSecond = + reports.mLocation.speedAccuracyMetersPerSecond; + data.position.bearingAccuracyDegrees = + reports.mLocation.bearingAccuracyDegrees; + + timeval tv_now, tv_report; + tv_report.tv_sec = reports.mLocation.mUtcReported.tv_sec; + tv_report.tv_usec = reports.mLocation.mUtcReported.tv_nsec / 1000ULL; + gettimeofday(&tv_now, NULL); + data.position.ageSeconds = + (tv_now.tv_sec - tv_report.tv_sec) + + (float)((tv_now.tv_usec - tv_report.tv_usec)) / 1000000; + } + else { + data.position.valid = false; + } + + if (data.position.horizontalAccuracyMeters <= 0 || + data.position.horizontalAccuracyMeters > GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS) { + data.position.horizontalAccuracyMeters = GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS; + } + if (data.position.verticalAccuracyMeters <= 0 || + data.position.verticalAccuracyMeters > GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS) { + data.position.verticalAccuracyMeters = GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS; + } + if (data.position.speedAccuracyMetersPerSecond <= 0 || + data.position.speedAccuracyMetersPerSecond > GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC) { + data.position.speedAccuracyMetersPerSecond = GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC; + } + if (data.position.bearingAccuracyDegrees <= 0 || + data.position.bearingAccuracyDegrees > GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG) { + data.position.bearingAccuracyDegrees = GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG; + } + + // time block + if (reports.mTime.mValid) { + data.time.timeEstimate = reports.mTime.timeEstimate; + data.time.timeUncertaintyNs = reports.mTime.timeUncertaintyNs; + data.time.frequencyUncertaintyNsPerSec = + reports.mTime.frequencyUncertaintyNsPerSec; + } + + if (data.time.timeEstimate < GNSS_DEBUG_UNKNOWN_UTC_TIME) { + data.time.timeEstimate = GNSS_DEBUG_UNKNOWN_UTC_TIME; + } + if (data.time.timeUncertaintyNs <= 0 || + data.time.timeUncertaintyNs > (float)GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC) { + data.time.timeUncertaintyNs = (float)GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC; + } + if (data.time.frequencyUncertaintyNsPerSec <= 0 || + data.time.frequencyUncertaintyNsPerSec > (float)GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC) { + data.time.frequencyUncertaintyNsPerSec = (float)GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC; + } + + // satellite data block + SatelliteData s = { }; + std::vector<SatelliteData> s_array = { }; + + for (uint32_t i=0; i<reports.mSatelliteInfo.size(); i++) { + memset(&s, 0, sizeof(s)); + s.svid = reports.mSatelliteInfo[i].svid; + convertGnssConstellationType( + reports.mSatelliteInfo[i].constellation, s.constellation); + convertGnssEphemerisType( + reports.mSatelliteInfo[i].mEphemerisType, s.ephemerisType); + convertGnssEphemerisSource( + reports.mSatelliteInfo[i].mEphemerisSource, s.ephemerisSource); + convertGnssEphemerisHealth( + reports.mSatelliteInfo[i].mEphemerisHealth, s.ephemerisHealth); + + s.ephemerisAgeSeconds = + reports.mSatelliteInfo[i].ephemerisAgeSeconds; + s.serverPredictionIsAvailable = + reports.mSatelliteInfo[i].serverPredictionIsAvailable; + s.serverPredictionAgeSeconds = + reports.mSatelliteInfo[i].serverPredictionAgeSeconds; + + s_array.push_back(s); + } + data.satelliteDataArray = s_array; + + // callback HIDL with collected debug data + _hidl_cb(data); + return Void(); +} + +} // namespace implementation +} // namespace V2_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/android/2.0/GnssDebug.h b/android/2.0/GnssDebug.h new file mode 100644 index 0000000..8d4fde3 --- /dev/null +++ b/android/2.0/GnssDebug.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Not a Contribution + */ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_GNSS_V2_0_GNSSDEBUG_H +#define ANDROID_HARDWARE_GNSS_V2_0_GNSSDEBUG_H + + +#include <android/hardware/gnss/1.0/IGnssDebug.h> +#include <hidl/Status.h> + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +using ::android::hardware::gnss::V1_0::IGnssDebug; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::hidl_vec; +using ::android::hardware::hidl_string; +using ::android::sp; + +/* Interface for GNSS Debug support. */ +struct Gnss; +struct GnssDebug : public IGnssDebug { + GnssDebug(Gnss* gnss); + ~GnssDebug() {}; + + /* + * Methods from ::android::hardware::gnss::V1_0::IGnssDebug follow. + * These declarations were generated from IGnssDebug.hal. + */ + Return<void> getDebugData(getDebugData_cb _hidl_cb) override; + +private: + Gnss* mGnss = nullptr; +}; + +} // namespace implementation +} // namespace V2_0 +} // namespace gnss +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GNSS_V2_0_GNSSDEBUG_H diff --git a/android/2.0/GnssGeofencing.cpp b/android/2.0/GnssGeofencing.cpp new file mode 100644 index 0000000..b72d835 --- /dev/null +++ b/android/2.0/GnssGeofencing.cpp @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Not a Contribution + */ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "GnssHal_GnssGeofencing" + +#include <log_util.h> +#include <GeofenceAPIClient.h> +#include "GnssGeofencing.h" + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +void GnssGeofencing::GnssGeofencingDeathRecipient::serviceDied( + uint64_t cookie, const wp<IBase>& who) { + LOC_LOGE("%s] service died. cookie: %llu, who: %p", + __FUNCTION__, static_cast<unsigned long long>(cookie), &who); + if (mGnssGeofencing != nullptr) { + mGnssGeofencing->removeAllGeofences(); + } +} + +GnssGeofencing::GnssGeofencing() : mApi(nullptr) { + mGnssGeofencingDeathRecipient = new GnssGeofencingDeathRecipient(this); +} + +GnssGeofencing::~GnssGeofencing() { + if (mApi != nullptr) { + delete mApi; + mApi = nullptr; + } +} + +// Methods from ::android::hardware::gnss::V1_0::IGnssGeofencing follow. +Return<void> GnssGeofencing::setCallback(const sp<IGnssGeofenceCallback>& callback) { + if (mApi != nullptr) { + LOC_LOGd("mApi is NOT nullptr"); + return Void(); + } + + mApi = new GeofenceAPIClient(callback); + if (mApi == nullptr) { + LOC_LOGE("%s]: failed to create mApi", __FUNCTION__); + } + + if (mGnssGeofencingCbIface != nullptr) { + mGnssGeofencingCbIface->unlinkToDeath(mGnssGeofencingDeathRecipient); + } + mGnssGeofencingCbIface = callback; + if (mGnssGeofencingCbIface != nullptr) { + mGnssGeofencingCbIface->linkToDeath(mGnssGeofencingDeathRecipient, 0 /*cookie*/); + } + + return Void(); +} + +Return<void> GnssGeofencing::addGeofence( + int32_t geofenceId, + double latitudeDegrees, + double longitudeDegrees, + double radiusMeters, + IGnssGeofenceCallback::GeofenceTransition lastTransition, + int32_t monitorTransitions, + uint32_t notificationResponsivenessMs, + uint32_t unknownTimerMs) { + if (mApi == nullptr) { + LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); + } else { + mApi->geofenceAdd( + geofenceId, + latitudeDegrees, + longitudeDegrees, + radiusMeters, + static_cast<int32_t>(lastTransition), + monitorTransitions, + notificationResponsivenessMs, + unknownTimerMs); + } + return Void(); +} + +Return<void> GnssGeofencing::pauseGeofence(int32_t geofenceId) { + if (mApi == nullptr) { + LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); + } else { + mApi->geofencePause(geofenceId); + } + return Void(); +} + +Return<void> GnssGeofencing::resumeGeofence(int32_t geofenceId, int32_t monitorTransitions) { + if (mApi == nullptr) { + LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); + } else { + mApi->geofenceResume(geofenceId, monitorTransitions); + } + return Void(); +} + +Return<void> GnssGeofencing::removeGeofence(int32_t geofenceId) { + if (mApi == nullptr) { + LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); + } else { + mApi->geofenceRemove(geofenceId); + } + return Void(); +} + +Return<void> GnssGeofencing::removeAllGeofences() { + if (mApi == nullptr) { + LOC_LOGD("%s]: mApi is nullptr, do nothing", __FUNCTION__); + } else { + mApi->geofenceRemoveAll(); + } + return Void(); +} + +} // namespace implementation +} // namespace V2_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/android/2.0/GnssGeofencing.h b/android/2.0/GnssGeofencing.h new file mode 100644 index 0000000..caa56d0 --- /dev/null +++ b/android/2.0/GnssGeofencing.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Not a Contribution + */ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_GNSS_V2_0_GNSSGEOFENCING_H +#define ANDROID_HARDWARE_GNSS_V2_0_GNSSGEOFENCING_H + +#include <android/hardware/gnss/1.0/IGnssGeofencing.h> +#include <hidl/Status.h> + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +using ::android::hardware::gnss::V1_0::IGnssGeofenceCallback; +using ::android::hardware::gnss::V1_0::IGnssGeofencing; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::hidl_vec; +using ::android::hardware::hidl_string; +using ::android::sp; + +class GeofenceAPIClient; +struct GnssGeofencing : public IGnssGeofencing { + GnssGeofencing(); + ~GnssGeofencing(); + + /* + * Methods from ::android::hardware::gnss::V1_0::IGnssGeofencing follow. + * These declarations were generated from IGnssGeofencing.hal. + */ + Return<void> setCallback(const sp<IGnssGeofenceCallback>& callback) override; + Return<void> addGeofence(int32_t geofenceId, + double latitudeDegrees, + double longitudeDegrees, + double radiusMeters, + IGnssGeofenceCallback::GeofenceTransition lastTransition, + int32_t monitorTransitions, + uint32_t notificationResponsivenessMs, + uint32_t unknownTimerMs) override; + + Return<void> pauseGeofence(int32_t geofenceId) override; + Return<void> resumeGeofence(int32_t geofenceId, int32_t monitorTransitions) override; + Return<void> removeGeofence(int32_t geofenceId) override; + + private: + // This method is not part of the IGnss base class. + // It is called by GnssGeofencingDeathRecipient to remove all geofences added so far. + Return<void> removeAllGeofences(); + + private: + struct GnssGeofencingDeathRecipient : hidl_death_recipient { + GnssGeofencingDeathRecipient(sp<GnssGeofencing> gnssGeofencing) : + mGnssGeofencing(gnssGeofencing) { + } + ~GnssGeofencingDeathRecipient() = default; + virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override; + sp<GnssGeofencing> mGnssGeofencing; + }; + + private: + sp<GnssGeofencingDeathRecipient> mGnssGeofencingDeathRecipient = nullptr; + sp<IGnssGeofenceCallback> mGnssGeofencingCbIface = nullptr; + GeofenceAPIClient* mApi = nullptr; +}; + +} // namespace implementation +} // namespace V2_0 +} // namespace gnss +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GNSS_V2_0_GNSSGEOFENCING_H diff --git a/android/2.0/GnssMeasurement.cpp b/android/2.0/GnssMeasurement.cpp new file mode 100644 index 0000000..721a48c --- /dev/null +++ b/android/2.0/GnssMeasurement.cpp @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Not a Contribution + */ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "LocSvc_GnssMeasurementInterface" + +#include <log_util.h> +#include "GnssMeasurement.h" +#include "MeasurementAPIClient.h" + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +void GnssMeasurement::GnssMeasurementDeathRecipient::serviceDied( + uint64_t cookie, const wp<IBase>& who) { + LOC_LOGE("%s] service died. cookie: %llu, who: %p", + __FUNCTION__, static_cast<unsigned long long>(cookie), &who); + if (mGnssMeasurement != nullptr) { + mGnssMeasurement->close(); + } +} + +GnssMeasurement::GnssMeasurement() { + mGnssMeasurementDeathRecipient = new GnssMeasurementDeathRecipient(this); + mApi = new MeasurementAPIClient(); +} + +GnssMeasurement::~GnssMeasurement() { + if (mApi) { + delete mApi; + mApi = nullptr; + } +} + +// Methods from ::android::hardware::gnss::V1_0::IGnssMeasurement follow. +Return<GnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback( + const sp<V1_0::IGnssMeasurementCallback>& callback) { + + Return<GnssMeasurement::GnssMeasurementStatus> ret = + IGnssMeasurement::GnssMeasurementStatus::ERROR_GENERIC; + if (mGnssMeasurementCbIface != nullptr) { + LOC_LOGE("%s]: GnssMeasurementCallback is already set", __FUNCTION__); + return IGnssMeasurement::GnssMeasurementStatus::ERROR_ALREADY_INIT; + } + + if (callback == nullptr) { + LOC_LOGE("%s]: callback is nullptr", __FUNCTION__); + return ret; + } + if (mApi == nullptr) { + LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); + return ret; + } + + mGnssMeasurementCbIface = callback; + mGnssMeasurementCbIface->linkToDeath(mGnssMeasurementDeathRecipient, 0); + + return mApi->measurementSetCallback(callback); +} + +Return<void> GnssMeasurement::close() { + if (mApi == nullptr) { + LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); + return Void(); + } + + if (mGnssMeasurementCbIface != nullptr) { + mGnssMeasurementCbIface->unlinkToDeath(mGnssMeasurementDeathRecipient); + mGnssMeasurementCbIface = nullptr; + } + if (mGnssMeasurementCbIface_1_1 != nullptr) { + mGnssMeasurementCbIface_1_1->unlinkToDeath(mGnssMeasurementDeathRecipient); + mGnssMeasurementCbIface_1_1 = nullptr; + } + if (mGnssMeasurementCbIface_2_0 != nullptr) { + mGnssMeasurementCbIface_2_0->unlinkToDeath(mGnssMeasurementDeathRecipient); + mGnssMeasurementCbIface_2_0 = nullptr; + } + mApi->measurementClose(); + + return Void(); +} + +// Methods from ::android::hardware::gnss::V1_1::IGnssMeasurement follow. +Return<GnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback_1_1( + const sp<V1_1::IGnssMeasurementCallback>& callback, bool enableFullTracking) { + + Return<GnssMeasurement::GnssMeasurementStatus> ret = + IGnssMeasurement::GnssMeasurementStatus::ERROR_GENERIC; + if (mGnssMeasurementCbIface_1_1 != nullptr) { + LOC_LOGE("%s]: GnssMeasurementCallback is already set", __FUNCTION__); + return IGnssMeasurement::GnssMeasurementStatus::ERROR_ALREADY_INIT; + } + + if (callback == nullptr) { + LOC_LOGE("%s]: callback is nullptr", __FUNCTION__); + return ret; + } + if (nullptr == mApi) { + LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); + return ret; + } + + mGnssMeasurementCbIface_1_1 = callback; + mGnssMeasurementCbIface_1_1->linkToDeath(mGnssMeasurementDeathRecipient, 0); + + GnssPowerMode powerMode = enableFullTracking? + GNSS_POWER_MODE_M1 : GNSS_POWER_MODE_M2; + + return mApi->measurementSetCallback_1_1(callback, powerMode); +} +// Methods from ::android::hardware::gnss::V2_0::IGnssMeasurement follow. +Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback_2_0( + const sp<V2_0::IGnssMeasurementCallback>& callback, + bool enableFullTracking) { + + Return<GnssMeasurement::GnssMeasurementStatus> ret = + IGnssMeasurement::GnssMeasurementStatus::ERROR_GENERIC; + if (mGnssMeasurementCbIface_2_0 != nullptr) { + LOC_LOGE("%s]: GnssMeasurementCallback is already set", __FUNCTION__); + return IGnssMeasurement::GnssMeasurementStatus::ERROR_ALREADY_INIT; + } + + if (callback == nullptr) { + LOC_LOGE("%s]: callback is nullptr", __FUNCTION__); + return ret; + } + if (nullptr == mApi) { + LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); + return ret; + } + + mGnssMeasurementCbIface_2_0 = callback; + mGnssMeasurementCbIface_2_0->linkToDeath(mGnssMeasurementDeathRecipient, 0); + + GnssPowerMode powerMode = enableFullTracking ? + GNSS_POWER_MODE_M1 : GNSS_POWER_MODE_M2; + + return mApi->measurementSetCallback_2_0(callback, powerMode); +} + +} // namespace implementation +} // namespace V2_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/android/2.0/GnssMeasurement.h b/android/2.0/GnssMeasurement.h new file mode 100644 index 0000000..000b00f --- /dev/null +++ b/android/2.0/GnssMeasurement.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Not a Contribution + */ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_GNSS_V2_0_GNSSMEASUREMENT_H +#define ANDROID_HARDWARE_GNSS_V2_0_GNSSMEASUREMENT_H + +#include <android/hardware/gnss/2.0/IGnssMeasurement.h> +#include <hidl/MQDescriptor.h> +#include <hidl/Status.h> + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::hidl_vec; +using ::android::hardware::hidl_string; +using ::android::sp; + +class MeasurementAPIClient; +struct GnssMeasurement : public V2_0::IGnssMeasurement { + GnssMeasurement(); + ~GnssMeasurement(); + + /* + * Methods from ::android::hardware::gnss::V1_0::IGnssMeasurement follow. + * These declarations were generated from IGnssMeasurement.hal. + */ + Return<GnssMeasurement::GnssMeasurementStatus> setCallback( + const sp<V1_0::IGnssMeasurementCallback>& callback) override; + Return<void> close() override; + + // Methods from ::android::hardware::gnss::V1_1::IGnssMeasurement follow. + Return<GnssMeasurement::GnssMeasurementStatus> setCallback_1_1( + const sp<V1_1::IGnssMeasurementCallback>& callback, + bool enableFullTracking) override; + + // Methods from ::android::hardware::gnss::V2_0::IGnssMeasurement follow. + Return<GnssMeasurement::GnssMeasurementStatus> setCallback_2_0( + const sp<V2_0::IGnssMeasurementCallback>& callback, + bool enableFullTracking) override; + private: + struct GnssMeasurementDeathRecipient : hidl_death_recipient { + GnssMeasurementDeathRecipient(sp<GnssMeasurement> gnssMeasurement) : + mGnssMeasurement(gnssMeasurement) { + } + ~GnssMeasurementDeathRecipient() = default; + virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override; + sp<GnssMeasurement> mGnssMeasurement; + }; + + private: + sp<GnssMeasurementDeathRecipient> mGnssMeasurementDeathRecipient = nullptr; + sp<V1_0::IGnssMeasurementCallback> mGnssMeasurementCbIface = nullptr; + sp<V1_1::IGnssMeasurementCallback> mGnssMeasurementCbIface_1_1 = nullptr; + sp<V2_0::IGnssMeasurementCallback> mGnssMeasurementCbIface_2_0 = nullptr; + MeasurementAPIClient* mApi; +}; + +} // namespace implementation +} // namespace V2_0 +} // namespace gnss +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GNSS_V2_0_GNSSMEASUREMENT_H diff --git a/android/2.0/GnssNi.cpp b/android/2.0/GnssNi.cpp new file mode 100644 index 0000000..d65a488 --- /dev/null +++ b/android/2.0/GnssNi.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Not a Contribution + */ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "LocSvc_GnssNiInterface" + +#include <log_util.h> +#include "Gnss.h" +#include "GnssNi.h" + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +void GnssNi::GnssNiDeathRecipient::serviceDied(uint64_t cookie, const wp<IBase>& who) { + LOC_LOGE("%s] service died. cookie: %llu, who: %p", + __FUNCTION__, static_cast<unsigned long long>(cookie), &who); + // we do nothing here + // Gnss::GnssDeathRecipient will stop the session +} + +GnssNi::GnssNi(Gnss* gnss) : mGnss(gnss) { + mGnssNiDeathRecipient = new GnssNiDeathRecipient(this); +} + +// Methods from ::android::hardware::gnss::V1_0::IGnssNi follow. +Return<void> GnssNi::setCallback(const sp<IGnssNiCallback>& callback) { + if (mGnss == nullptr) { + LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__); + return Void(); + } + + mGnss->setGnssNiCb(callback); + + if (mGnssNiCbIface != nullptr) { + mGnssNiCbIface->unlinkToDeath(mGnssNiDeathRecipient); + } + mGnssNiCbIface = callback; + if (mGnssNiCbIface != nullptr) { + mGnssNiCbIface->linkToDeath(mGnssNiDeathRecipient, 0 /*cookie*/); + } + + return Void(); +} + +Return<void> GnssNi::respond(int32_t notifId, IGnssNiCallback::GnssUserResponseType userResponse) { + if (mGnss == nullptr) { + LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__); + return Void(); + } + + GnssAPIClient* api = mGnss->getApi(); + if (api == nullptr) { + LOC_LOGE("%s]: api is nullptr", __FUNCTION__); + return Void(); + } + + api->gnssNiRespond(notifId, userResponse); + + return Void(); +} + +} // namespace implementation +} // namespace V2_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/android/2.0/GnssNi.h b/android/2.0/GnssNi.h new file mode 100644 index 0000000..26e281f --- /dev/null +++ b/android/2.0/GnssNi.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Not a Contribution + */ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_GNSS_V2_0_GNSSNI_H +#define ANDROID_HARDWARE_GNSS_V2_0_GNSSNI_H + +#include <android/hardware/gnss/1.0/IGnssNi.h> +#include <hidl/Status.h> + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +using ::android::hardware::gnss::V1_0::IGnssNi; +using ::android::hardware::gnss::V1_0::IGnssNiCallback; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::hidl_vec; +using ::android::hardware::hidl_string; +using ::android::sp; + +struct Gnss; +struct GnssNi : public IGnssNi { + GnssNi(Gnss* gnss); + ~GnssNi() = default; + + /* + * Methods from ::android::hardware::gnss::V1_0::IGnssNi follow. + * These declarations were generated from IGnssNi.hal. + */ + Return<void> setCallback(const sp<IGnssNiCallback>& callback) override; + Return<void> respond(int32_t notifId, + IGnssNiCallback::GnssUserResponseType userResponse) override; + + private: + struct GnssNiDeathRecipient : hidl_death_recipient { + GnssNiDeathRecipient(sp<GnssNi> gnssNi) : mGnssNi(gnssNi) { + } + ~GnssNiDeathRecipient() = default; + virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override; + sp<GnssNi> mGnssNi; + }; + + private: + sp<GnssNiDeathRecipient> mGnssNiDeathRecipient = nullptr; + sp<IGnssNiCallback> mGnssNiCbIface = nullptr; + Gnss* mGnss = nullptr; +}; + +} // namespace implementation +} // namespace V2_0 +} // namespace gnss +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GNSS_V2_0_GNSSNI_H diff --git a/android/dummy/android.hardware.gnss@1.0-service-qti.rc b/android/2.0/android.hardware.gnss@2.0-service-qti.rc index b5da6f9..36ee47c 100644 --- a/android/dummy/android.hardware.gnss@1.0-service-qti.rc +++ b/android/2.0/android.hardware.gnss@2.0-service-qti.rc @@ -1,4 +1,4 @@ -service gnss_service /vendor/bin/hw/android.hardware.gnss@1.0-service-qti +service gnss_service /vendor/bin/hw/android.hardware.gnss@2.0-service-qti class hal user gps group system gps radio diff --git a/android/2.0/location_api/BatchingAPIClient.cpp b/android/2.0/location_api/BatchingAPIClient.cpp new file mode 100644 index 0000000..48caee6 --- /dev/null +++ b/android/2.0/location_api/BatchingAPIClient.cpp @@ -0,0 +1,196 @@ +/* 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_BatchingAPIClient" + +#include <log_util.h> +#include <loc_cfg.h> + +#include "LocationUtil.h" +#include "BatchingAPIClient.h" + +#include "limits.h" + + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +using ::android::hardware::gnss::V1_0::IGnssBatching; +using ::android::hardware::gnss::V1_0::IGnssBatchingCallback; +using ::android::hardware::gnss::V1_0::GnssLocation; + +static void convertBatchOption(const IGnssBatching::Options& in, LocationOptions& out, + LocationCapabilitiesMask mask); + +BatchingAPIClient::BatchingAPIClient(const sp<IGnssBatchingCallback>& callback) : + LocationAPIClientBase(), + mGnssBatchingCbIface(callback), + mDefaultId(UINT_MAX), + mLocationCapabilitiesMask(0) +{ + LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback); + + LocationCallbacks locationCallbacks; + memset(&locationCallbacks, 0, sizeof(LocationCallbacks)); + locationCallbacks.size = sizeof(LocationCallbacks); + + locationCallbacks.trackingCb = nullptr; + locationCallbacks.batchingCb = nullptr; + if (mGnssBatchingCbIface != nullptr) { + locationCallbacks.batchingCb = [this](size_t count, Location* location, + BatchingOptions batchOptions) { + onBatchingCb(count, location, batchOptions); + }; + } + locationCallbacks.geofenceBreachCb = nullptr; + locationCallbacks.geofenceStatusCb = nullptr; + locationCallbacks.gnssLocationInfoCb = nullptr; + locationCallbacks.gnssNiCb = nullptr; + locationCallbacks.gnssSvCb = nullptr; + locationCallbacks.gnssNmeaCb = nullptr; + locationCallbacks.gnssMeasurementsCb = nullptr; + + locAPISetCallbacks(locationCallbacks); +} + +BatchingAPIClient::~BatchingAPIClient() +{ + LOC_LOGD("%s]: ()", __FUNCTION__); +} + +int BatchingAPIClient::getBatchSize() +{ + LOC_LOGD("%s]: ()", __FUNCTION__); + return locAPIGetBatchSize(); +} + +int BatchingAPIClient::startSession(const IGnssBatching::Options& opts) +{ + LOC_LOGD("%s]: (%lld %d)", __FUNCTION__, + static_cast<long long>(opts.periodNanos), static_cast<uint8_t>(opts.flags)); + int retVal = -1; + LocationOptions options; + convertBatchOption(opts, options, mLocationCapabilitiesMask); + uint32_t mode = 0; + if (opts.flags == static_cast<uint8_t>(IGnssBatching::Flag::WAKEUP_ON_FIFO_FULL)) { + mode = SESSION_MODE_ON_FULL; + } + if (locAPIStartSession(mDefaultId, mode, options) == LOCATION_ERROR_SUCCESS) { + retVal = 1; + } + return retVal; +} + +int BatchingAPIClient::updateSessionOptions(const IGnssBatching::Options& opts) +{ + LOC_LOGD("%s]: (%lld %d)", __FUNCTION__, + static_cast<long long>(opts.periodNanos), static_cast<uint8_t>(opts.flags)); + int retVal = -1; + LocationOptions options; + convertBatchOption(opts, options, mLocationCapabilitiesMask); + + uint32_t mode = 0; + if (opts.flags == static_cast<uint8_t>(IGnssBatching::Flag::WAKEUP_ON_FIFO_FULL)) { + mode = SESSION_MODE_ON_FULL; + } + if (locAPIUpdateSessionOptions(mDefaultId, mode, options) == LOCATION_ERROR_SUCCESS) { + retVal = 1; + } + return retVal; +} + +int BatchingAPIClient::stopSession() +{ + LOC_LOGD("%s]: ", __FUNCTION__); + int retVal = -1; + if (locAPIStopSession(mDefaultId) == LOCATION_ERROR_SUCCESS) { + retVal = 1; + } + return retVal; +} + +void BatchingAPIClient::getBatchedLocation(int last_n_locations) +{ + LOC_LOGD("%s]: (%d)", __FUNCTION__, last_n_locations); + locAPIGetBatchedLocations(mDefaultId, last_n_locations); +} + +void BatchingAPIClient::flushBatchedLocations() +{ + LOC_LOGD("%s]: ()", __FUNCTION__); + locAPIGetBatchedLocations(mDefaultId, SIZE_MAX); +} + +void BatchingAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask) +{ + LOC_LOGD("%s]: (%02x)", __FUNCTION__, capabilitiesMask); + mLocationCapabilitiesMask = capabilitiesMask; +} + +void BatchingAPIClient::onBatchingCb(size_t count, Location* location, + BatchingOptions /*batchOptions*/) +{ + LOC_LOGD("%s]: (count: %zu)", __FUNCTION__, count); + if (mGnssBatchingCbIface != nullptr && count > 0) { + hidl_vec<GnssLocation> locationVec; + locationVec.resize(count); + for (size_t i = 0; i < count; i++) { + convertGnssLocation(location[i], locationVec[i]); + } + auto r = mGnssBatchingCbIface->gnssLocationBatchCb(locationVec); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssLocationBatchCb description=%s", + __func__, r.description().c_str()); + } + } +} + +static void convertBatchOption(const IGnssBatching::Options& in, LocationOptions& out, + LocationCapabilitiesMask mask) +{ + memset(&out, 0, sizeof(LocationOptions)); + out.size = sizeof(LocationOptions); + out.minInterval = (uint32_t)(in.periodNanos / 1000000L); + out.minDistance = 0; + out.mode = GNSS_SUPL_MODE_STANDALONE; + if (mask & LOCATION_CAPABILITIES_GNSS_MSA_BIT) + out.mode = GNSS_SUPL_MODE_MSA; + if (mask & LOCATION_CAPABILITIES_GNSS_MSB_BIT) + out.mode = GNSS_SUPL_MODE_MSB; +} + +} // namespace implementation +} // namespace V2_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/android/2.0/location_api/BatchingAPIClient.h b/android/2.0/location_api/BatchingAPIClient.h new file mode 100644 index 0000000..33a8c2e --- /dev/null +++ b/android/2.0/location_api/BatchingAPIClient.h @@ -0,0 +1,74 @@ +/* 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_API_CLINET_H +#define BATCHING_API_CLINET_H + +#include <android/hardware/gnss/1.0/IGnssBatching.h> +#include <android/hardware/gnss/1.0/IGnssBatchingCallback.h> +#include <pthread.h> + +#include <LocationAPIClientBase.h> + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +class BatchingAPIClient : public LocationAPIClientBase +{ +public: + BatchingAPIClient(const sp<V1_0::IGnssBatchingCallback>& callback); + ~BatchingAPIClient(); + int getBatchSize(); + int startSession(const V1_0::IGnssBatching::Options& options); + int updateSessionOptions(const V1_0::IGnssBatching::Options& options); + int stopSession(); + void getBatchedLocation(int last_n_locations); + void flushBatchedLocations(); + + inline LocationCapabilitiesMask getCapabilities() { return mLocationCapabilitiesMask; } + + // callbacks + void onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask) final; + void onBatchingCb(size_t count, Location* location, BatchingOptions batchOptions) final; + +private: + sp<V1_0::IGnssBatchingCallback> mGnssBatchingCbIface; + uint32_t mDefaultId; + LocationCapabilitiesMask mLocationCapabilitiesMask; +}; + +} // namespace implementation +} // namespace V2_0 +} // namespace gnss +} // namespace hardware +} // namespace android +#endif // BATCHING_API_CLINET_H diff --git a/android/2.0/location_api/GeofenceAPIClient.cpp b/android/2.0/location_api/GeofenceAPIClient.cpp new file mode 100644 index 0000000..fabf8bb --- /dev/null +++ b/android/2.0/location_api/GeofenceAPIClient.cpp @@ -0,0 +1,275 @@ +/* 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_GeofenceApiClient" + +#include <log_util.h> +#include <loc_cfg.h> + +#include "LocationUtil.h" +#include "GeofenceAPIClient.h" + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +using ::android::hardware::gnss::V1_0::IGnssGeofenceCallback; +using ::android::hardware::gnss::V1_0::GnssLocation; + +GeofenceAPIClient::GeofenceAPIClient(const sp<IGnssGeofenceCallback>& callback) : + LocationAPIClientBase(), + mGnssGeofencingCbIface(callback) +{ + LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback); + + LocationCallbacks locationCallbacks; + memset(&locationCallbacks, 0, sizeof(LocationCallbacks)); + locationCallbacks.size = sizeof(LocationCallbacks); + + locationCallbacks.trackingCb = nullptr; + locationCallbacks.batchingCb = nullptr; + + locationCallbacks.geofenceBreachCb = nullptr; + if (mGnssGeofencingCbIface != nullptr) { + locationCallbacks.geofenceBreachCb = + [this](GeofenceBreachNotification geofenceBreachNotification) { + onGeofenceBreachCb(geofenceBreachNotification); + }; + + locationCallbacks.geofenceStatusCb = + [this](GeofenceStatusNotification geofenceStatusNotification) { + onGeofenceStatusCb(geofenceStatusNotification); + }; + } + + locationCallbacks.gnssLocationInfoCb = nullptr; + locationCallbacks.gnssNiCb = nullptr; + locationCallbacks.gnssSvCb = nullptr; + locationCallbacks.gnssNmeaCb = nullptr; + locationCallbacks.gnssMeasurementsCb = nullptr; + + locAPISetCallbacks(locationCallbacks); +} + +void GeofenceAPIClient::geofenceAdd(uint32_t geofence_id, double latitude, double longitude, + double radius_meters, int32_t last_transition, int32_t monitor_transitions, + uint32_t notification_responsiveness_ms, uint32_t unknown_timer_ms) +{ + LOC_LOGD("%s]: (%d %f %f %f %d %d %d %d)", __FUNCTION__, + geofence_id, latitude, longitude, radius_meters, + last_transition, monitor_transitions, notification_responsiveness_ms, unknown_timer_ms); + + GeofenceOption options; + memset(&options, 0, sizeof(GeofenceOption)); + options.size = sizeof(GeofenceOption); + if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::ENTERED) + options.breachTypeMask |= GEOFENCE_BREACH_ENTER_BIT; + if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::EXITED) + options.breachTypeMask |= GEOFENCE_BREACH_EXIT_BIT; + options.responsiveness = notification_responsiveness_ms; + + GeofenceInfo data; + data.size = sizeof(GeofenceInfo); + data.latitude = latitude; + data.longitude = longitude; + data.radius = radius_meters; + + LocationError err = (LocationError)locAPIAddGeofences(1, &geofence_id, &options, &data); + if (LOCATION_ERROR_SUCCESS != err) { + onAddGeofencesCb(1, &err, &geofence_id); + } +} + +void GeofenceAPIClient::geofencePause(uint32_t geofence_id) +{ + LOC_LOGD("%s]: (%d)", __FUNCTION__, geofence_id); + locAPIPauseGeofences(1, &geofence_id); +} + +void GeofenceAPIClient::geofenceResume(uint32_t geofence_id, int32_t monitor_transitions) +{ + LOC_LOGD("%s]: (%d %d)", __FUNCTION__, geofence_id, monitor_transitions); + GeofenceBreachTypeMask mask = 0; + if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::ENTERED) + mask |= GEOFENCE_BREACH_ENTER_BIT; + if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::EXITED) + mask |= GEOFENCE_BREACH_EXIT_BIT; + locAPIResumeGeofences(1, &geofence_id, &mask); +} + +void GeofenceAPIClient::geofenceRemove(uint32_t geofence_id) +{ + LOC_LOGD("%s]: (%d)", __FUNCTION__, geofence_id); + locAPIRemoveGeofences(1, &geofence_id); +} + +void GeofenceAPIClient::geofenceRemoveAll() +{ + LOC_LOGD("%s]", __FUNCTION__); + // TODO locAPIRemoveAllGeofences(); +} + +// callbacks +void GeofenceAPIClient::onGeofenceBreachCb(GeofenceBreachNotification geofenceBreachNotification) +{ + LOC_LOGD("%s]: (%zu)", __FUNCTION__, geofenceBreachNotification.count); + if (mGnssGeofencingCbIface != nullptr) { + for (size_t i = 0; i < geofenceBreachNotification.count; i++) { + GnssLocation gnssLocation; + convertGnssLocation(geofenceBreachNotification.location, gnssLocation); + + IGnssGeofenceCallback::GeofenceTransition transition; + if (geofenceBreachNotification.type == GEOFENCE_BREACH_ENTER) + transition = IGnssGeofenceCallback::GeofenceTransition::ENTERED; + else if (geofenceBreachNotification.type == GEOFENCE_BREACH_EXIT) + transition = IGnssGeofenceCallback::GeofenceTransition::EXITED; + else { + // continue with other breach if transition is + // nether GPS_GEOFENCE_ENTERED nor GPS_GEOFENCE_EXITED + continue; + } + + auto r = mGnssGeofencingCbIface->gnssGeofenceTransitionCb( + geofenceBreachNotification.ids[i], gnssLocation, transition, + static_cast<V1_0::GnssUtcTime>(geofenceBreachNotification.timestamp)); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssGeofenceTransitionCb description=%s", + __func__, r.description().c_str()); + } + } + } +} + +void GeofenceAPIClient::onGeofenceStatusCb(GeofenceStatusNotification geofenceStatusNotification) +{ + LOC_LOGD("%s]: (%d)", __FUNCTION__, geofenceStatusNotification.available); + if (mGnssGeofencingCbIface != nullptr) { + IGnssGeofenceCallback::GeofenceAvailability status = + IGnssGeofenceCallback::GeofenceAvailability::UNAVAILABLE; + if (geofenceStatusNotification.available == GEOFENCE_STATUS_AVAILABILE_YES) { + status = IGnssGeofenceCallback::GeofenceAvailability::AVAILABLE; + } + GnssLocation gnssLocation; + memset(&gnssLocation, 0, sizeof(GnssLocation)); + auto r = mGnssGeofencingCbIface->gnssGeofenceStatusCb(status, gnssLocation); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssGeofenceStatusCb description=%s", + __func__, r.description().c_str()); + } + } +} + +void GeofenceAPIClient::onAddGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) +{ + LOC_LOGD("%s]: (%zu)", __FUNCTION__, count); + if (mGnssGeofencingCbIface != nullptr) { + for (size_t i = 0; i < count; i++) { + IGnssGeofenceCallback::GeofenceStatus status = + IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC; + if (errors[i] == LOCATION_ERROR_SUCCESS) + status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS; + else if (errors[i] == LOCATION_ERROR_ID_EXISTS) + status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_EXISTS; + auto r = mGnssGeofencingCbIface->gnssGeofenceAddCb(ids[i], status); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssGeofenceAddCb description=%s", + __func__, r.description().c_str()); + } + } + } +} + +void GeofenceAPIClient::onRemoveGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) +{ + LOC_LOGD("%s]: (%zu)", __FUNCTION__, count); + if (mGnssGeofencingCbIface != nullptr) { + for (size_t i = 0; i < count; i++) { + IGnssGeofenceCallback::GeofenceStatus status = + IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC; + if (errors[i] == LOCATION_ERROR_SUCCESS) + status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS; + else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN) + status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN; + auto r = mGnssGeofencingCbIface->gnssGeofenceRemoveCb(ids[i], status); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssGeofenceRemoveCb description=%s", + __func__, r.description().c_str()); + } + } + } +} + +void GeofenceAPIClient::onPauseGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) +{ + LOC_LOGD("%s]: (%zu)", __FUNCTION__, count); + if (mGnssGeofencingCbIface != nullptr) { + for (size_t i = 0; i < count; i++) { + IGnssGeofenceCallback::GeofenceStatus status = + IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC; + if (errors[i] == LOCATION_ERROR_SUCCESS) + status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS; + else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN) + status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN; + auto r = mGnssGeofencingCbIface->gnssGeofencePauseCb(ids[i], status); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssGeofencePauseCb description=%s", + __func__, r.description().c_str()); + } + } + } +} + +void GeofenceAPIClient::onResumeGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) +{ + LOC_LOGD("%s]: (%zu)", __FUNCTION__, count); + if (mGnssGeofencingCbIface != nullptr) { + for (size_t i = 0; i < count; i++) { + IGnssGeofenceCallback::GeofenceStatus status = + IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC; + if (errors[i] == LOCATION_ERROR_SUCCESS) + status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS; + else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN) + status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN; + auto r = mGnssGeofencingCbIface->gnssGeofenceResumeCb(ids[i], status); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssGeofenceResumeCb description=%s", + __func__, r.description().c_str()); + } + } + } +} + +} // namespace implementation +} // namespace V2_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/android/2.0/location_api/GeofenceAPIClient.h b/android/2.0/location_api/GeofenceAPIClient.h new file mode 100644 index 0000000..71049de --- /dev/null +++ b/android/2.0/location_api/GeofenceAPIClient.h @@ -0,0 +1,76 @@ +/* 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 GEOFENCE_API_CLINET_H +#define GEOFENCE_API_CLINET_H + + +#include <android/hardware/gnss/1.0/IGnssGeofenceCallback.h> +#include <LocationAPIClientBase.h> + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +using ::android::sp; + +class GeofenceAPIClient : public LocationAPIClientBase +{ +public: + GeofenceAPIClient(const sp<V1_0::IGnssGeofenceCallback>& callback); + virtual ~GeofenceAPIClient() = default; + + void geofenceAdd(uint32_t geofence_id, double latitude, double longitude, + double radius_meters, int32_t last_transition, int32_t monitor_transitions, + uint32_t notification_responsiveness_ms, uint32_t unknown_timer_ms); + void geofencePause(uint32_t geofence_id); + void geofenceResume(uint32_t geofence_id, int32_t monitor_transitions); + void geofenceRemove(uint32_t geofence_id); + void geofenceRemoveAll(); + + // callbacks + void onGeofenceBreachCb(GeofenceBreachNotification geofenceBreachNotification) final; + void onGeofenceStatusCb(GeofenceStatusNotification geofenceStatusNotification) final; + void onAddGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) final; + void onRemoveGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) final; + void onPauseGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) final; + void onResumeGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) final; + +private: + sp<V1_0::IGnssGeofenceCallback> mGnssGeofencingCbIface; +}; + +} // namespace implementation +} // namespace V2_0 +} // namespace gnss +} // namespace hardware +} // namespace android +#endif // GEOFENCE_API_CLINET_H diff --git a/android/2.0/location_api/GnssAPIClient.cpp b/android/2.0/location_api/GnssAPIClient.cpp new file mode 100644 index 0000000..44ae284 --- /dev/null +++ b/android/2.0/location_api/GnssAPIClient.cpp @@ -0,0 +1,565 @@ +/* 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_GnssAPIClient" +#define SINGLE_SHOT_MIN_TRACKING_INTERVAL_MSEC (590 * 60 * 60 * 1000) // 590 hours + +#include <log_util.h> +#include <loc_cfg.h> + +#include "LocationUtil.h" +#include "GnssAPIClient.h" +#include <LocContext.h> + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +using ::android::hardware::gnss::V1_0::IGnss; +using ::android::hardware::gnss::V1_0::IGnssCallback; +using ::android::hardware::gnss::V1_0::IGnssNiCallback; +using ::android::hardware::gnss::V1_0::GnssLocation; + +static void convertGnssSvStatus(GnssSvNotification& in, IGnssCallback::GnssSvStatus& out); + +GnssAPIClient::GnssAPIClient(const sp<IGnssCallback>& gpsCb, + const sp<IGnssNiCallback>& niCb) : + LocationAPIClientBase(), + mGnssCbIface(nullptr), + mGnssNiCbIface(nullptr), + mControlClient(new LocationAPIControlClient()), + mLocationCapabilitiesMask(0), + mLocationCapabilitiesCached(false) +{ + LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb); + + // set default LocationOptions. + memset(&mTrackingOptions, 0, sizeof(TrackingOptions)); + mTrackingOptions.size = sizeof(TrackingOptions); + mTrackingOptions.minInterval = 1000; + mTrackingOptions.minDistance = 0; + mTrackingOptions.mode = GNSS_SUPL_MODE_STANDALONE; + + gnssUpdateCallbacks(gpsCb, niCb); +} + +GnssAPIClient::~GnssAPIClient() +{ + LOC_LOGD("%s]: ()", __FUNCTION__); + if (mControlClient) { + delete mControlClient; + mControlClient = nullptr; + } +} + +// for GpsInterface +void GnssAPIClient::gnssUpdateCallbacks(const sp<IGnssCallback>& gpsCb, + const sp<IGnssNiCallback>& niCb) +{ + LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb); + + mMutex.lock(); + mGnssCbIface = gpsCb; + mGnssNiCbIface = niCb; + mMutex.unlock(); + + LocationCallbacks locationCallbacks; + memset(&locationCallbacks, 0, sizeof(LocationCallbacks)); + locationCallbacks.size = sizeof(LocationCallbacks); + + locationCallbacks.trackingCb = nullptr; + if (mGnssCbIface != nullptr) { + locationCallbacks.trackingCb = [this](Location location) { + onTrackingCb(location); + }; + } + + locationCallbacks.batchingCb = nullptr; + locationCallbacks.geofenceBreachCb = nullptr; + locationCallbacks.geofenceStatusCb = nullptr; + locationCallbacks.gnssLocationInfoCb = nullptr; + + locationCallbacks.gnssNiCb = nullptr; + loc_core::ContextBase* context = + loc_core::LocContext::getLocContext( + NULL, NULL, + loc_core::LocContext::mLocationHalName, false); + if (mGnssNiCbIface != nullptr && !context->hasAgpsExtendedCapabilities()) { + LOC_LOGD("Registering NI CB"); + locationCallbacks.gnssNiCb = [this](uint32_t id, GnssNiNotification gnssNiNotification) { + onGnssNiCb(id, gnssNiNotification); + }; + } + + locationCallbacks.gnssSvCb = nullptr; + if (mGnssCbIface != nullptr) { + locationCallbacks.gnssSvCb = [this](GnssSvNotification gnssSvNotification) { + onGnssSvCb(gnssSvNotification); + }; + } + + locationCallbacks.gnssNmeaCb = nullptr; + if (mGnssCbIface != nullptr) { + locationCallbacks.gnssNmeaCb = [this](GnssNmeaNotification gnssNmeaNotification) { + onGnssNmeaCb(gnssNmeaNotification); + }; + } + + locationCallbacks.gnssMeasurementsCb = nullptr; + + locAPISetCallbacks(locationCallbacks); +} + +bool GnssAPIClient::gnssStart() +{ + LOC_LOGD("%s]: ()", __FUNCTION__); + bool retVal = true; + locAPIStartTracking(mTrackingOptions); + return retVal; +} + +bool GnssAPIClient::gnssStop() +{ + LOC_LOGD("%s]: ()", __FUNCTION__); + bool retVal = true; + locAPIStopTracking(); + return retVal; +} + +bool GnssAPIClient::gnssSetPositionMode(IGnss::GnssPositionMode mode, + IGnss::GnssPositionRecurrence recurrence, uint32_t minIntervalMs, + uint32_t preferredAccuracyMeters, uint32_t preferredTimeMs, + GnssPowerMode powerMode, uint32_t timeBetweenMeasurement) +{ + LOC_LOGD("%s]: (%d %d %d %d %d %d %d)", __FUNCTION__, + (int)mode, recurrence, minIntervalMs, preferredAccuracyMeters, + preferredTimeMs, (int)powerMode, timeBetweenMeasurement); + bool retVal = true; + memset(&mTrackingOptions, 0, sizeof(TrackingOptions)); + mTrackingOptions.size = sizeof(TrackingOptions); + mTrackingOptions.minInterval = minIntervalMs; + if (IGnss::GnssPositionMode::MS_ASSISTED == mode || + IGnss::GnssPositionRecurrence::RECURRENCE_SINGLE == recurrence) { + // We set a very large interval to simulate SINGLE mode. Once we report a fix, + // the caller should take the responsibility to stop the session. + // For MSA, we always treat it as SINGLE mode. + mTrackingOptions.minInterval = SINGLE_SHOT_MIN_TRACKING_INTERVAL_MSEC; + } + mTrackingOptions.minDistance = preferredAccuracyMeters; + if (mode == IGnss::GnssPositionMode::STANDALONE) + mTrackingOptions.mode = GNSS_SUPL_MODE_STANDALONE; + else if (mode == IGnss::GnssPositionMode::MS_BASED) + mTrackingOptions.mode = GNSS_SUPL_MODE_MSB; + else if (mode == IGnss::GnssPositionMode::MS_ASSISTED) + mTrackingOptions.mode = GNSS_SUPL_MODE_MSA; + else { + LOC_LOGD("%s]: invalid GnssPositionMode: %d", __FUNCTION__, (int)mode); + retVal = false; + } + if (GNSS_POWER_MODE_INVALID != powerMode) { + mTrackingOptions.powerMode = powerMode; + mTrackingOptions.tbm = timeBetweenMeasurement; + } + locAPIUpdateTrackingOptions(mTrackingOptions); + return retVal; +} + +// for GpsNiInterface +void GnssAPIClient::gnssNiRespond(int32_t notifId, + IGnssNiCallback::GnssUserResponseType userResponse) +{ + LOC_LOGD("%s]: (%d %d)", __FUNCTION__, notifId, static_cast<int>(userResponse)); + GnssNiResponse data; + switch (userResponse) { + case IGnssNiCallback::GnssUserResponseType::RESPONSE_ACCEPT: + data = GNSS_NI_RESPONSE_ACCEPT; + break; + case IGnssNiCallback::GnssUserResponseType::RESPONSE_DENY: + data = GNSS_NI_RESPONSE_DENY; + break; + case IGnssNiCallback::GnssUserResponseType::RESPONSE_NORESP: + data = GNSS_NI_RESPONSE_NO_RESPONSE; + break; + default: + data = GNSS_NI_RESPONSE_IGNORE; + break; + } + + locAPIGnssNiResponse(notifId, data); +} + +// these apis using LocationAPIControlClient +void GnssAPIClient::gnssDeleteAidingData(IGnss::GnssAidingData aidingDataFlags) +{ + LOC_LOGD("%s]: (%02hx)", __FUNCTION__, aidingDataFlags); + if (mControlClient == nullptr) { + return; + } + GnssAidingData data; + memset(&data, 0, sizeof (GnssAidingData)); + data.sv.svTypeMask = GNSS_AIDING_DATA_SV_TYPE_GPS_BIT | + GNSS_AIDING_DATA_SV_TYPE_GLONASS_BIT | + GNSS_AIDING_DATA_SV_TYPE_QZSS_BIT | + GNSS_AIDING_DATA_SV_TYPE_BEIDOU_BIT | + GNSS_AIDING_DATA_SV_TYPE_GALILEO_BIT; + + if (aidingDataFlags == IGnss::GnssAidingData::DELETE_ALL) + data.deleteAll = true; + else { + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_EPHEMERIS) + data.sv.svMask |= GNSS_AIDING_DATA_SV_EPHEMERIS_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_ALMANAC) + data.sv.svMask |= GNSS_AIDING_DATA_SV_ALMANAC_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_POSITION) + data.common.mask |= GNSS_AIDING_DATA_COMMON_POSITION_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_TIME) + data.common.mask |= GNSS_AIDING_DATA_COMMON_TIME_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_IONO) + data.sv.svMask |= GNSS_AIDING_DATA_SV_IONOSPHERE_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_UTC) + data.common.mask |= GNSS_AIDING_DATA_COMMON_UTC_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_HEALTH) + data.sv.svMask |= GNSS_AIDING_DATA_SV_HEALTH_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SVDIR) + data.sv.svMask |= GNSS_AIDING_DATA_SV_DIRECTION_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SVSTEER) + data.sv.svMask |= GNSS_AIDING_DATA_SV_STEER_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SADATA) + data.sv.svMask |= GNSS_AIDING_DATA_SV_SA_DATA_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_RTI) + data.common.mask |= GNSS_AIDING_DATA_COMMON_RTI_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_CELLDB_INFO) + data.common.mask |= GNSS_AIDING_DATA_COMMON_CELLDB_BIT; + } + mControlClient->locAPIGnssDeleteAidingData(data); +} + +void GnssAPIClient::gnssEnable(LocationTechnologyType techType) +{ + LOC_LOGD("%s]: (%0d)", __FUNCTION__, techType); + if (mControlClient == nullptr) { + return; + } + mControlClient->locAPIEnable(techType); +} + +void GnssAPIClient::gnssDisable() +{ + LOC_LOGD("%s]: ()", __FUNCTION__); + if (mControlClient == nullptr) { + return; + } + mControlClient->locAPIDisable(); +} + +void GnssAPIClient::gnssConfigurationUpdate(const GnssConfig& gnssConfig) +{ + LOC_LOGD("%s]: (%02x)", __FUNCTION__, gnssConfig.flags); + if (mControlClient == nullptr) { + return; + } + mControlClient->locAPIGnssUpdateConfig(gnssConfig); +} + +void GnssAPIClient::requestCapabilities() { + // only send capablities if it's already cached, otherwise the first time LocationAPI + // is initialized, capabilities will be sent by LocationAPI + if (mLocationCapabilitiesCached) { + onCapabilitiesCb(mLocationCapabilitiesMask); + } +} + +// callbacks +void GnssAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask) +{ + LOC_LOGD("%s]: (%02x)", __FUNCTION__, capabilitiesMask); + mLocationCapabilitiesMask = capabilitiesMask; + mLocationCapabilitiesCached = true; + + mMutex.lock(); + auto gnssCbIface(mGnssCbIface); + mMutex.unlock(); + + if (gnssCbIface != nullptr) { + uint32_t data = 0; + if ((capabilitiesMask & LOCATION_CAPABILITIES_TIME_BASED_TRACKING_BIT) || + (capabilitiesMask & LOCATION_CAPABILITIES_TIME_BASED_BATCHING_BIT) || + (capabilitiesMask & LOCATION_CAPABILITIES_DISTANCE_BASED_TRACKING_BIT) || + (capabilitiesMask & LOCATION_CAPABILITIES_DISTANCE_BASED_BATCHING_BIT)) + data |= IGnssCallback::Capabilities::SCHEDULING; + if (capabilitiesMask & LOCATION_CAPABILITIES_GEOFENCE_BIT) + data |= IGnssCallback::Capabilities::GEOFENCING; + if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT) + data |= IGnssCallback::Capabilities::MEASUREMENTS; + if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MSB_BIT) + data |= IGnssCallback::Capabilities::MSB; + if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MSA_BIT) + data |= IGnssCallback::Capabilities::MSA; + auto r = gnssCbIface->gnssSetCapabilitesCb(data); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssSetCapabilitesCb description=%s", + __func__, r.description().c_str()); + } + } + if (gnssCbIface != nullptr) { + IGnssCallback::GnssSystemInfo gnssInfo; + if (capabilitiesMask & LOCATION_CAPABILITIES_CONSTELLATION_ENABLEMENT_BIT || + capabilitiesMask & LOCATION_CAPABILITIES_AGPM_BIT) { + gnssInfo.yearOfHw = 2018; + } else if (capabilitiesMask & LOCATION_CAPABILITIES_DEBUG_NMEA_BIT) { + gnssInfo.yearOfHw = 2017; + } else if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT) { + gnssInfo.yearOfHw = 2016; + } else { + gnssInfo.yearOfHw = 2015; + } + LOC_LOGV("%s:%d] set_system_info_cb (%d)", __FUNCTION__, __LINE__, gnssInfo.yearOfHw); + auto r = gnssCbIface->gnssSetSystemInfoCb(gnssInfo); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssSetSystemInfoCb description=%s", + __func__, r.description().c_str()); + } + } +} + +void GnssAPIClient::onTrackingCb(Location location) +{ + LOC_LOGD("%s]: (flags: %02x)", __FUNCTION__, location.flags); + mMutex.lock(); + auto gnssCbIface(mGnssCbIface); + mMutex.unlock(); + + if (gnssCbIface != nullptr) { + GnssLocation gnssLocation; + convertGnssLocation(location, gnssLocation); + auto r = gnssCbIface->gnssLocationCb(gnssLocation); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssLocationCb description=%s", + __func__, r.description().c_str()); + } + } +} + +void GnssAPIClient::onGnssNiCb(uint32_t id, GnssNiNotification gnssNiNotification) +{ + LOC_LOGD("%s]: (id: %d)", __FUNCTION__, id); + mMutex.lock(); + auto gnssNiCbIface(mGnssNiCbIface); + mMutex.unlock(); + + if (gnssNiCbIface == nullptr) { + LOC_LOGE("%s]: mGnssNiCbIface is nullptr", __FUNCTION__); + return; + } + + IGnssNiCallback::GnssNiNotification notificationGnss = {}; + + notificationGnss.notificationId = id; + + if (gnssNiNotification.type == GNSS_NI_TYPE_VOICE) + notificationGnss.niType = IGnssNiCallback::GnssNiType::VOICE; + else if (gnssNiNotification.type == GNSS_NI_TYPE_SUPL) + notificationGnss.niType = IGnssNiCallback::GnssNiType::UMTS_SUPL; + else if (gnssNiNotification.type == GNSS_NI_TYPE_CONTROL_PLANE) + notificationGnss.niType = IGnssNiCallback::GnssNiType::UMTS_CTRL_PLANE; + else if (gnssNiNotification.type == GNSS_NI_TYPE_EMERGENCY_SUPL) + notificationGnss.niType = IGnssNiCallback::GnssNiType::EMERGENCY_SUPL; + + if (gnssNiNotification.options & GNSS_NI_OPTIONS_NOTIFICATION_BIT) + notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::NEED_NOTIFY; + if (gnssNiNotification.options & GNSS_NI_OPTIONS_VERIFICATION_BIT) + notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::NEED_VERIFY; + if (gnssNiNotification.options & GNSS_NI_OPTIONS_PRIVACY_OVERRIDE_BIT) + notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::PRIVACY_OVERRIDE; + + notificationGnss.timeoutSec = gnssNiNotification.timeout; + + if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_ACCEPT) + notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_ACCEPT; + else if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_DENY) + notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_DENY; + else if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_NO_RESPONSE || + gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_IGNORE) + notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_NORESP; + + notificationGnss.requestorId = gnssNiNotification.requestor; + + notificationGnss.notificationMessage = gnssNiNotification.message; + + if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_NONE) + notificationGnss.requestorIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_NONE; + else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_GSM_DEFAULT) + notificationGnss.requestorIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_GSM_DEFAULT; + else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_UTF8) + notificationGnss.requestorIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UTF8; + else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_UCS2) + notificationGnss.requestorIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UCS2; + + if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_NONE) + notificationGnss.notificationIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_NONE; + else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_GSM_DEFAULT) + notificationGnss.notificationIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_GSM_DEFAULT; + else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_UTF8) + notificationGnss.notificationIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UTF8; + else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_UCS2) + notificationGnss.notificationIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UCS2; + + gnssNiCbIface->niNotifyCb(notificationGnss); +} + +void GnssAPIClient::onGnssSvCb(GnssSvNotification gnssSvNotification) +{ + LOC_LOGD("%s]: (count: %zu)", __FUNCTION__, gnssSvNotification.count); + mMutex.lock(); + auto gnssCbIface(mGnssCbIface); + mMutex.unlock(); + + if (gnssCbIface != nullptr) { + IGnssCallback::GnssSvStatus svStatus; + convertGnssSvStatus(gnssSvNotification, svStatus); + auto r = gnssCbIface->gnssSvStatusCb(svStatus); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssSvStatusCb description=%s", + __func__, r.description().c_str()); + } + } +} + +void GnssAPIClient::onGnssNmeaCb(GnssNmeaNotification gnssNmeaNotification) +{ + mMutex.lock(); + auto gnssCbIface(mGnssCbIface); + mMutex.unlock(); + + if (gnssCbIface != nullptr) { + const std::string s(gnssNmeaNotification.nmea); + std::stringstream ss(s); + std::string each; + while(std::getline(ss, each, '\n')) { + each += '\n'; + android::hardware::hidl_string nmeaString; + nmeaString.setToExternal(each.c_str(), each.length()); + auto r = gnssCbIface->gnssNmeaCb( + static_cast<V1_0::GnssUtcTime>(gnssNmeaNotification.timestamp), nmeaString); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssNmeaCb nmea=%s length=%zu description=%s", __func__, + gnssNmeaNotification.nmea, gnssNmeaNotification.length, + r.description().c_str()); + } + } + } +} + +void GnssAPIClient::onStartTrackingCb(LocationError error) +{ + LOC_LOGD("%s]: (%d)", __FUNCTION__, error); + mMutex.lock(); + auto gnssCbIface(mGnssCbIface); + mMutex.unlock(); + + if (error == LOCATION_ERROR_SUCCESS && gnssCbIface != nullptr) { + auto r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_ON); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssStatusCb ENGINE_ON description=%s", + __func__, r.description().c_str()); + } + r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_BEGIN); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssStatusCb SESSION_BEGIN description=%s", + __func__, r.description().c_str()); + } + } +} + +void GnssAPIClient::onStopTrackingCb(LocationError error) +{ + LOC_LOGD("%s]: (%d)", __FUNCTION__, error); + mMutex.lock(); + auto gnssCbIface(mGnssCbIface); + mMutex.unlock(); + + if (error == LOCATION_ERROR_SUCCESS && gnssCbIface != nullptr) { + auto r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_END); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssStatusCb SESSION_END description=%s", + __func__, r.description().c_str()); + } + r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_OFF); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssStatusCb ENGINE_OFF description=%s", + __func__, r.description().c_str()); + } + } +} + +static void convertGnssSvStatus(GnssSvNotification& in, IGnssCallback::GnssSvStatus& out) +{ + memset(&out, 0, sizeof(IGnssCallback::GnssSvStatus)); + out.numSvs = in.count; + if (out.numSvs > static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT)) { + LOC_LOGW("%s]: Too many satellites %u. Clamps to %d.", + __FUNCTION__, out.numSvs, V1_0::GnssMax::SVS_COUNT); + out.numSvs = static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT); + } + for (size_t i = 0; i < out.numSvs; i++) { + IGnssCallback::GnssSvInfo& info = out.gnssSvList[i]; + info.svid = in.gnssSvs[i].svId; + convertGnssConstellationType(in.gnssSvs[i].type, info.constellation); + info.cN0Dbhz = in.gnssSvs[i].cN0Dbhz; + info.elevationDegrees = in.gnssSvs[i].elevation; + info.azimuthDegrees = in.gnssSvs[i].azimuth; + info.carrierFrequencyHz = in.gnssSvs[i].carrierFrequencyHz; + info.svFlag = static_cast<uint8_t>(IGnssCallback::GnssSvFlags::NONE); + if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_EPHEMER_BIT) + info.svFlag |= IGnssCallback::GnssSvFlags::HAS_EPHEMERIS_DATA; + if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_ALMANAC_BIT) + info.svFlag |= IGnssCallback::GnssSvFlags::HAS_ALMANAC_DATA; + if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT) + info.svFlag |= IGnssCallback::GnssSvFlags::USED_IN_FIX; + if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_CARRIER_FREQUENCY_BIT) + info.svFlag |= IGnssCallback::GnssSvFlags::HAS_CARRIER_FREQUENCY; + } +} + +} // namespace implementation +} // namespace V2_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/android/2.0/location_api/GnssAPIClient.h b/android/2.0/location_api/GnssAPIClient.h new file mode 100644 index 0000000..a129cee --- /dev/null +++ b/android/2.0/location_api/GnssAPIClient.h @@ -0,0 +1,108 @@ +/* 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 GNSS_API_CLINET_H +#define GNSS_API_CLINET_H + + +#include <mutex> +#include <android/hardware/gnss/2.0/IGnss.h> +//#include <android/hardware/gnss/1.1/IGnssCallback.h> +#include <LocationAPIClientBase.h> + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +using ::android::sp; + +class GnssAPIClient : public LocationAPIClientBase +{ +public: + GnssAPIClient(const sp<V1_0::IGnssCallback>& gpsCb, + const sp<V1_0::IGnssNiCallback>& niCb); + virtual ~GnssAPIClient(); + GnssAPIClient(const GnssAPIClient&) = delete; + GnssAPIClient& operator=(const GnssAPIClient&) = delete; + + // for GpsInterface + void gnssUpdateCallbacks(const sp<V1_0::IGnssCallback>& gpsCb, + const sp<V1_0::IGnssNiCallback>& niCb); + bool gnssStart(); + bool gnssStop(); + bool gnssSetPositionMode(V1_0::IGnss::GnssPositionMode mode, + V1_0::IGnss::GnssPositionRecurrence recurrence, + uint32_t minIntervalMs, + uint32_t preferredAccuracyMeters, + uint32_t preferredTimeMs, + GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID, + uint32_t timeBetweenMeasurement = 0); + + // for GpsNiInterface + void gnssNiRespond(int32_t notifId, V1_0::IGnssNiCallback::GnssUserResponseType userResponse); + + // these apis using LocationAPIControlClient + void gnssDeleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags); + void gnssEnable(LocationTechnologyType techType); + void gnssDisable(); + void gnssConfigurationUpdate(const GnssConfig& gnssConfig); + + inline LocationCapabilitiesMask gnssGetCapabilities() const { + return mLocationCapabilitiesMask; + } + void requestCapabilities(); + + // callbacks we are interested in + void onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask) final; + void onTrackingCb(Location location) final; + void onGnssNiCb(uint32_t id, GnssNiNotification gnssNiNotification) final; + void onGnssSvCb(GnssSvNotification gnssSvNotification) final; + void onGnssNmeaCb(GnssNmeaNotification gnssNmeaNotification) final; + + void onStartTrackingCb(LocationError error) final; + void onStopTrackingCb(LocationError error) final; + +private: + sp<V1_0::IGnssCallback> mGnssCbIface; + sp<V1_0::IGnssNiCallback> mGnssNiCbIface; + std::mutex mMutex; + LocationAPIControlClient* mControlClient; + LocationCapabilitiesMask mLocationCapabilitiesMask; + bool mLocationCapabilitiesCached; + TrackingOptions mTrackingOptions; +}; + +} // namespace implementation +} // namespace V2_0 +} // namespace gnss +} // namespace hardware +} // namespace android +#endif // GNSS_API_CLINET_H diff --git a/android/2.0/location_api/LocationUtil.cpp b/android/2.0/location_api/LocationUtil.cpp new file mode 100644 index 0000000..c921154 --- /dev/null +++ b/android/2.0/location_api/LocationUtil.cpp @@ -0,0 +1,206 @@ +/* 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 <LocationUtil.h> + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +using ::android::hardware::gnss::V1_0::GnssLocation; +using ::android::hardware::gnss::V1_0::GnssConstellationType; +using ::android::hardware::gnss::V1_0::GnssLocationFlags; + +void convertGnssLocation(Location& in, GnssLocation& out) +{ + memset(&out, 0, sizeof(GnssLocation)); + if (in.flags & LOCATION_HAS_LAT_LONG_BIT) { + out.gnssLocationFlags |= GnssLocationFlags::HAS_LAT_LONG; + out.latitudeDegrees = in.latitude; + out.longitudeDegrees = in.longitude; + } + if (in.flags & LOCATION_HAS_ALTITUDE_BIT) { + out.gnssLocationFlags |= GnssLocationFlags::HAS_ALTITUDE; + out.altitudeMeters = in.altitude; + } + if (in.flags & LOCATION_HAS_SPEED_BIT) { + out.gnssLocationFlags |= GnssLocationFlags::HAS_SPEED; + out.speedMetersPerSec = in.speed; + } + if (in.flags & LOCATION_HAS_BEARING_BIT) { + out.gnssLocationFlags |= GnssLocationFlags::HAS_BEARING; + out.bearingDegrees = in.bearing; + } + if (in.flags & LOCATION_HAS_ACCURACY_BIT) { + out.gnssLocationFlags |= GnssLocationFlags::HAS_HORIZONTAL_ACCURACY; + out.horizontalAccuracyMeters = in.accuracy; + } + if (in.flags & LOCATION_HAS_VERTICAL_ACCURACY_BIT) { + out.gnssLocationFlags |= GnssLocationFlags::HAS_VERTICAL_ACCURACY; + out.verticalAccuracyMeters = in.verticalAccuracy; + } + if (in.flags & LOCATION_HAS_SPEED_ACCURACY_BIT) { + out.gnssLocationFlags |= GnssLocationFlags::HAS_SPEED_ACCURACY; + out.speedAccuracyMetersPerSecond = in.speedAccuracy; + } + if (in.flags & LOCATION_HAS_BEARING_ACCURACY_BIT) { + out.gnssLocationFlags |= GnssLocationFlags::HAS_BEARING_ACCURACY; + out.bearingAccuracyDegrees = in.bearingAccuracy; + } + + out.timestamp = static_cast<V1_0::GnssUtcTime>(in.timestamp); +} + +void convertGnssLocation(const GnssLocation& in, Location& out) +{ + memset(&out, 0, sizeof(out)); + if (in.gnssLocationFlags & GnssLocationFlags::HAS_LAT_LONG) { + out.flags |= LOCATION_HAS_LAT_LONG_BIT; + out.latitude = in.latitudeDegrees; + out.longitude = in.longitudeDegrees; + } + if (in.gnssLocationFlags & GnssLocationFlags::HAS_ALTITUDE) { + out.flags |= LOCATION_HAS_ALTITUDE_BIT; + out.altitude = in.altitudeMeters; + } + if (in.gnssLocationFlags & GnssLocationFlags::HAS_SPEED) { + out.flags |= LOCATION_HAS_SPEED_BIT; + out.speed = in.speedMetersPerSec; + } + if (in.gnssLocationFlags & GnssLocationFlags::HAS_BEARING) { + out.flags |= LOCATION_HAS_BEARING_BIT; + out.bearing = in.bearingDegrees; + } + if (in.gnssLocationFlags & GnssLocationFlags::HAS_HORIZONTAL_ACCURACY) { + out.flags |= LOCATION_HAS_ACCURACY_BIT; + out.accuracy = in.horizontalAccuracyMeters; + } + if (in.gnssLocationFlags & GnssLocationFlags::HAS_VERTICAL_ACCURACY) { + out.flags |= LOCATION_HAS_VERTICAL_ACCURACY_BIT; + out.verticalAccuracy = in.verticalAccuracyMeters; + } + if (in.gnssLocationFlags & GnssLocationFlags::HAS_SPEED_ACCURACY) { + out.flags |= LOCATION_HAS_SPEED_ACCURACY_BIT; + out.speedAccuracy = in.speedAccuracyMetersPerSecond; + } + if (in.gnssLocationFlags & GnssLocationFlags::HAS_BEARING_ACCURACY) { + out.flags |= LOCATION_HAS_BEARING_ACCURACY_BIT; + out.bearingAccuracy = in.bearingAccuracyDegrees; + } + + out.timestamp = static_cast<uint64_t>(in.timestamp); +} + +void convertGnssConstellationType(GnssSvType& in, GnssConstellationType& out) +{ + switch(in) { + case GNSS_SV_TYPE_GPS: + out = GnssConstellationType::GPS; + break; + case GNSS_SV_TYPE_SBAS: + out = GnssConstellationType::SBAS; + break; + case GNSS_SV_TYPE_GLONASS: + out = GnssConstellationType::GLONASS; + break; + case GNSS_SV_TYPE_QZSS: + out = GnssConstellationType::QZSS; + break; + case GNSS_SV_TYPE_BEIDOU: + out = GnssConstellationType::BEIDOU; + break; + case GNSS_SV_TYPE_GALILEO: + out = GnssConstellationType::GALILEO; + break; + case GNSS_SV_TYPE_UNKNOWN: + default: + out = GnssConstellationType::UNKNOWN; + break; + } +} + +void convertGnssEphemerisType(GnssEphemerisType& in, GnssDebug::SatelliteEphemerisType& out) +{ + switch(in) { + case GNSS_EPH_TYPE_EPHEMERIS: + out = GnssDebug::SatelliteEphemerisType::EPHEMERIS; + break; + case GNSS_EPH_TYPE_ALMANAC: + out = GnssDebug::SatelliteEphemerisType::ALMANAC_ONLY; + break; + case GNSS_EPH_TYPE_UNKNOWN: + default: + out = GnssDebug::SatelliteEphemerisType::NOT_AVAILABLE; + break; + } +} + +void convertGnssEphemerisSource(GnssEphemerisSource& in, GnssDebug::SatelliteEphemerisSource& out) +{ + switch(in) { + case GNSS_EPH_SOURCE_DEMODULATED: + out = GnssDebug::SatelliteEphemerisSource::DEMODULATED; + break; + case GNSS_EPH_SOURCE_SUPL_PROVIDED: + out = GnssDebug::SatelliteEphemerisSource::SUPL_PROVIDED; + break; + case GNSS_EPH_SOURCE_OTHER_SERVER_PROVIDED: + out = GnssDebug::SatelliteEphemerisSource::OTHER_SERVER_PROVIDED; + break; + case GNSS_EPH_SOURCE_LOCAL: + case GNSS_EPH_SOURCE_UNKNOWN: + default: + out = GnssDebug::SatelliteEphemerisSource::OTHER; + break; + } +} + +void convertGnssEphemerisHealth(GnssEphemerisHealth& in, GnssDebug::SatelliteEphemerisHealth& out) +{ + switch(in) { + case GNSS_EPH_HEALTH_GOOD: + out = GnssDebug::SatelliteEphemerisHealth::GOOD; + break; + case GNSS_EPH_HEALTH_BAD: + out = GnssDebug::SatelliteEphemerisHealth::BAD; + break; + case GNSS_EPH_HEALTH_UNKNOWN: + default: + out = GnssDebug::SatelliteEphemerisHealth::UNKNOWN; + break; + } +} + +} // namespace implementation +} // namespace V2_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/android/2.0/location_api/LocationUtil.h b/android/2.0/location_api/LocationUtil.h new file mode 100644 index 0000000..c6f5ead --- /dev/null +++ b/android/2.0/location_api/LocationUtil.h @@ -0,0 +1,55 @@ +/* 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 LOCATION_UTIL_H +#define LOCATION_UTIL_H + +#include <android/hardware/gnss/1.0/types.h> +#include <LocationAPI.h> +#include <GnssDebug.h> + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +void convertGnssLocation(Location& in, V1_0::GnssLocation& out); +void convertGnssLocation(const V1_0::GnssLocation& in, Location& out); +void convertGnssConstellationType(GnssSvType& in, V1_0::GnssConstellationType& out); +void convertGnssEphemerisType(GnssEphemerisType& in, GnssDebug::SatelliteEphemerisType& out); +void convertGnssEphemerisSource(GnssEphemerisSource& in, GnssDebug::SatelliteEphemerisSource& out); +void convertGnssEphemerisHealth(GnssEphemerisHealth& in, GnssDebug::SatelliteEphemerisHealth& out); + +} // namespace implementation +} // namespace V2_0 +} // namespace gnss +} // namespace hardware +} // namespace android +#endif // LOCATION_UTIL_H diff --git a/android/2.0/location_api/MeasurementAPIClient.cpp b/android/2.0/location_api/MeasurementAPIClient.cpp new file mode 100644 index 0000000..d9cae18 --- /dev/null +++ b/android/2.0/location_api/MeasurementAPIClient.cpp @@ -0,0 +1,424 @@ +/* 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_MeasurementAPIClient" + +#include <log_util.h> +#include <loc_cfg.h> + +#include "LocationUtil.h" +#include "MeasurementAPIClient.h" + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +using ::android::hardware::gnss::V1_0::IGnssMeasurement; +using ::android::hardware::gnss::V2_0::IGnssMeasurementCallback; + +static void convertGnssData(GnssMeasurementsNotification& in, + V1_0::IGnssMeasurementCallback::GnssData& out); +static void convertGnssData_1_1(GnssMeasurementsNotification& in, + V1_1::IGnssMeasurementCallback::GnssData& out); +static void convertGnssData_2_0(GnssMeasurementsNotification& in, + V2_0::IGnssMeasurementCallback::GnssData& out); +static void convertGnssMeasurement(GnssMeasurementsData& in, + V1_0::IGnssMeasurementCallback::GnssMeasurement& out); +static void convertGnssClock(GnssMeasurementsClock& in, IGnssMeasurementCallback::GnssClock& out); + +MeasurementAPIClient::MeasurementAPIClient() : + mGnssMeasurementCbIface(nullptr), + mGnssMeasurementCbIface_1_1(nullptr), + mGnssMeasurementCbIface_2_0(nullptr), + mTracking(false) +{ + LOC_LOGD("%s]: ()", __FUNCTION__); +} + +MeasurementAPIClient::~MeasurementAPIClient() +{ + LOC_LOGD("%s]: ()", __FUNCTION__); +} + +// for GpsInterface +Return<IGnssMeasurement::GnssMeasurementStatus> +MeasurementAPIClient::measurementSetCallback(const sp<V1_0::IGnssMeasurementCallback>& callback) +{ + LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback); + + mMutex.lock(); + mGnssMeasurementCbIface = callback; + mMutex.unlock(); + + return startTracking(); +} + +Return<IGnssMeasurement::GnssMeasurementStatus> +MeasurementAPIClient::measurementSetCallback_1_1( + const sp<V1_1::IGnssMeasurementCallback>& callback, + GnssPowerMode powerMode, uint32_t timeBetweenMeasurement) +{ + LOC_LOGD("%s]: (%p) (powermode: %d) (tbm: %d)", + __FUNCTION__, &callback, (int)powerMode, timeBetweenMeasurement); + + mMutex.lock(); + mGnssMeasurementCbIface_1_1 = callback; + mMutex.unlock(); + + return startTracking(powerMode, timeBetweenMeasurement); +} + +Return<IGnssMeasurement::GnssMeasurementStatus> +MeasurementAPIClient::measurementSetCallback_2_0( + const sp<V2_0::IGnssMeasurementCallback>& callback, + GnssPowerMode powerMode, uint32_t timeBetweenMeasurement) +{ + LOC_LOGD("%s]: (%p) (powermode: %d) (tbm: %d)", + __FUNCTION__, &callback, (int)powerMode, timeBetweenMeasurement); + + mMutex.lock(); + mGnssMeasurementCbIface_2_0 = callback; + mMutex.unlock(); + + return startTracking(powerMode, timeBetweenMeasurement); +} + +Return<IGnssMeasurement::GnssMeasurementStatus> +MeasurementAPIClient::startTracking( + GnssPowerMode powerMode, uint32_t timeBetweenMeasurement) +{ + LocationCallbacks locationCallbacks; + memset(&locationCallbacks, 0, sizeof(LocationCallbacks)); + locationCallbacks.size = sizeof(LocationCallbacks); + + locationCallbacks.trackingCb = nullptr; + locationCallbacks.batchingCb = nullptr; + locationCallbacks.geofenceBreachCb = nullptr; + locationCallbacks.geofenceStatusCb = nullptr; + locationCallbacks.gnssLocationInfoCb = nullptr; + locationCallbacks.gnssNiCb = nullptr; + locationCallbacks.gnssSvCb = nullptr; + locationCallbacks.gnssNmeaCb = nullptr; + + locationCallbacks.gnssMeasurementsCb = nullptr; + if (mGnssMeasurementCbIface_2_0 != nullptr || + mGnssMeasurementCbIface_1_1 != nullptr || + mGnssMeasurementCbIface != nullptr) { + locationCallbacks.gnssMeasurementsCb = + [this](GnssMeasurementsNotification gnssMeasurementsNotification) { + onGnssMeasurementsCb(gnssMeasurementsNotification); + }; + } + + locAPISetCallbacks(locationCallbacks); + + TrackingOptions options = {}; + memset(&options, 0, sizeof(TrackingOptions)); + options.size = sizeof(TrackingOptions); + options.minInterval = 1000; + options.mode = GNSS_SUPL_MODE_STANDALONE; + if (GNSS_POWER_MODE_INVALID != powerMode) { + options.powerMode = powerMode; + options.tbm = timeBetweenMeasurement; + } + + mTracking = true; + LOC_LOGD("%s]: start tracking session", __FUNCTION__); + locAPIStartTracking(options); + return IGnssMeasurement::GnssMeasurementStatus::SUCCESS; +} + +// for GpsMeasurementInterface +void MeasurementAPIClient::measurementClose() { + LOC_LOGD("%s]: ()", __FUNCTION__); + mTracking = false; + locAPIStopTracking(); +} + +// callbacks +void MeasurementAPIClient::onGnssMeasurementsCb( + GnssMeasurementsNotification gnssMeasurementsNotification) +{ + LOC_LOGD("%s]: (count: %zu active: %d)", + __FUNCTION__, gnssMeasurementsNotification.count, mTracking); + if (mTracking) { + mMutex.lock(); + sp<V1_0::IGnssMeasurementCallback> gnssMeasurementCbIface = nullptr; + sp<V1_1::IGnssMeasurementCallback> gnssMeasurementCbIface_1_1 = nullptr; + sp<V2_0::IGnssMeasurementCallback> gnssMeasurementCbIface_2_0 = nullptr; + if (mGnssMeasurementCbIface_2_0 != nullptr) { + gnssMeasurementCbIface_2_0 = mGnssMeasurementCbIface_2_0; + } else if (mGnssMeasurementCbIface_1_1 != nullptr) { + gnssMeasurementCbIface_1_1 = mGnssMeasurementCbIface_1_1; + } else if (mGnssMeasurementCbIface != nullptr) { + gnssMeasurementCbIface = mGnssMeasurementCbIface; + } + mMutex.unlock(); + + if (gnssMeasurementCbIface_2_0 != nullptr) { + V2_0::IGnssMeasurementCallback::GnssData gnssData; + convertGnssData_2_0(gnssMeasurementsNotification, gnssData); + auto r = gnssMeasurementCbIface_2_0->gnssMeasurementCb_2_0(gnssData); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssMeasurementCb description=%s", + __func__, r.description().c_str()); + } + } else if (gnssMeasurementCbIface_1_1 != nullptr) { + V1_1::IGnssMeasurementCallback::GnssData gnssData; + convertGnssData_1_1(gnssMeasurementsNotification, gnssData); + auto r = gnssMeasurementCbIface_1_1->gnssMeasurementCb(gnssData); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssMeasurementCb description=%s", + __func__, r.description().c_str()); + } + } else if (gnssMeasurementCbIface != nullptr) { + V1_0::IGnssMeasurementCallback::GnssData gnssData; + convertGnssData(gnssMeasurementsNotification, gnssData); + auto r = gnssMeasurementCbIface->GnssMeasurementCb(gnssData); + if (!r.isOk()) { + LOC_LOGE("%s] Error from GnssMeasurementCb description=%s", + __func__, r.description().c_str()); + } + } + } +} + +static void convertGnssMeasurement(GnssMeasurementsData& in, + V1_0::IGnssMeasurementCallback::GnssMeasurement& out) +{ + memset(&out, 0, sizeof(IGnssMeasurementCallback::GnssMeasurement)); + if (in.flags & GNSS_MEASUREMENTS_DATA_SIGNAL_TO_NOISE_RATIO_BIT) + out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_SNR; + if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_FREQUENCY_BIT) + out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_FREQUENCY; + if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_CYCLES_BIT) + out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_CYCLES; + if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_BIT) + out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_PHASE; + if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_UNCERTAINTY_BIT) + out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_PHASE_UNCERTAINTY; + if (in.flags & GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT) + out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_AUTOMATIC_GAIN_CONTROL; + out.svid = in.svId; + convertGnssConstellationType(in.svType, out.constellation); + out.timeOffsetNs = in.timeOffsetNs; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_CODE_LOCK_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_CODE_LOCK; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_BIT_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BIT_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_SUBFRAME_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SUBFRAME_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_TOW_DECODED_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_DECODED; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_MSEC_AMBIGUOUS_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_MSEC_AMBIGUOUS; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_SYMBOL_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SYMBOL_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_GLO_STRING_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_STRING_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_GLO_TOD_DECODED_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_DECODED; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_BIT_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_BIT_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_SUBFRAME_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_SUBFRAME_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1BC_CODE_LOCK_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1BC_CODE_LOCK; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1C_2ND_CODE_LOCK_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1C_2ND_CODE_LOCK; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1B_PAGE_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1B_PAGE_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_SBAS_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SBAS_SYNC; + out.receivedSvTimeInNs = in.receivedSvTimeNs; + out.receivedSvTimeUncertaintyInNs = in.receivedSvTimeUncertaintyNs; + out.cN0DbHz = in.carrierToNoiseDbHz; + out.pseudorangeRateMps = in.pseudorangeRateMps; + out.pseudorangeRateUncertaintyMps = in.pseudorangeRateUncertaintyMps; + if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_VALID_BIT) + out.accumulatedDeltaRangeState |= + IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_VALID; + if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_RESET_BIT) + out.accumulatedDeltaRangeState |= + IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_RESET; + if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_CYCLE_SLIP_BIT) + out.accumulatedDeltaRangeState |= + IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_CYCLE_SLIP; + out.accumulatedDeltaRangeM = in.adrMeters; + out.accumulatedDeltaRangeUncertaintyM = in.adrUncertaintyMeters; + out.carrierFrequencyHz = in.carrierFrequencyHz; + out.carrierCycles = in.carrierCycles; + out.carrierPhase = in.carrierPhase; + out.carrierPhaseUncertainty = in.carrierPhaseUncertainty; + uint8_t indicator = + static_cast<uint8_t>(IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_UNKNOWN); + if (in.multipathIndicator & GNSS_MEASUREMENTS_MULTIPATH_INDICATOR_PRESENT) + indicator |= IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_PRESENT; + if (in.multipathIndicator & GNSS_MEASUREMENTS_MULTIPATH_INDICATOR_NOT_PRESENT) + indicator |= IGnssMeasurementCallback::GnssMultipathIndicator::INDICATIOR_NOT_PRESENT; + out.multipathIndicator = + static_cast<IGnssMeasurementCallback::GnssMultipathIndicator>(indicator); + out.snrDb = in.signalToNoiseRatioDb; + out.agcLevelDb = in.agcLevelDb; +} + +static void convertGnssClock(GnssMeasurementsClock& in, IGnssMeasurementCallback::GnssClock& out) +{ + memset(&out, 0, sizeof(IGnssMeasurementCallback::GnssClock)); + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_LEAP_SECOND_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_LEAP_SECOND; + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_TIME_UNCERTAINTY_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_TIME_UNCERTAINTY; + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_FULL_BIAS_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_FULL_BIAS; + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_BIAS; + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_UNCERTAINTY_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_BIAS_UNCERTAINTY; + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_DRIFT; + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_UNCERTAINTY_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_DRIFT_UNCERTAINTY; + out.leapSecond = in.leapSecond; + out.timeNs = in.timeNs; + out.timeUncertaintyNs = in.timeUncertaintyNs; + out.fullBiasNs = in.fullBiasNs; + out.biasNs = in.biasNs; + out.biasUncertaintyNs = in.biasUncertaintyNs; + out.driftNsps = in.driftNsps; + out.driftUncertaintyNsps = in.driftUncertaintyNsps; + out.hwClockDiscontinuityCount = in.hwClockDiscontinuityCount; +} + +static void convertGnssData(GnssMeasurementsNotification& in, + V1_0::IGnssMeasurementCallback::GnssData& out) +{ + out.measurementCount = in.count; + if (out.measurementCount > static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT)) { + LOC_LOGW("%s]: Too many measurement %u. Clamps to %d.", + __FUNCTION__, out.measurementCount, V1_0::GnssMax::SVS_COUNT); + out.measurementCount = static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT); + } + for (size_t i = 0; i < out.measurementCount; i++) { + convertGnssMeasurement(in.measurements[i], out.measurements[i]); + } + convertGnssClock(in.clock, out.clock); +} + +static void convertGnssData_1_1(GnssMeasurementsNotification& in, + V1_1::IGnssMeasurementCallback::GnssData& out) +{ + out.measurements.resize(in.count); + for (size_t i = 0; i < in.count; i++) { + convertGnssMeasurement(in.measurements[i], out.measurements[i].v1_0); + if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_VALID_BIT) + out.measurements[i].accumulatedDeltaRangeState |= + IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_VALID; + if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_RESET_BIT) + out.measurements[i].accumulatedDeltaRangeState |= + IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_RESET; + if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_CYCLE_SLIP_BIT) + out.measurements[i].accumulatedDeltaRangeState |= + IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_CYCLE_SLIP; + if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_HALF_CYCLE_RESOLVED_BIT) + out.measurements[i].accumulatedDeltaRangeState |= + IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_HALF_CYCLE_RESOLVED; + } + convertGnssClock(in.clock, out.clock); +} + +static void convertGnssData_2_0(GnssMeasurementsNotification& in, + V2_0::IGnssMeasurementCallback::GnssData& out) +{ + out.measurements.resize(in.count); + for (size_t i = 0; i < in.count; i++) { + convertGnssMeasurement(in.measurements[i], out.measurements[i].v1_1.v1_0); + if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_VALID_BIT) + out.measurements[i].v1_1.accumulatedDeltaRangeState |= + IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_VALID; + if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_RESET_BIT) + out.measurements[i].v1_1.accumulatedDeltaRangeState |= + IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_RESET; + if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_CYCLE_SLIP_BIT) + out.measurements[i].v1_1.accumulatedDeltaRangeState |= + IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_CYCLE_SLIP; + if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_HALF_CYCLE_RESOLVED_BIT) + out.measurements[i].v1_1.accumulatedDeltaRangeState |= + IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_HALF_CYCLE_RESOLVED; + +// out.measurements[i].codeType = +// static_cast<IGnssMeasurementCallback::GnssMeasurementCodeType>(in.measurements[i].codeType); +// out.measurements[i].otherCodeTypeName = in.measurements[i].otherCodeTypeName; + + if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_CODE_LOCK_BIT) + out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_CODE_LOCK; + if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_BIT_SYNC_BIT) + out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BIT_SYNC; + if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_SUBFRAME_SYNC_BIT) + out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SUBFRAME_SYNC; + if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_TOW_DECODED_BIT) + out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_DECODED; + if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_MSEC_AMBIGUOUS_BIT) + out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_MSEC_AMBIGUOUS; + if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_SYMBOL_SYNC_BIT) + out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SYMBOL_SYNC; + if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_GLO_STRING_SYNC_BIT) + out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_STRING_SYNC; + if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_GLO_TOD_DECODED_BIT) + out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_DECODED; + if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_BIT_SYNC_BIT) + out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_BIT_SYNC; + if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_SUBFRAME_SYNC_BIT) + out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_SUBFRAME_SYNC; + if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1BC_CODE_LOCK_BIT) + out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1BC_CODE_LOCK; + if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1C_2ND_CODE_LOCK_BIT) + out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1C_2ND_CODE_LOCK; + if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1B_PAGE_SYNC_BIT) + out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1B_PAGE_SYNC; + if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_SBAS_SYNC_BIT) + out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SBAS_SYNC; + if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_TOW_KNOWN_BIT) + out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_KNOWN; + if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_GLO_TOD_KNOWN_BIT) + out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_KNOWN; + if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_2ND_CODE_LOCK_BIT) + out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_2ND_CODE_LOCK; + } + convertGnssClock(in.clock, out.clock); +} + +} // namespace implementation +} // namespace V2_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/android/2.0/location_api/MeasurementAPIClient.h b/android/2.0/location_api/MeasurementAPIClient.h new file mode 100644 index 0000000..4146a13 --- /dev/null +++ b/android/2.0/location_api/MeasurementAPIClient.h @@ -0,0 +1,89 @@ +/* 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 MEASUREMENT_API_CLINET_H +#define MEASUREMENT_API_CLINET_H + +#include <mutex> +#include <android/hardware/gnss/2.0/IGnssMeasurement.h> +//#include <android/hardware/gnss/1.1/IGnssMeasurementCallback.h> +#include <LocationAPIClientBase.h> +#include <hidl/Status.h> +#include <gps_extended_c.h> + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +using ::android::sp; + +class MeasurementAPIClient : public LocationAPIClientBase +{ +public: + MeasurementAPIClient(); + virtual ~MeasurementAPIClient(); + MeasurementAPIClient(const MeasurementAPIClient&) = delete; + MeasurementAPIClient& operator=(const MeasurementAPIClient&) = delete; + + // for GpsMeasurementInterface + Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> measurementSetCallback( + const sp<V1_0::IGnssMeasurementCallback>& callback); + Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> measurementSetCallback_1_1( + const sp<V1_1::IGnssMeasurementCallback>& callback, + GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID, + uint32_t timeBetweenMeasurement = GPS_DEFAULT_FIX_INTERVAL_MS); + Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> measurementSetCallback_2_0( + const sp<V2_0::IGnssMeasurementCallback>& callback, + GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID, + uint32_t timeBetweenMeasurement = GPS_DEFAULT_FIX_INTERVAL_MS); + void measurementClose(); + Return<IGnssMeasurement::GnssMeasurementStatus> startTracking( + GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID, + uint32_t timeBetweenMeasurement = GPS_DEFAULT_FIX_INTERVAL_MS); + + // callbacks we are interested in + void onGnssMeasurementsCb(GnssMeasurementsNotification gnssMeasurementsNotification) final; + +private: + std::mutex mMutex; + sp<V1_0::IGnssMeasurementCallback> mGnssMeasurementCbIface; + sp<V1_1::IGnssMeasurementCallback> mGnssMeasurementCbIface_1_1; + sp<V2_0::IGnssMeasurementCallback> mGnssMeasurementCbIface_2_0; + + bool mTracking; +}; + +} // namespace implementation +} // namespace V2_0 +} // namespace gnss +} // namespace hardware +} // namespace android +#endif // MEASUREMENT_API_CLINET_H diff --git a/android/2.0/service.cpp b/android/2.0/service.cpp new file mode 100644 index 0000000..16f0b06 --- /dev/null +++ b/android/2.0/service.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Not a Contribution + */ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "android.hardware.gnss@2.0-service-qti" + +#include <android/hardware/gnss/2.0/IGnss.h> +#include <hidl/LegacySupport.h> +#include "loc_cfg.h" +#include "loc_misc_utils.h" + +extern "C" { +#include "vndfwk-detect.h" +} + +#ifdef ARCH_ARM_32 +#define DEFAULT_HW_BINDER_MEM_SIZE 65536 +#endif + +using android::hardware::gnss::V2_0::IGnss; + +using android::hardware::configureRpcThreadpool; +using android::hardware::registerPassthroughServiceImplementation; +using android::hardware::joinRpcThreadpool; + +using android::status_t; +using android::OK; + +typedef int vendorEnhancedServiceMain(int /* argc */, char* /* argv */ []); + +int main() { + + ALOGI("%s", __FUNCTION__); + + bool vendorEnhanced = isRunningWithVendorEnhancedFramework(); + setVendorEnhanced(vendorEnhanced); + +#ifdef ARCH_ARM_32 + android::hardware::ProcessState::initWithMmapSize((size_t)(DEFAULT_HW_BINDER_MEM_SIZE)); +#endif + configureRpcThreadpool(1, true); + status_t status; + + status = registerPassthroughServiceImplementation<IGnss>(); + if (status == OK) { + if (vendorEnhanced) { + #ifdef LOC_HIDL_VERSION + #define VENDOR_ENHANCED_LIB "vendor.qti.gnss@" LOC_HIDL_VERSION "-service.so" + + void* libHandle = NULL; + vendorEnhancedServiceMain* vendorEnhancedMainMethod = (vendorEnhancedServiceMain*) + dlGetSymFromLib(libHandle, VENDOR_ENHANCED_LIB, "main"); + if (NULL != vendorEnhancedMainMethod) { + (*vendorEnhancedMainMethod)(0, NULL); + } + #else + ALOGE("LOC_HIDL_VERSION not defined."); + #endif + } + + joinRpcThreadpool(); + + } else { + ALOGE("Error while registering IGnss 2.0 service: %d", status); + } + + return 0; +} diff --git a/android/Android.mk b/android/Android.mk index bff117e..f117def 100644 --- a/android/Android.mk +++ b/android/Android.mk @@ -1,10 +1,14 @@ LOCAL_PATH := $(call my-dir) ifneq ($(BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE),) +ifeq ($(GNSS_HIDL_VERSION),2.0) +include $(LOCAL_PATH)/2.0/Android.mk +else ifeq ($(GNSS_HIDL_VERSION),1.1) include $(LOCAL_PATH)/1.1/Android.mk else include $(LOCAL_PATH)/1.0/Android.mk -endif +endif #GNSS HIDL 1.1 +endif #GNSS HIDL 2.0 else #QMAA flag set, build dummy android.hardware.gnss@1.0-impl-qti include $(LOCAL_PATH)/dummy/Android.mk endif #BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE diff --git a/android/dummy/Android.mk b/android/dummy/Android.mk index d438888..05114e1 100644 --- a/android/dummy/Android.mk +++ b/android/dummy/Android.mk @@ -1,9 +1,9 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) -#build dummy android.hardware.gnss@1.0-impl-qti +#build dummy android.hardware.gnss@2.0-impl-qti include $(CLEAR_VARS) -LOCAL_MODULE := android.hardware.gnss@1.0-impl-qti +LOCAL_MODULE := android.hardware.gnss@2.0-impl-qti LOCAL_VENDOR_MODULE := true LOCAL_MODULE_RELATIVE_PATH := hw LOCAL_SRC_FILES := GnssDummy.cpp @@ -20,19 +20,11 @@ LOCAL_SHARED_LIBRARIES := \ LOCAL_CFLAGS += $(GNSS_CFLAGS) include $(BUILD_SHARED_LIBRARY) -BUILD_GNSS_HIDL_SERVICE := true -ifneq ($(BOARD_VENDOR_QCOM_LOC_PDK_FEATURE_SET), true) -ifneq ($(LW_FEATURE_SET),true) -#BUILD_GNSS_HIDL_SERVICE := false -endif # LW_FEATURE_SET -endif # BOARD_VENDOR_QCOM_LOC_PDK_FEATURE_SET - -ifeq ($(BUILD_GNSS_HIDL_SERVICE), true) include $(CLEAR_VARS) -LOCAL_MODULE := android.hardware.gnss@1.0-service-qti +LOCAL_MODULE := android.hardware.gnss@2.0-service-qti LOCAL_VENDOR_MODULE := true LOCAL_MODULE_RELATIVE_PATH := hw -LOCAL_INIT_RC := android.hardware.gnss@1.0-service-qti.rc +LOCAL_INIT_RC := android.hardware.gnss@2.0-service-qti.rc LOCAL_SRC_FILES := \ serviceDummy.cpp \ @@ -60,4 +52,3 @@ LOCAL_SHARED_LIBRARIES += \ LOCAL_CFLAGS += $(GNSS_CFLAGS) include $(BUILD_EXECUTABLE) -endif # BUILD_GNSS_HIDL_SERVICE diff --git a/android/dummy/android.hardware.gnss@2.0-service-qti.rc b/android/dummy/android.hardware.gnss@2.0-service-qti.rc new file mode 100644 index 0000000..36ee47c --- /dev/null +++ b/android/dummy/android.hardware.gnss@2.0-service-qti.rc @@ -0,0 +1,4 @@ +service gnss_service /vendor/bin/hw/android.hardware.gnss@2.0-service-qti + class hal + user gps + group system gps radio diff --git a/android/measurement_corrections/1.0/MeasurementCorrections.cpp b/android/measurement_corrections/1.0/MeasurementCorrections.cpp new file mode 100644 index 0000000..c1a335a --- /dev/null +++ b/android/measurement_corrections/1.0/MeasurementCorrections.cpp @@ -0,0 +1,70 @@ +/* + * Copyright (c) 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_MeasurementCorrectionsInterface" + +#include <log_util.h> +#include "MeasurementCorrections.h" + +namespace android { +namespace hardware { +namespace gnss { +namespace measurement_corrections { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::hidl_array; +using ::android::hardware::hidl_memory; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::sp; +using ::android::hardware::gnss::V1_0::GnssLocation; + +MeasurementCorrections::MeasurementCorrections() { +} + +MeasurementCorrections::~MeasurementCorrections() { +} + +Return<bool> MeasurementCorrections::setCorrections(const ::android::hardware::gnss::measurement_corrections::V1_0::MeasurementCorrections& corrections) { + return true; +} + +Return<bool> MeasurementCorrections::setCallback(const sp<IMeasurementCorrectionsCallback>& callback) { + return true; +} + +} // namespace implementation +} // namespace V1_0 +} // namespace measurement_corrections +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/android/measurement_corrections/1.0/MeasurementCorrections.h b/android/measurement_corrections/1.0/MeasurementCorrections.h new file mode 100644 index 0000000..ad534dc --- /dev/null +++ b/android/measurement_corrections/1.0/MeasurementCorrections.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 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 ANDROID_HARDWARE_GNSS_V1_0_MeasurementCorrections_H +#define ANDROID_HARDWARE_GNSS_V1_0_MeasurementCorrections_H + +#include <android/hardware/gnss/measurement_corrections/1.0/IMeasurementCorrections.h> +#include <android/hardware/gnss/measurement_corrections/1.0/IMeasurementCorrectionsCallback.h> +#include <hidl/MQDescriptor.h> +#include <hidl/Status.h> + +#include <location_interface.h> + +namespace android { +namespace hardware { +namespace gnss { +namespace measurement_corrections { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::hidl_array; +using ::android::hardware::hidl_memory; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::sp; +using ::android::hardware::gnss::V1_0::GnssLocation; +using ::android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrectionsCallback; + +struct MeasurementCorrections : public IMeasurementCorrections { + MeasurementCorrections(); + ~MeasurementCorrections(); + +// Methods from ::android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections follow. +Return<bool> setCorrections(const ::android::hardware::gnss::measurement_corrections::V1_0::MeasurementCorrections& corrections) override; + +Return<bool> setCallback(const sp<IMeasurementCorrectionsCallback>& callback) override; + +}; + + +} // namespace implementation +} // namespace V1_0 +} // namespace measurement_corrections +} // namespace gnss +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GNSS_V1_0_MeasurementCorrections_H diff --git a/android/visibility_control/1.0/GnssVisibilityControl.cpp b/android/visibility_control/1.0/GnssVisibilityControl.cpp new file mode 100644 index 0000000..82e465c --- /dev/null +++ b/android/visibility_control/1.0/GnssVisibilityControl.cpp @@ -0,0 +1,145 @@ +/* + * Copyright (c) 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 <android/hardware/gnss/visibility_control/1.0/IGnssVisibilityControl.h> +#include <hidl/MQDescriptor.h> +#include <hidl/Status.h> +#include "GnssVisibilityControl.h" +#include <location_interface.h> + +namespace android { +namespace hardware { +namespace gnss { +namespace visibility_control { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::hidl_array; +using ::android::hardware::hidl_memory; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::sp; + +static GnssVisibilityControl* spGnssVisibilityControl = nullptr; + +static void convertGnssNfwNotification(GnssNfwNotification& in, + IGnssVisibilityControlCallback::NfwNotification& out); + +GnssVisibilityControl::GnssVisibilityControl(Gnss* gnss) : mGnss(gnss) { + spGnssVisibilityControl = this; +} +GnssVisibilityControl::~GnssVisibilityControl() { + spGnssVisibilityControl = nullptr; +} + +void GnssVisibilityControl::nfwStatusCb(GnssNfwNotification notification) { + if (nullptr != spGnssVisibilityControl) { + spGnssVisibilityControl->statusCb(notification); + } +} + +static void convertGnssNfwNotification(GnssNfwNotification& in, + IGnssVisibilityControlCallback::NfwNotification& out) +{ + memset(&out, 0, sizeof(IGnssVisibilityControlCallback::NfwNotification)); + out.proxyAppPackageName = in.proxyAppPackageName; + out.protocolStack = (IGnssVisibilityControlCallback::NfwProtocolStack)in.protocolStack; + out.otherProtocolStackName = in.otherProtocolStackName; + out.requestor = (IGnssVisibilityControlCallback::NfwRequestor)in.requestor; + out.requestorId = in.requestorId; + out.responseType = (IGnssVisibilityControlCallback::NfwResponseType)in.responseType; + out.inEmergencyMode = in.inEmergencyMode; + out.isCachedLocation = in.isCachedLocation; +} + +void GnssVisibilityControl::statusCb(GnssNfwNotification notification) { + + if (mGnssVisibilityControlCbIface != nullptr) { + IGnssVisibilityControlCallback::NfwNotification nfwNotification; + + // Convert from one structure to another + convertGnssNfwNotification(notification, nfwNotification); + + auto r = mGnssVisibilityControlCbIface->nfwNotifyCb(nfwNotification); + if (!r.isOk()) { + LOC_LOGw("Error invoking NFW status cb %s", r.description().c_str()); + } + } else { + LOC_LOGw("setCallback has not been called yet"); + } +} + +// Methods from ::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl follow. +Return<bool> GnssVisibilityControl::enableNfwLocationAccess(const hidl_vec<::android::hardware::hidl_string>& proxyApps) { + + if (nullptr == mGnss || nullptr == mGnss->getGnssInterface()) { + LOC_LOGe("Null GNSS interface"); + return false; + } + + /* If the vector is empty we need to disable all NFW clients + If there is at least one app in the vector we need to enable + all NFW clients */ + if (0 == proxyApps.size()) { + mGnss->getGnssInterface()->enableNfwLocationAccess(false); + } else { + mGnss->getGnssInterface()->enableNfwLocationAccess(true); + } + + return true; +} +/** + * Registers the callback for HAL implementation to use. + * + * @param callback Handle to IGnssVisibilityControlCallback interface. + */ +Return<bool> GnssVisibilityControl::setCallback(const ::android::sp<::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControlCallback>& callback) { + + if (nullptr == mGnss || nullptr == mGnss->getGnssInterface()) { + LOC_LOGe("Null GNSS interface"); + return false; + } + mGnssVisibilityControlCbIface = callback; + + NfwCbInfo cbInfo = {}; + cbInfo.visibilityControlCb = (void*)nfwStatusCb; + + mGnss->getGnssInterface()->nfwInit(cbInfo); + + return true; +} + +} // namespace implementation +} // namespace V1_0 +} // namespace visibility_control +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/android/visibility_control/1.0/GnssVisibilityControl.h b/android/visibility_control/1.0/GnssVisibilityControl.h new file mode 100644 index 0000000..4eaea51 --- /dev/null +++ b/android/visibility_control/1.0/GnssVisibilityControl.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 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 ANDROID_HARDWARE_GNSS_V1_0_GnssVisibilityControl_H +#define ANDROID_HARDWARE_GNSS_V1_0_GnssVisibilityControl_H + +#include <android/hardware/gnss/visibility_control/1.0/IGnssVisibilityControl.h> +#include <hidl/MQDescriptor.h> +#include <hidl/Status.h> + +#include <gps_extended_c.h> +#include <location_interface.h> +#include "Gnss.h" + +namespace android { +namespace hardware { +namespace gnss { +namespace visibility_control { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::hidl_array; +using ::android::hardware::hidl_memory; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::sp; +using ::android::hardware::gnss::V2_0::implementation::Gnss; + +struct GnssVisibilityControl : public IGnssVisibilityControl { + GnssVisibilityControl(Gnss* gnss); + ~GnssVisibilityControl(); + + // Methods from ::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl follow. + Return<bool> enableNfwLocationAccess(const hidl_vec<::android::hardware::hidl_string>& proxyApps) override; + /** + * Registers the callback for HAL implementation to use. + * + * @param callback Handle to IGnssVisibilityControlCallback interface. + */ + Return<bool> setCallback(const ::android::sp<::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControlCallback>& callback) override; + + void statusCb(GnssNfwNotification notification); + + /* Data call setup callback passed down to GNSS HAL implementation */ + static void nfwStatusCb(GnssNfwNotification notification); + +private: + Gnss* mGnss = nullptr; + sp<IGnssVisibilityControlCallback> mGnssVisibilityControlCbIface = nullptr; +}; + + +} // namespace implementation +} // namespace V1_0 +} // namespace visibility_control +} // namespace gnss +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GNSS_V1_0_GnssVisibilityControl_H diff --git a/batching/Android.mk b/batching/Android.mk new file mode 100644 index 0000000..b08d155 --- /dev/null +++ b/batching/Android.mk @@ -0,0 +1,37 @@ +ifneq ($(BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE),) +ifneq ($(BUILD_TINY_ANDROID),true) + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := libbatching +LOCAL_VENDOR_MODULE := true +LOCAL_MODULE_TAGS := optional + +LOCAL_SHARED_LIBRARIES := \ + libutils \ + libcutils \ + liblog \ + libloc_core \ + libgps.utils \ + libdl \ + liblbs_core + +LOCAL_SRC_FILES += \ + location_batching.cpp \ + BatchingAdapter.cpp + +LOCAL_HEADER_LIBRARIES := \ + libgps.utils_headers \ + libloc_core_headers \ + libloc_pla_headers \ + liblocation_api_headers + +LOCAL_PRELINK_MODULE := false + +LOCAL_CFLAGS += $(GNSS_CFLAGS) +include $(BUILD_SHARED_LIBRARY) + +endif # not BUILD_TINY_ANDROID +endif # BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE diff --git a/batching/BatchingAdapter.cpp b/batching/BatchingAdapter.cpp new file mode 100644 index 0000000..135f0ed --- /dev/null +++ b/batching/BatchingAdapter.cpp @@ -0,0 +1,1050 @@ +/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#define LOG_NDEBUG 0 +#define LOG_TAG "LocSvc_BatchingAdapter" + +#include <loc_pla.h> +#include <log_util.h> +#include <LocContext.h> +#include <BatchingAdapter.h> + +using namespace loc_core; + +BatchingAdapter::BatchingAdapter() : + LocAdapterBase(0, + LocContext::getLocContext( + NULL, + NULL, + LocContext::mLocationHalName, + false)), + mOngoingTripDistance(0), + mOngoingTripTBFInterval(0), + mTripWithOngoingTBFDropped(false), + mTripWithOngoingTripDistanceDropped(false), + mBatchingTimeout(0), + mBatchingAccuracy(1), + mBatchSize(0), + mTripBatchSize(0) +{ + LOC_LOGD("%s]: Constructor", __func__); + readConfigCommand(); + setConfigCommand(); +} + +void +BatchingAdapter::readConfigCommand() +{ + LOC_LOGD("%s]: ", __func__); + + struct MsgReadConfig : public LocMsg { + BatchingAdapter& mAdapter; + inline MsgReadConfig(BatchingAdapter& adapter) : + LocMsg(), + mAdapter(adapter) {} + inline virtual void proc() const { + uint32_t batchingTimeout = 0; + uint32_t batchingAccuracy = 0; + uint32_t batchSize = 0; + uint32_t tripBatchSize = 0; + static const loc_param_s_type flp_conf_param_table[] = + { + {"BATCH_SIZE", &batchSize, NULL, 'n'}, + {"OUTDOOR_TRIP_BATCH_SIZE", &tripBatchSize, NULL, 'n'}, + {"BATCH_SESSION_TIMEOUT", &batchingTimeout, NULL, 'n'}, + {"ACCURACY", &batchingAccuracy, NULL, 'n'}, + }; + UTIL_READ_CONF(LOC_PATH_FLP_CONF, flp_conf_param_table); + + LOC_LOGD("%s]: batchSize %u tripBatchSize %u batchingAccuracy %u batchingTimeout %u ", + __func__, batchSize, tripBatchSize, batchingAccuracy, batchingTimeout); + + mAdapter.setBatchSize(batchSize); + mAdapter.setTripBatchSize(tripBatchSize); + mAdapter.setBatchingTimeout(batchingTimeout); + mAdapter.setBatchingAccuracy(batchingAccuracy); + } + }; + + sendMsg(new MsgReadConfig(*this)); + +} + +void +BatchingAdapter::setConfigCommand() +{ + LOC_LOGD("%s]: ", __func__); + + struct MsgSetConfig : public LocMsg { + BatchingAdapter& mAdapter; + LocApiBase& mApi; + inline MsgSetConfig(BatchingAdapter& adapter, + LocApiBase& api) : + LocMsg(), + mAdapter(adapter), + mApi(api) {} + inline virtual void proc() const { + mApi.setBatchSize(mAdapter.getBatchSize()); + mApi.setTripBatchSize(mAdapter.getTripBatchSize()); + } + }; + + sendMsg(new MsgSetConfig(*this, *mLocApi)); +} + +void +BatchingAdapter::stopClientSessions(LocationAPI* client) +{ + LOC_LOGD("%s]: client %p", __func__, client); + + typedef struct pairKeyBatchMode { + LocationAPI* client; + uint32_t id; + BatchingMode batchingMode; + inline pairKeyBatchMode(LocationAPI* _client, uint32_t _id, BatchingMode _bMode) : + client(_client), id(_id), batchingMode(_bMode) {} + } pairKeyBatchMode; + std::vector<pairKeyBatchMode> vBatchingClient; + for (auto it : mBatchingSessions) { + if (client == it.first.client) { + vBatchingClient.emplace_back(it.first.client, it.first.id, it.second.batchingMode); + } + } + for (auto keyBatchingMode : vBatchingClient) { + if (keyBatchingMode.batchingMode != BATCHING_MODE_TRIP) { + stopBatching(keyBatchingMode.client, keyBatchingMode.id); + } else { + stopTripBatchingMultiplex(keyBatchingMode.client, keyBatchingMode.id); + } + } +} + +void +BatchingAdapter::updateClientsEventMask() +{ + LOC_API_ADAPTER_EVENT_MASK_T mask = 0; + for (auto it=mClientData.begin(); it != mClientData.end(); ++it) { + // we don't register LOC_API_ADAPTER_BIT_BATCH_FULL until we + // start batching with ROUTINE or TRIP option + if (it->second.batchingCb != nullptr) { + mask |= LOC_API_ADAPTER_BIT_BATCH_STATUS; + } + } + if (autoReportBatchingSessionsCount() > 0) { + mask |= LOC_API_ADAPTER_BIT_BATCH_FULL; + } + updateEvtMask(mask, LOC_REGISTRATION_MASK_SET); +} + +void +BatchingAdapter::handleEngineUpEvent() +{ + struct MsgSSREvent : public LocMsg { + BatchingAdapter& mAdapter; + LocApiBase& mApi; + inline MsgSSREvent(BatchingAdapter& adapter, + LocApiBase& api) : + LocMsg(), + mAdapter(adapter), + mApi(api) {} + virtual void proc() const { + mAdapter.setEngineCapabilitiesKnown(true); + mAdapter.broadcastCapabilities(mAdapter.getCapabilities()); + mApi.setBatchSize(mAdapter.getBatchSize()); + mApi.setTripBatchSize(mAdapter.getTripBatchSize()); + mAdapter.restartSessions(); + for (auto msg: mAdapter.mPendingMsgs) { + mAdapter.sendMsg(msg); + } + mAdapter.mPendingMsgs.clear(); + } + }; + + sendMsg(new MsgSSREvent(*this, *mLocApi)); +} + +void +BatchingAdapter::restartSessions() +{ + LOC_LOGD("%s]: ", __func__); + + if (autoReportBatchingSessionsCount() > 0) { + updateEvtMask(LOC_API_ADAPTER_BIT_BATCH_FULL, + LOC_REGISTRATION_MASK_ENABLED); + } + for (auto it = mBatchingSessions.begin(); + it != mBatchingSessions.end(); ++it) { + if (it->second.batchingMode != BATCHING_MODE_TRIP) { + mLocApi->startBatching(it->first.id, it->second, + getBatchingAccuracy(), getBatchingTimeout(), + new LocApiResponse(*getContext(), + [] (LocationError /*err*/) {})); + } + } + + if (mTripSessions.size() > 0) { + // restart outdoor trip batching session if any. + mOngoingTripDistance = 0; + mOngoingTripTBFInterval = 0; + + // record the min trip distance and min tbf interval of all ongoing sessions + for (auto tripSession : mTripSessions) { + + TripSessionStatus &tripSessStatus = tripSession.second; + + if ((0 == mOngoingTripDistance) || + (mOngoingTripDistance > + (tripSessStatus.tripDistance - tripSessStatus.accumulatedDistanceThisTrip))) { + mOngoingTripDistance = tripSessStatus.tripDistance - + tripSessStatus.accumulatedDistanceThisTrip; + } + + if ((0 == mOngoingTripTBFInterval) || + (mOngoingTripTBFInterval > tripSessStatus.tripTBFInterval)) { + mOngoingTripTBFInterval = tripSessStatus.tripTBFInterval; + } + + // reset the accumulatedDistanceOngoingBatch for each session + tripSessStatus.accumulatedDistanceOngoingBatch = 0; + + } + + mLocApi->startOutdoorTripBatching(mOngoingTripDistance, mOngoingTripTBFInterval, + getBatchingTimeout(), new LocApiResponse(*getContext(), [this] (LocationError err) { + if (LOCATION_ERROR_SUCCESS != err) { + mOngoingTripDistance = 0; + mOngoingTripTBFInterval = 0; + } + printTripReport(); + })); + } +} + +bool +BatchingAdapter::hasBatchingCallback(LocationAPI* client) +{ + auto it = mClientData.find(client); + return (it != mClientData.end() && it->second.batchingCb); +} + +bool +BatchingAdapter::isBatchingSession(LocationAPI* client, uint32_t sessionId) +{ + LocationSessionKey key(client, sessionId); + return (mBatchingSessions.find(key) != mBatchingSessions.end()); +} + +bool +BatchingAdapter::isTripSession(uint32_t sessionId) { + return (mTripSessions.find(sessionId) != mTripSessions.end()); +} + +void +BatchingAdapter::saveBatchingSession(LocationAPI* client, uint32_t sessionId, + const BatchingOptions& batchingOptions) +{ + LocationSessionKey key(client, sessionId); + mBatchingSessions[key] = batchingOptions; +} + +void +BatchingAdapter::eraseBatchingSession(LocationAPI* client, uint32_t sessionId) +{ + LocationSessionKey key(client, sessionId); + auto it = mBatchingSessions.find(key); + if (it != mBatchingSessions.end()) { + mBatchingSessions.erase(it); + } +} + +void +BatchingAdapter::reportResponse(LocationAPI* client, LocationError err, uint32_t sessionId) +{ + LOC_LOGD("%s]: client %p id %u err %u", __func__, client, sessionId, err); + + auto it = mClientData.find(client); + if (it != mClientData.end() && + it->second.responseCb != nullptr) { + it->second.responseCb(err, sessionId); + } else { + LOC_LOGE("%s]: client %p id %u not found in data", __func__, client, sessionId); + } +} + +uint32_t +BatchingAdapter::autoReportBatchingSessionsCount() +{ + uint32_t count = 0; + for (auto batchingSession: mBatchingSessions) { + if (batchingSession.second.batchingMode != BATCHING_MODE_NO_AUTO_REPORT) { + count++; + } + } + count += mTripSessions.size(); + return count; +} + +uint32_t +BatchingAdapter::startBatchingCommand( + LocationAPI* client, BatchingOptions& batchOptions) +{ + uint32_t sessionId = generateSessionId(); + LOC_LOGD("%s]: client %p id %u minInterval %u minDistance %u mode %u Batching Mode %d", + __func__, client, sessionId, batchOptions.minInterval, batchOptions.minDistance, + batchOptions.mode,batchOptions.batchingMode); + + struct MsgStartBatching : public LocMsg { + BatchingAdapter& mAdapter; + LocApiBase& mApi; + LocationAPI* mClient; + uint32_t mSessionId; + BatchingOptions mBatchingOptions; + inline MsgStartBatching(BatchingAdapter& adapter, + LocApiBase& api, + LocationAPI* client, + uint32_t sessionId, + BatchingOptions batchOptions) : + LocMsg(), + mAdapter(adapter), + mApi(api), + mClient(client), + mSessionId(sessionId), + mBatchingOptions(batchOptions) {} + inline virtual void proc() const { + if (!mAdapter.isEngineCapabilitiesKnown()) { + mAdapter.mPendingMsgs.push_back(new MsgStartBatching(*this)); + return; + } + LocationError err = LOCATION_ERROR_SUCCESS; + + if (!mAdapter.hasBatchingCallback(mClient)) { + err = LOCATION_ERROR_CALLBACK_MISSING; + } else if (0 == mBatchingOptions.size) { + err = LOCATION_ERROR_INVALID_PARAMETER; + } else if (!ContextBase::isMessageSupported( + LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_LOCATION_BATCHING)) { + err = LOCATION_ERROR_NOT_SUPPORTED; + } + if (LOCATION_ERROR_SUCCESS == err) { + if (mBatchingOptions.batchingMode == BATCHING_MODE_ROUTINE || + mBatchingOptions.batchingMode == BATCHING_MODE_NO_AUTO_REPORT) { + mAdapter.startBatching(mClient, mSessionId, mBatchingOptions); + } else if (mBatchingOptions.batchingMode == BATCHING_MODE_TRIP) { + mAdapter.startTripBatchingMultiplex(mClient, mSessionId, mBatchingOptions); + } else { + mAdapter.reportResponse(mClient, LOCATION_ERROR_INVALID_PARAMETER, mSessionId); + } + } + } + }; + + sendMsg(new MsgStartBatching(*this, *mLocApi, client, sessionId, batchOptions)); + + return sessionId; +} + +void +BatchingAdapter::startBatching(LocationAPI* client, uint32_t sessionId, + const BatchingOptions& batchingOptions) +{ + if (batchingOptions.batchingMode != BATCHING_MODE_NO_AUTO_REPORT && + 0 == autoReportBatchingSessionsCount()) { + // if there is currenty no batching sessions interested in batch full event, then this + // new session will need to register for batch full event + updateEvtMask(LOC_API_ADAPTER_BIT_BATCH_FULL, + LOC_REGISTRATION_MASK_ENABLED); + } + + // Assume start will be OK, remove session if not + saveBatchingSession(client, sessionId, batchingOptions); + mLocApi->startBatching(sessionId, batchingOptions, getBatchingAccuracy(), getBatchingTimeout(), + new LocApiResponse(*getContext(), + [this, client, sessionId, batchingOptions] (LocationError err) { + if (LOCATION_ERROR_SUCCESS != err) { + eraseBatchingSession(client, sessionId); + } + + if (LOCATION_ERROR_SUCCESS != err && + batchingOptions.batchingMode != BATCHING_MODE_NO_AUTO_REPORT && + 0 == autoReportBatchingSessionsCount()) { + // if we fail to start batching and we have already registered batch full event + // we need to undo that since no sessions are now interested in batch full event + updateEvtMask(LOC_API_ADAPTER_BIT_BATCH_FULL, + LOC_REGISTRATION_MASK_DISABLED); + } + + reportResponse(client, err, sessionId); + })); +} + +void +BatchingAdapter::updateBatchingOptionsCommand(LocationAPI* client, uint32_t id, + BatchingOptions& batchOptions) +{ + LOC_LOGD("%s]: client %p id %u minInterval %u minDistance %u mode %u batchMode %u", + __func__, client, id, batchOptions.minInterval, + batchOptions.minDistance, batchOptions.mode, + batchOptions.batchingMode); + + struct MsgUpdateBatching : public LocMsg { + BatchingAdapter& mAdapter; + LocApiBase& mApi; + LocationAPI* mClient; + uint32_t mSessionId; + BatchingOptions mBatchOptions; + inline MsgUpdateBatching(BatchingAdapter& adapter, + LocApiBase& api, + LocationAPI* client, + uint32_t sessionId, + BatchingOptions batchOptions) : + LocMsg(), + mAdapter(adapter), + mApi(api), + mClient(client), + mSessionId(sessionId), + mBatchOptions(batchOptions) {} + inline virtual void proc() const { + if (!mAdapter.isEngineCapabilitiesKnown()) { + mAdapter.mPendingMsgs.push_back(new MsgUpdateBatching(*this)); + return; + } + LocationError err = LOCATION_ERROR_SUCCESS; + if (!mAdapter.isBatchingSession(mClient, mSessionId)) { + err = LOCATION_ERROR_ID_UNKNOWN; + } else if ((0 == mBatchOptions.size) || + (mBatchOptions.batchingMode > BATCHING_MODE_NO_AUTO_REPORT)) { + err = LOCATION_ERROR_INVALID_PARAMETER; + } + if (LOCATION_ERROR_SUCCESS == err) { + if (!mAdapter.isTripSession(mSessionId)) { + mAdapter.stopBatching(mClient, mSessionId, true, mBatchOptions); + } else { + mAdapter.stopTripBatchingMultiplex(mClient, mSessionId, true, mBatchOptions); + } + } + } + }; + + sendMsg(new MsgUpdateBatching(*this, *mLocApi, client, id, batchOptions)); +} + +void +BatchingAdapter::stopBatchingCommand(LocationAPI* client, uint32_t id) +{ + LOC_LOGD("%s]: client %p id %u", __func__, client, id); + + struct MsgStopBatching : public LocMsg { + BatchingAdapter& mAdapter; + LocApiBase& mApi; + LocationAPI* mClient; + uint32_t mSessionId; + inline MsgStopBatching(BatchingAdapter& adapter, + LocApiBase& api, + LocationAPI* client, + uint32_t sessionId) : + LocMsg(), + mAdapter(adapter), + mApi(api), + mClient(client), + mSessionId(sessionId) {} + inline virtual void proc() const { + if (!mAdapter.isEngineCapabilitiesKnown()) { + mAdapter.mPendingMsgs.push_back(new MsgStopBatching(*this)); + return; + } + LocationError err = LOCATION_ERROR_SUCCESS; + if (!mAdapter.isBatchingSession(mClient, mSessionId)) { + err = LOCATION_ERROR_ID_UNKNOWN; + } + if (LOCATION_ERROR_SUCCESS == err) { + if (mAdapter.isTripSession(mSessionId)) { + mAdapter.stopTripBatchingMultiplex(mClient, mSessionId); + } else { + mAdapter.stopBatching(mClient, mSessionId); + } + } + } + }; + + sendMsg(new MsgStopBatching(*this, *mLocApi, client, id)); +} + +void +BatchingAdapter::stopBatching(LocationAPI* client, uint32_t sessionId, bool restartNeeded, + const BatchingOptions& batchOptions) +{ + LocationSessionKey key(client, sessionId); + auto it = mBatchingSessions.find(key); + if (it != mBatchingSessions.end()) { + auto flpOptions = it->second; + // Assume stop will be OK, restore session if not + eraseBatchingSession(client, sessionId); + mLocApi->stopBatching(sessionId, + new LocApiResponse(*getContext(), + [this, client, sessionId, flpOptions, restartNeeded, batchOptions] + (LocationError err) { + if (LOCATION_ERROR_SUCCESS != err) { + saveBatchingSession(client, sessionId, batchOptions); + } else { + // if stopBatching is success, unregister for batch full event if this was the last + // batching session that is interested in batch full event + if (0 == autoReportBatchingSessionsCount() && + flpOptions.batchingMode != BATCHING_MODE_NO_AUTO_REPORT) { + updateEvtMask(LOC_API_ADAPTER_BIT_BATCH_FULL, + LOC_REGISTRATION_MASK_DISABLED); + } + + if (restartNeeded) { + if (batchOptions.batchingMode == BATCHING_MODE_ROUTINE || + batchOptions.batchingMode == BATCHING_MODE_NO_AUTO_REPORT) { + startBatching(client, sessionId, batchOptions); + } else if (batchOptions.batchingMode == BATCHING_MODE_TRIP) { + startTripBatchingMultiplex(client, sessionId, batchOptions); + } + } + } + reportResponse(client, err, sessionId); + })); + } +} + +void +BatchingAdapter::getBatchedLocationsCommand(LocationAPI* client, uint32_t id, size_t count) +{ + LOC_LOGD("%s]: client %p id %u count %zu", __func__, client, id, count); + + struct MsgGetBatchedLocations : public LocMsg { + BatchingAdapter& mAdapter; + LocApiBase& mApi; + LocationAPI* mClient; + uint32_t mSessionId; + size_t mCount; + inline MsgGetBatchedLocations(BatchingAdapter& adapter, + LocApiBase& api, + LocationAPI* client, + uint32_t sessionId, + size_t count) : + LocMsg(), + mAdapter(adapter), + mApi(api), + mClient(client), + mSessionId(sessionId), + mCount(count) {} + inline virtual void proc() const { + if (!mAdapter.isEngineCapabilitiesKnown()) { + mAdapter.mPendingMsgs.push_back(new MsgGetBatchedLocations(*this)); + return; + } + LocationError err = LOCATION_ERROR_SUCCESS; + if (!mAdapter.hasBatchingCallback(mClient)) { + err = LOCATION_ERROR_CALLBACK_MISSING; + } else if (!mAdapter.isBatchingSession(mClient, mSessionId)) { + err = LOCATION_ERROR_ID_UNKNOWN; + } + if (LOCATION_ERROR_SUCCESS == err) { + if (mAdapter.isTripSession(mSessionId)) { + mApi.getBatchedTripLocations(mCount, 0, + new LocApiResponse(*mAdapter.getContext(), + [&mAdapter = mAdapter, mSessionId = mSessionId, + mClient = mClient] (LocationError err) { + mAdapter.reportResponse(mClient, err, mSessionId); + })); + } else { + mApi.getBatchedLocations(mCount, new LocApiResponse(*mAdapter.getContext(), + [&mAdapter = mAdapter, mSessionId = mSessionId, + mClient = mClient] (LocationError err) { + mAdapter.reportResponse(mClient, err, mSessionId); + })); + } + } else { + mAdapter.reportResponse(mClient, err, mSessionId); + } + } + }; + + sendMsg(new MsgGetBatchedLocations(*this, *mLocApi, client, id, count)); +} + +void +BatchingAdapter::reportLocationsEvent(const Location* locations, size_t count, + BatchingMode batchingMode) +{ + LOC_LOGD("%s]: count %zu batchMode %d", __func__, count, batchingMode); + + struct MsgReportLocations : public LocMsg { + BatchingAdapter& mAdapter; + Location* mLocations; + size_t mCount; + BatchingMode mBatchingMode; + inline MsgReportLocations(BatchingAdapter& adapter, + const Location* locations, + size_t count, + BatchingMode batchingMode) : + LocMsg(), + mAdapter(adapter), + mLocations(new Location[count]), + mCount(count), + mBatchingMode(batchingMode) + { + if (nullptr == mLocations) { + LOC_LOGE("%s]: new failed to allocate mLocations", __func__); + return; + } + for (size_t i=0; i < mCount; ++i) { + mLocations[i] = locations[i]; + } + } + inline virtual ~MsgReportLocations() { + if (nullptr != mLocations) + delete[] mLocations; + } + inline virtual void proc() const { + mAdapter.reportLocations(mLocations, mCount, mBatchingMode); + } + }; + + sendMsg(new MsgReportLocations(*this, locations, count, batchingMode)); +} + +void +BatchingAdapter::reportLocations(Location* locations, size_t count, BatchingMode batchingMode) +{ + BatchingOptions batchOptions = {sizeof(BatchingOptions), batchingMode}; + + for (auto it=mClientData.begin(); it != mClientData.end(); ++it) { + if (nullptr != it->second.batchingCb) { + it->second.batchingCb(count, locations, batchOptions); + } + } +} + +void +BatchingAdapter::reportCompletedTripsEvent(uint32_t accumulated_distance) +{ + struct MsgReportCompletedTrips : public LocMsg { + BatchingAdapter& mAdapter; + uint32_t mAccumulatedDistance; + inline MsgReportCompletedTrips(BatchingAdapter& adapter, + uint32_t accumulated_distance) : + LocMsg(), + mAdapter(adapter), + mAccumulatedDistance(accumulated_distance) + { + } + inline virtual ~MsgReportCompletedTrips() { + } + inline virtual void proc() const { + + // Check if any trips are completed + std::list<uint32_t> completedTripsList; + completedTripsList.clear(); + + for(auto itt = mAdapter.mTripSessions.begin(); itt != mAdapter.mTripSessions.end();) + { + TripSessionStatus &tripSession = itt->second; + + tripSession.accumulatedDistanceThisTrip = + tripSession.accumulatedDistanceOnTripRestart + + (mAccumulatedDistance - tripSession.accumulatedDistanceOngoingBatch); + if (tripSession.tripDistance <= tripSession.accumulatedDistanceThisTrip) { + // trip is completed + completedTripsList.push_back(itt->first); + itt = mAdapter.mTripSessions.erase(itt); + + if (tripSession.tripTBFInterval == mAdapter.mOngoingTripTBFInterval) { + // trip with ongoing TBF interval is completed + mAdapter.mTripWithOngoingTBFDropped = true; + } + + if (tripSession.tripDistance == mAdapter.mOngoingTripDistance) { + // trip with ongoing trip distance is completed + mAdapter.mTripWithOngoingTripDistanceDropped = true; + } + } else { + itt++; + } + } + + if (completedTripsList.size() > 0) { + mAdapter.reportBatchStatusChange(BATCHING_STATUS_TRIP_COMPLETED, + completedTripsList); + mAdapter.restartTripBatching(false, mAccumulatedDistance, 0); + } else { + mAdapter.printTripReport(); + } + } + }; + + LOC_LOGD("%s]: Accumulated Distance so far: %u", + __func__, accumulated_distance); + + sendMsg(new MsgReportCompletedTrips(*this, accumulated_distance)); +} + +void +BatchingAdapter::reportBatchStatusChange(BatchingStatus batchStatus, + std::list<uint32_t> & completedTripsList) +{ + BatchingStatusInfo batchStatusInfo = + {sizeof(BatchingStatusInfo), batchStatus}; + + for (auto it=mClientData.begin(); it != mClientData.end(); ++it) { + if (nullptr != it->second.batchingStatusCb) { + it->second.batchingStatusCb(batchStatusInfo, completedTripsList); + } + } +} + +void +BatchingAdapter::reportBatchStatusChangeEvent(BatchingStatus batchStatus) +{ + struct MsgReportBatchStatus : public LocMsg { + BatchingAdapter& mAdapter; + BatchingStatus mBatchStatus; + inline MsgReportBatchStatus(BatchingAdapter& adapter, + BatchingStatus batchStatus) : + LocMsg(), + mAdapter(adapter), + mBatchStatus(batchStatus) + { + } + inline virtual ~MsgReportBatchStatus() { + } + inline virtual void proc() const { + std::list<uint32_t> tempList; + tempList.clear(); + mAdapter.reportBatchStatusChange(mBatchStatus, tempList); + } + }; + + sendMsg(new MsgReportBatchStatus(*this, batchStatus)); +} + +void +BatchingAdapter::startTripBatchingMultiplex(LocationAPI* client, uint32_t sessionId, + const BatchingOptions& batchingOptions) +{ + if (mTripSessions.size() == 0) { + // if there is currenty no batching sessions interested in batch full event, then this + // new session will need to register for batch full event + if (0 == autoReportBatchingSessionsCount()) { + updateEvtMask(LOC_API_ADAPTER_BIT_BATCH_FULL, + LOC_REGISTRATION_MASK_ENABLED); + } + + // Assume start will be OK, remove session if not + saveBatchingSession(client, sessionId, batchingOptions); + + mTripSessions[sessionId] = { 0, 0, 0, batchingOptions.minDistance, + batchingOptions.minInterval}; + mLocApi->startOutdoorTripBatching(batchingOptions.minDistance, + batchingOptions.minInterval, getBatchingTimeout(), new LocApiResponse(*getContext(), + [this, client, sessionId, batchingOptions] (LocationError err) { + if (err == LOCATION_ERROR_SUCCESS) { + mOngoingTripDistance = batchingOptions.minDistance; + mOngoingTripTBFInterval = batchingOptions.minInterval; + LOC_LOGD("%s] New Trip started ...", __func__); + printTripReport(); + } else { + eraseBatchingSession(client, sessionId); + mTripSessions.erase(sessionId); + // if we fail to start batching and we have already registered batch full event + // we need to undo that since no sessions are now interested in batch full event + if (0 == autoReportBatchingSessionsCount()) { + updateEvtMask(LOC_API_ADAPTER_BIT_BATCH_FULL, + LOC_REGISTRATION_MASK_DISABLED); + } + } + reportResponse(client, err, sessionId); + })); + } else { + // query accumulated distance + mLocApi->queryAccumulatedTripDistance( + new LocApiResponseData<LocApiBatchData>(*getContext(), + [this, batchingOptions, sessionId, client] + (LocationError err, LocApiBatchData data) { + uint32_t accumulatedDistanceOngoingBatch = 0; + uint32_t numOfBatchedPositions = 0; + uint32_t ongoingTripDistance = mOngoingTripDistance; + uint32_t ongoingTripInterval = mOngoingTripTBFInterval; + bool needsRestart = false; + + // check if TBF of new session is lesser than ongoing TBF interval + if (ongoingTripInterval > batchingOptions.minInterval) { + ongoingTripInterval = batchingOptions.minInterval; + needsRestart = true; + } + accumulatedDistanceOngoingBatch = data.accumulatedDistance; + numOfBatchedPositions = data.numOfBatchedPositions; + TripSessionStatus newTripSession = { accumulatedDistanceOngoingBatch, 0, 0, + batchingOptions.minDistance, + batchingOptions.minInterval}; + if (err != LOCATION_ERROR_SUCCESS) { + // unable to query accumulated distance, assume remaining distance in + // ongoing batch is mongoingTripDistance. + if (batchingOptions.minDistance < ongoingTripDistance) { + ongoingTripDistance = batchingOptions.minDistance; + needsRestart = true; + } + } else { + // compute the remaining distance + uint32_t ongoing_trip_remaining_distance = ongoingTripDistance - + accumulatedDistanceOngoingBatch; + + // check if new trip distance is lesser than the ongoing batch remaining distance + if (batchingOptions.minDistance < ongoing_trip_remaining_distance) { + ongoingTripDistance = batchingOptions.minDistance; + needsRestart = true; + } else if (needsRestart == true) { + // needsRestart is anyways true , may be because of lesser TBF of new session. + ongoingTripDistance = ongoing_trip_remaining_distance; + } + mTripSessions[sessionId] = newTripSession; + LOC_LOGD("%s] New Trip started ...", __func__); + printTripReport(); + } + + if (needsRestart) { + mOngoingTripDistance = ongoingTripDistance; + mOngoingTripTBFInterval = ongoingTripInterval; + + // reset the accumulatedDistanceOngoingBatch for each session, + // and record the total accumulated distance so far for the session. + for (auto itt = mTripSessions.begin(); itt != mTripSessions.end(); itt++) { + TripSessionStatus &tripSessStatus = itt->second; + tripSessStatus.accumulatedDistanceOngoingBatch = 0; + tripSessStatus.accumulatedDistanceOnTripRestart = + tripSessStatus.accumulatedDistanceThisTrip; + } + mLocApi->reStartOutdoorTripBatching(ongoingTripDistance, ongoingTripInterval, + getBatchingTimeout(), new LocApiResponse(*getContext(), + [this, client, sessionId] (LocationError err) { + if (err != LOCATION_ERROR_SUCCESS) { + LOC_LOGE("%s] New Trip restart failed!", __func__); + } + reportResponse(client, err, sessionId); + })); + } else { + reportResponse(client, LOCATION_ERROR_SUCCESS, sessionId); + } + })); + } +} + +void +BatchingAdapter::stopTripBatchingMultiplex(LocationAPI* client, uint32_t sessionId, + bool restartNeeded, const BatchingOptions& batchOptions) +{ + LocationError err = LOCATION_ERROR_SUCCESS; + + if (mTripSessions.size() == 1) { + mLocApi->stopOutdoorTripBatching(true, new LocApiResponse(*getContext(), + [this, restartNeeded, client, sessionId, batchOptions] + (LocationError err) { + if (LOCATION_ERROR_SUCCESS == err) { + // if stopOutdoorTripBatching is success, unregister for batch full event if this + // was the last batching session that is interested in batch full event + if (1 == autoReportBatchingSessionsCount()) { + updateEvtMask(LOC_API_ADAPTER_BIT_BATCH_FULL, + LOC_REGISTRATION_MASK_DISABLED); + } + } + stopTripBatchingMultiplexCommon(err, client, sessionId, restartNeeded, batchOptions); + })); + return; + } + + stopTripBatchingMultiplexCommon(err, client, sessionId, restartNeeded, batchOptions); +} + +void +BatchingAdapter::stopTripBatchingMultiplexCommon(LocationError err, LocationAPI* client, + uint32_t sessionId, bool restartNeeded, const BatchingOptions& batchOptions) +{ + auto itt = mTripSessions.find(sessionId); + TripSessionStatus tripSess = itt->second; + if (tripSess.tripTBFInterval == mOngoingTripTBFInterval) { + // trip with ongoing trip interval is stopped + mTripWithOngoingTBFDropped = true; + } + + if (tripSess.tripDistance == mOngoingTripDistance) { + // trip with ongoing trip distance is stopped + mTripWithOngoingTripDistanceDropped = true; + } + + mTripSessions.erase(sessionId); + + if (mTripSessions.size() == 0) { + mOngoingTripDistance = 0; + mOngoingTripTBFInterval = 0; + } else { + restartTripBatching(true); + } + + if (restartNeeded) { + eraseBatchingSession(client, sessionId); + if (batchOptions.batchingMode == BATCHING_MODE_ROUTINE || + batchOptions.batchingMode == BATCHING_MODE_NO_AUTO_REPORT) { + startBatching(client, sessionId, batchOptions); + } else if (batchOptions.batchingMode == BATCHING_MODE_TRIP) { + startTripBatchingMultiplex(client, sessionId, batchOptions); + } + } + reportResponse(client, err, sessionId); +} + + +void +BatchingAdapter::restartTripBatching(bool queryAccumulatedDistance, uint32_t accDist, + uint32_t numbatchedPos) +{ + // does batch need restart with new trip distance / TBF interval + uint32_t minRemainingDistance = 0; + uint32_t minTBFInterval = 0; + + // if no more trips left, stop the ongoing trip + if (mTripSessions.size() == 0) { + mLocApi->stopOutdoorTripBatching(true, new LocApiResponse(*getContext(), + [] (LocationError /*err*/) {})); + mOngoingTripDistance = 0; + mOngoingTripTBFInterval = 0; + // unregister for batch full event if there are no more + // batching session that is interested in batch full event + if (0 == autoReportBatchingSessionsCount()) { + updateEvtMask(LOC_API_ADAPTER_BIT_BATCH_FULL, + LOC_REGISTRATION_MASK_DISABLED); + } + return; + } + + // record the min trip distance and min tbf interval of all ongoing sessions + for (auto itt = mTripSessions.begin(); itt != mTripSessions.end(); itt++) { + + TripSessionStatus tripSessStatus = itt->second; + + if ((minRemainingDistance == 0) || + (minRemainingDistance > (tripSessStatus.tripDistance + - tripSessStatus.accumulatedDistanceThisTrip))) { + minRemainingDistance = tripSessStatus.tripDistance - + tripSessStatus.accumulatedDistanceThisTrip; + } + + if ((minTBFInterval == 0) || + (minTBFInterval > tripSessStatus.tripTBFInterval)) { + minTBFInterval = tripSessStatus.tripTBFInterval; + } + } + + mLocApi->queryAccumulatedTripDistance( + new LocApiResponseData<LocApiBatchData>(*getContext(), + [this, queryAccumulatedDistance, minRemainingDistance, minTBFInterval, accDist, + numbatchedPos] (LocationError /*err*/, LocApiBatchData data) { + bool needsRestart = false; + + uint32_t ongoingTripDistance = mOngoingTripDistance; + uint32_t ongoingTripInterval = mOngoingTripTBFInterval; + uint32_t accumulatedDistance = accDist; + uint32_t numOfBatchedPositions = numbatchedPos; + + if (queryAccumulatedDistance) { + accumulatedDistance = data.accumulatedDistance; + numOfBatchedPositions = data.numOfBatchedPositions; + } + + if ((!mTripWithOngoingTripDistanceDropped) && + (ongoingTripDistance - accumulatedDistance != 0)) { + // if ongoing trip is already not completed still, + // check the min distance against the remaining distance + if (minRemainingDistance < + (ongoingTripDistance - accumulatedDistance)) { + ongoingTripDistance = minRemainingDistance; + needsRestart = true; + } + } else if (minRemainingDistance != 0) { + // else if ongoing trip is already completed / dropped, + // use the minRemainingDistance of ongoing sessions + ongoingTripDistance = minRemainingDistance; + needsRestart = true; + } + + if ((minTBFInterval < ongoingTripInterval) || + ((minTBFInterval != ongoingTripInterval) && + (mTripWithOngoingTBFDropped))) { + ongoingTripInterval = minTBFInterval; + needsRestart = true; + } + + if (needsRestart) { + mLocApi->reStartOutdoorTripBatching(ongoingTripDistance, ongoingTripInterval, + getBatchingTimeout(), new LocApiResponse(*getContext(), + [this, accumulatedDistance, ongoingTripDistance, ongoingTripInterval] + (LocationError err) { + + if (err == LOCATION_ERROR_SUCCESS) { + for(auto itt = mTripSessions.begin(); itt != mTripSessions.end(); itt++) { + TripSessionStatus &tripSessStatus = itt->second; + tripSessStatus.accumulatedDistanceThisTrip = + tripSessStatus.accumulatedDistanceOnTripRestart + + (accumulatedDistance - + tripSessStatus.accumulatedDistanceOngoingBatch); + + tripSessStatus.accumulatedDistanceOngoingBatch = 0; + tripSessStatus.accumulatedDistanceOnTripRestart = + tripSessStatus.accumulatedDistanceThisTrip; + } + + mOngoingTripDistance = ongoingTripDistance; + mOngoingTripTBFInterval = ongoingTripInterval; + } + })); + } + })); +} + +void +BatchingAdapter::printTripReport() +{ + IF_LOC_LOGD { + LOC_LOGD("Ongoing Trip Distance = %u, Ongoing Trip TBF Interval = %u", + mOngoingTripDistance, mOngoingTripTBFInterval); + + for (auto itt = mTripSessions.begin(); itt != mTripSessions.end(); itt++) { + TripSessionStatus tripSessStatus = itt->second; + + LOC_LOGD("tripDistance:%u tripTBFInterval:%u" + " trip accumulated Distance:%u" + " trip accumualted distance ongoing batch:%u" + " trip accumulated distance on trip restart %u \r\n", + tripSessStatus.tripDistance, tripSessStatus.tripTBFInterval, + tripSessStatus.accumulatedDistanceThisTrip, + tripSessStatus.accumulatedDistanceOngoingBatch, + tripSessStatus.accumulatedDistanceOnTripRestart); + } + } +} diff --git a/batching/BatchingAdapter.h b/batching/BatchingAdapter.h new file mode 100644 index 0000000..66f7c5f --- /dev/null +++ b/batching/BatchingAdapter.h @@ -0,0 +1,152 @@ +/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef BATCHING_ADAPTER_H +#define BATCHING_ADAPTER_H + +#include <LocAdapterBase.h> +#include <LocContext.h> +#include <LocationAPI.h> +#include <map> + +using namespace loc_core; + +class BatchingAdapter : public LocAdapterBase { + + /* ==== BATCHING ======================================================================= */ + typedef struct { + uint32_t accumulatedDistanceOngoingBatch; + uint32_t accumulatedDistanceThisTrip; + uint32_t accumulatedDistanceOnTripRestart; + uint32_t tripDistance; + uint32_t tripTBFInterval; + } TripSessionStatus; + typedef std::map<uint32_t, TripSessionStatus> TripSessionStatusMap; + typedef std::map<LocationSessionKey, BatchingOptions> BatchingSessionMap; + + BatchingSessionMap mBatchingSessions; + TripSessionStatusMap mTripSessions; + uint32_t mOngoingTripDistance; + uint32_t mOngoingTripTBFInterval; + bool mTripWithOngoingTBFDropped; + bool mTripWithOngoingTripDistanceDropped; + + void startTripBatchingMultiplex(LocationAPI* client, uint32_t sessionId, + const BatchingOptions& batchingOptions); + void stopTripBatchingMultiplex(LocationAPI* client, uint32_t sessionId, + bool restartNeeded, + const BatchingOptions& batchOptions); + inline void stopTripBatchingMultiplex(LocationAPI* client, uint32_t id) { + BatchingOptions batchOptions; + stopTripBatchingMultiplex(client, id, false, batchOptions); + }; + void stopTripBatchingMultiplexCommon(LocationError err, + LocationAPI* client, + uint32_t sessionId, + bool restartNeeded, + const BatchingOptions& batchOptions); + void restartTripBatching(bool queryAccumulatedDistance, uint32_t accDist = 0, + uint32_t numbatchedPos = 0); + void printTripReport(); + + /* ==== CONFIGURATION ================================================================== */ + uint32_t mBatchingTimeout; + uint32_t mBatchingAccuracy; + size_t mBatchSize; + size_t mTripBatchSize; + +protected: + + /* ==== CLIENT ========================================================================= */ + virtual void updateClientsEventMask(); + virtual void stopClientSessions(LocationAPI* client); + +public: + BatchingAdapter(); + virtual ~BatchingAdapter() {} + + /* ==== SSR ============================================================================ */ + /* ======== EVENTS ====(Called from QMI Thread)========================================= */ + virtual void handleEngineUpEvent(); + /* ======== UTILITIES ================================================================== */ + void restartSessions(); + + /* ==== BATCHING ======================================================================= */ + /* ======== COMMANDS ====(Called from Client Thread)==================================== */ + uint32_t startBatchingCommand(LocationAPI* client, BatchingOptions &batchOptions); + void updateBatchingOptionsCommand( + LocationAPI* client, uint32_t id, BatchingOptions& batchOptions); + void stopBatchingCommand(LocationAPI* client, uint32_t id); + void getBatchedLocationsCommand(LocationAPI* client, uint32_t id, size_t count); + /* ======== RESPONSES ================================================================== */ + void reportResponse(LocationAPI* client, LocationError err, uint32_t sessionId); + /* ======== UTILITIES ================================================================== */ + bool hasBatchingCallback(LocationAPI* client); + bool isBatchingSession(LocationAPI* client, uint32_t sessionId); + bool isTripSession(uint32_t sessionId); + void saveBatchingSession(LocationAPI* client, uint32_t sessionId, + const BatchingOptions& batchingOptions); + void eraseBatchingSession(LocationAPI* client, uint32_t sessionId); + uint32_t autoReportBatchingSessionsCount(); + void startBatching(LocationAPI* client, uint32_t sessionId, + const BatchingOptions& batchingOptions); + void stopBatching(LocationAPI* client, uint32_t sessionId, bool restartNeeded, + const BatchingOptions& batchOptions); + void stopBatching(LocationAPI* client, uint32_t sessionId) { + BatchingOptions batchOptions; + stopBatching(client, sessionId, false, batchOptions); + }; + + /* ==== REPORTS ======================================================================== */ + /* ======== EVENTS ====(Called from QMI Thread)========================================= */ + void reportLocationsEvent(const Location* locations, size_t count, + BatchingMode batchingMode); + void reportCompletedTripsEvent(uint32_t accumulatedDistance); + void reportBatchStatusChangeEvent(BatchingStatus batchStatus); + /* ======== UTILITIES ================================================================== */ + void reportLocations(Location* locations, size_t count, BatchingMode batchingMode); + void reportBatchStatusChange(BatchingStatus batchStatus, + std::list<uint32_t> & completedTripsList); + + /* ==== CONFIGURATION ================================================================== */ + /* ======== COMMANDS ====(Called from Client Thread)==================================== */ + void readConfigCommand(); + void setConfigCommand(); + /* ======== UTILITIES ================================================================== */ + void setBatchSize(size_t batchSize) { mBatchSize = batchSize; } + size_t getBatchSize() { return mBatchSize; } + void setTripBatchSize(size_t batchSize) { mTripBatchSize = batchSize; } + size_t getTripBatchSize() { return mTripBatchSize; } + void setBatchingTimeout(uint32_t batchingTimeout) { mBatchingTimeout = batchingTimeout; } + uint32_t getBatchingTimeout() { return mBatchingTimeout; } + void setBatchingAccuracy(uint32_t accuracy) { mBatchingAccuracy = accuracy; } + uint32_t getBatchingAccuracy() { return mBatchingAccuracy; } + +}; + +#endif /* BATCHING_ADAPTER_H */ diff --git a/batching/Makefile.am b/batching/Makefile.am new file mode 100644 index 0000000..ef8011e --- /dev/null +++ b/batching/Makefile.am @@ -0,0 +1,45 @@ +AM_CFLAGS = \ + $(GPSUTILS_CFLAGS) \ + $(LOCCORE_CFLAGS) \ + -I./ \ + -std=c++1y \ + -D__func__=__PRETTY_FUNCTION__ \ + -fno-short-enums + +ACLOCAL_AMFLAGS = -I m4 + +requiredlibs = \ + $(GPSUTILS_LIBS) \ + $(LOCCORE_LIBS) \ + -llog + +h_sources = \ + BatchingAdapter.h + +libbatching_la_SOURCES = \ + location_batching.cpp \ + BatchingAdapter.cpp + +if USE_GLIB +libbatching_la_CFLAGS = -DUSE_GLIB $(AM_CFLAGS) @GLIB_CFLAGS@ +#libbatching_la_LDFLAGS = -lstdc++ -g -Wl,-z,defs -lpthread $(requiredlibs) @GLIB_LIBS@ -shared -avoid-version +libbatching_la_LDFLAGS = -lstdc++ -g -Wl,-z,defs -lpthread $(requiredlibs) @GLIB_LIBS@ -avoid-version +libbatching_la_CPPFLAGS = -DUSE_GLIB $(AM_CFLAGS) $(AM_CPPFLAGS) @GLIB_CFLAGS@ +else +libbatching_la_CFLAGS = $(AM_CFLAGS) +libbatching_la_LDFLAGS = -Wl,-z,defs -lpthread $(requiredlibs) -shared -version-info 1:0:0 +libbatching_la_CPPFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS) +endif + +library_include_HEADERS = $(h_sources) + +library_includedir = $(pkgincludedir) + +#Create and Install libraries +lib_LTLIBRARIES = libbatching.la + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = location-batching.pc +sysconf_DATA = $(WORKSPACE)/hardware/qcom/gps/etc/flp.conf +EXTRA_DIST = $(pkgconfig_DATA) + diff --git a/batching/configure.ac b/batching/configure.ac new file mode 100644 index 0000000..27435c6 --- /dev/null +++ b/batching/configure.ac @@ -0,0 +1,78 @@ +# configure.ac -- Autoconf script for gps location-batching +# +# Process this file with autoconf to produce a configure script + +# Requires autoconf tool later than 2.61 +AC_PREREQ(2.61) +# Initialize the gps location-batching package version 1.0.0 +AC_INIT([location-batching],1.0.0) +# Does not strictly follow GNU Coding standards +AM_INIT_AUTOMAKE([foreign]) +# Disables auto rebuilding of configure, Makefile.ins +AM_MAINTAINER_MODE +# Verifies the --srcdir is correct by checking for the path +AC_CONFIG_SRCDIR([Makefile.am]) +# defines some macros variable to be included by source +AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_MACRO_DIR([m4]) + +# Checks for programs. +AC_PROG_LIBTOOL +AC_PROG_CXX +AC_PROG_CC +AM_PROG_CC_C_O +AC_PROG_AWK +AC_PROG_CPP +AC_PROG_INSTALL +AC_PROG_LN_S +AC_PROG_MAKE_SET +PKG_PROG_PKG_CONFIG + +# Checks for libraries. +PKG_CHECK_MODULES([GPSUTILS], [gps-utils]) +AC_SUBST([GPSUTILS_CFLAGS]) +AC_SUBST([GPSUTILS_LIBS]) + +PKG_CHECK_MODULES([LOCCORE], [loc-core]) +AC_SUBST([LOCCORE_CFLAGS]) +AC_SUBST([LOCCORE_LIBS]) + +PKG_CHECK_MODULES([GEOFENCE], [location-geofence]) +AC_SUBST([GEOFENCE_CFLAGS]) +AC_SUBST([GEOFENCE_LIBS]) + +AC_ARG_WITH([locpla_includes], + AC_HELP_STRING([--with-locpla-includes=@<:@dir@:>@], + [specify the path to locpla-includes in loc-pla_git.bb]), + [locpla_incdir=$withval], + with_locpla_includes=no) + +if test "x$with_locpla_includes" != "xno"; then + AC_SUBST(LOCPLA_CFLAGS, "-I${locpla_incdir}") +fi + +AC_ARG_WITH([glib], + AC_HELP_STRING([--with-glib], + [enable glib, building HLOS systems which use glib])) + +if (test "x${with_glib}" = "xyes"); then + AC_DEFINE(ENABLE_USEGLIB, 1, [Define if HLOS systems uses glib]) + PKG_CHECK_MODULES(GTHREAD, gthread-2.0 >= 2.16, dummy=yes, + AC_MSG_ERROR(GThread >= 2.16 is required)) + PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.16, dummy=yes, + AC_MSG_ERROR(GLib >= 2.16 is required)) + GLIB_CFLAGS="$GLIB_CFLAGS $GTHREAD_CFLAGS" + GLIB_LIBS="$GLIB_LIBS $GTHREAD_LIBS" + + AC_SUBST(GLIB_CFLAGS) + AC_SUBST(GLIB_LIBS) +fi + +AM_CONDITIONAL(USE_GLIB, test "x${with_glib}" = "xyes") + +AC_CONFIG_FILES([ \ + Makefile \ + location-batching.pc + ]) + +AC_OUTPUT diff --git a/batching/location-batching.pc.in b/batching/location-batching.pc.in new file mode 100644 index 0000000..da1fbf4 --- /dev/null +++ b/batching/location-batching.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: location-batching +Description: QTI GPS Batching +Version: @VERSION +Libs: -L${libdir} -lbatching +Cflags: -I${includedir}/location-batching diff --git a/batching/location_batching.cpp b/batching/location_batching.cpp new file mode 100644 index 0000000..571da72 --- /dev/null +++ b/batching/location_batching.cpp @@ -0,0 +1,134 @@ +/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "BatchingAdapter.h" +#include "location_interface.h" + +static BatchingAdapter* gBatchingAdapter = NULL; + +static void initialize(); +static void deinitialize(); + +static void addClient(LocationAPI* client, const LocationCallbacks& callbacks); +static void removeClient(LocationAPI* client, removeClientCompleteCallback rmClientCb); +static void requestCapabilities(LocationAPI* client); + +static uint32_t startBatching(LocationAPI* client, BatchingOptions&); +static void stopBatching(LocationAPI* client, uint32_t id); +static void updateBatchingOptions(LocationAPI* client, uint32_t id, BatchingOptions&); +static void getBatchedLocations(LocationAPI* client, uint32_t id, size_t count); + +static const BatchingInterface gBatchingInterface = { + sizeof(BatchingInterface), + initialize, + deinitialize, + addClient, + removeClient, + requestCapabilities, + startBatching, + stopBatching, + updateBatchingOptions, + getBatchedLocations +}; + +#ifndef DEBUG_X86 +extern "C" const BatchingInterface* getBatchingInterface() +#else +const BatchingInterface* getBatchingInterface() +#endif // DEBUG_X86 +{ + return &gBatchingInterface; +} + +static void initialize() +{ + if (NULL == gBatchingAdapter) { + gBatchingAdapter = new BatchingAdapter(); + } +} + +static void deinitialize() +{ + if (NULL != gBatchingAdapter) { + delete gBatchingAdapter; + gBatchingAdapter = NULL; + } +} + +static void addClient(LocationAPI* client, const LocationCallbacks& callbacks) +{ + if (NULL != gBatchingAdapter) { + gBatchingAdapter->addClientCommand(client, callbacks); + } +} + +static void removeClient(LocationAPI* client, removeClientCompleteCallback rmClientCb) +{ + if (NULL != gBatchingAdapter) { + gBatchingAdapter->removeClientCommand(client, rmClientCb); + } +} + +static void requestCapabilities(LocationAPI* client) +{ + if (NULL != gBatchingAdapter) { + gBatchingAdapter->requestCapabilitiesCommand(client); + } +} + +static uint32_t startBatching(LocationAPI* client, BatchingOptions &batchOptions) +{ + if (NULL != gBatchingAdapter) { + return gBatchingAdapter->startBatchingCommand(client, batchOptions); + } else { + return 0; + } +} + +static void stopBatching(LocationAPI* client, uint32_t id) +{ + if (NULL != gBatchingAdapter) { + gBatchingAdapter->stopBatchingCommand(client, id); + } +} + +static void updateBatchingOptions( + LocationAPI* client, uint32_t id, BatchingOptions& batchOptions) +{ + if (NULL != gBatchingAdapter) { + gBatchingAdapter->updateBatchingOptionsCommand(client, id, batchOptions); + } +} + +static void getBatchedLocations(LocationAPI* client, uint32_t id, size_t count) +{ + if (NULL != gBatchingAdapter) { + gBatchingAdapter->getBatchedLocationsCommand(client, id, count); + } +} + diff --git a/build/target_specific_features.mk b/build/target_specific_features.mk index 0c0f730..2e74aff 100644 --- a/build/target_specific_features.mk +++ b/build/target_specific_features.mk @@ -16,6 +16,8 @@ GNSS_CFLAGS := \ -Wno-error=switch \ -Wno-error=date-time +LOCAL_SANITIZE := signed-integer-overflow, unsigned-integer-overflow + # GPS-HIDL GNSS_HIDL_1_0_TARGET_LIST := msm8960 GNSS_HIDL_1_0_TARGET_LIST += msm8974 @@ -28,23 +30,38 @@ GNSS_HIDL_1_0_TARGET_LIST += msm8909 GNSS_HIDL_1_0_TARGET_LIST += msm8952 GNSS_HIDL_1_0_TARGET_LIST += msm8992 GNSS_HIDL_1_0_TARGET_LIST += msm8996 -GNSS_HIDL_1_0_TARGET_LIST += msm8937 -GNSS_HIDL_1_0_TARGET_LIST += msm8953 -GNSS_HIDL_1_0_TARGET_LIST += msm8998 -GNSS_HIDL_1_0_TARGET_LIST += apq8098_latv -GNSS_HIDL_1_0_TARGET_LIST += sdm710 -GNSS_HIDL_1_0_TARGET_LIST += qcs605 -GNSS_HIDL_1_0_TARGET_LIST += sdm845 -GNSS_HIDL_1_0_TARGET_LIST += sdm660 -GNSS_HIDL_1_1_TARGET_LIST := msmnile -GNSS_HIDL_1_1_TARGET_LIST += $(MSMSTEPPE) -GNSS_HIDL_1_1_TARGET_LIST += $(TRINKET) - +GNSS_HIDL_2_0_TARGET_LIST := msm8937 +GNSS_HIDL_2_0_TARGET_LIST += msm8953 +GNSS_HIDL_2_0_TARGET_LIST += msm8998 +GNSS_HIDL_2_0_TARGET_LIST += apq8098_latv +GNSS_HIDL_2_0_TARGET_LIST += sdm710 +GNSS_HIDL_2_0_TARGET_LIST += qcs605 +GNSS_HIDL_2_0_TARGET_LIST += sdm845 +GNSS_HIDL_2_0_TARGET_LIST += sdm660 +GNSS_HIDL_2_0_TARGET_LIST += msmnile +GNSS_HIDL_2_0_TARGET_LIST += $(MSMSTEPPE) +GNSS_HIDL_2_0_TARGET_LIST += $(TRINKET) +GNSS_HIDL_2_0_TARGET_LIST += kona +ifneq (,$(filter $(GNSS_HIDL_2_0_TARGET_LIST),$(TARGET_BOARD_PLATFORM))) +GNSS_HIDL_VERSION = 2.0 +endif ifneq (,$(filter $(GNSS_HIDL_1_0_TARGET_LIST),$(TARGET_BOARD_PLATFORM))) GNSS_HIDL_VERSION = 1.0 endif - ifneq (,$(filter $(GNSS_HIDL_1_1_TARGET_LIST),$(TARGET_BOARD_PLATFORM))) GNSS_HIDL_VERSION = 1.1 endif + +GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST := msm8937 +GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST += msm8953 +GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST += msm8998 +GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST += apq8098_latv +GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST += sdm710 +GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST += qcs605 +GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST += sdm845 +GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST += sdm660 + +ifneq (,$(filter $(GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST),$(TARGET_BOARD_PLATFORM))) +GNSS_HIDL_LEGACY_MEASURMENTS = true +endif diff --git a/core/Android.mk b/core/Android.mk index 97614a1..bd955c1 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/ContextBase.cpp b/core/ContextBase.cpp index 3d55e1c..28109bb 100644 --- a/core/ContextBase.cpp +++ b/core/ContextBase.cpp @@ -108,7 +108,7 @@ void ContextBase::readConfig() mGps_conf.INTERMEDIATE_POS = 0; mGps_conf.ACCURACY_THRES = 0; mGps_conf.NMEA_PROVIDER = 0; - mGps_conf.GPS_LOCK = 0x03; + mGps_conf.GPS_LOCK = GNSS_CONFIG_GPS_LOCK_MO_AND_NI; mGps_conf.SUPL_VER = 0x10000; mGps_conf.SUPL_MODE = 0x1; mGps_conf.SUPL_ES = 0; diff --git a/core/ContextBase.h b/core/ContextBase.h index 8a3d300..9c72835 100644 --- a/core/ContextBase.h +++ b/core/ContextBase.h @@ -55,7 +55,7 @@ typedef struct loc_gps_cfg_s char XTRA_SERVER_3[LOC_MAX_PARAM_STRING]; uint32_t USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL; uint32_t NMEA_PROVIDER; - uint32_t GPS_LOCK; + GnssConfigGpsLock GPS_LOCK; uint32_t A_GLONASS_POS_PROTOCOL_SELECT; uint32_t AGPS_CERT_WRITABLE_MASK; uint32_t AGPS_CONFIG_INJECT; diff --git a/core/EngineHubProxyBase.h b/core/EngineHubProxyBase.h index 34af4d0..4239a50 100644 --- a/core/EngineHubProxyBase.h +++ b/core/EngineHubProxyBase.h @@ -90,6 +90,17 @@ public: (void) systemInfo; return false; } + + inline virtual bool gnssReportKlobucharIonoModel(const GnssKlobucharIonoModel& ionoModel) { + (void) ionoModel; + return false; + } + + inline virtual bool gnssReportAdditionalSystemInfo( + const GnssAdditionalSystemInfo& additionalSystemInfo) { + (void) additionalSystemInfo; + return false; + } }; typedef std::function<void(const UlpLocation& ulpLocation, diff --git a/core/LocAdapterBase.cpp b/core/LocAdapterBase.cpp index 3f82dd6..6fad918 100644 --- a/core/LocAdapterBase.cpp +++ b/core/LocAdapterBase.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2014, 2016-2018 The Linux Foundation. All rights reserved. +/* 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 @@ -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); } @@ -100,10 +101,6 @@ void LocAdapterBase:: DEFAULT_IMPL() void LocAdapterBase:: - reportSvMeasurementEvent(GnssSvMeasurementSet &/*svMeasurementSet*/) -DEFAULT_IMPL() - -void LocAdapterBase:: reportSvPolynomialEvent(GnssSvPolynomial &/*svPolynomial*/) DEFAULT_IMPL() @@ -161,7 +158,7 @@ bool LocAdapterBase:: DEFAULT_IMPL(false) void LocAdapterBase:: - reportGnssMeasurementDataEvent(const GnssMeasurementsNotification& /*measurements*/, +reportGnssMeasurementsEvent(const GnssMeasurements& /*gnssMeasurements*/, int /*msInWeek*/) DEFAULT_IMPL() @@ -191,4 +188,220 @@ DEFAULT_IMPL(false) bool LocAdapterBase:: reportDeleteAidingDataEvent(GnssAidingData & /*aidingData*/) DEFAULT_IMPL(false) + +bool LocAdapterBase:: + reportKlobucharIonoModelEvent(GnssKlobucharIonoModel& /*ionoModel*/) +DEFAULT_IMPL(false) + +bool LocAdapterBase:: + reportGnssAdditionalSystemInfoEvent(GnssAdditionalSystemInfo& /*additionalSystemInfo*/) +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 e4f7be2..13c8493 100644 --- a/core/LocAdapterBase.h +++ b/core/LocAdapterBase.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2014, 2016-2018 The Linux Foundation. All rights reserved. +/* 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 @@ -34,6 +34,8 @@ #include <LocationAPI.h> #include <map> +#define MIN_TRACKING_INTERVAL (100) // 100 msec + typedef struct LocationSessionKey { LocationAPI* client; uint32_t id; @@ -49,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<LocationSessionKey, LocationOptions> LocationSessionMap; -typedef std::map<LocationSessionKey, TrackingOptions> TrackingOptionsMap; + +typedef void (*removeClientCompleteCallback)(LocationAPI* client); namespace loc_core { @@ -60,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; @@ -69,15 +73,25 @@ protected: inline LocAdapterBase(const MsgTask* msgTask) : mIsMaster(false), mEvtMask(0), mContext(NULL), mLocApi(NULL), mLocAdapterProxyBase(NULL), mMsgTask(msgTask) {} - LocAdapterBase(const LOC_API_ADAPTER_EVENT_MASK_T mask, - ContextBase* context, bool isMaster, - LocAdapterProxyBase *adapterProxyBase = NULL); + + /* ==== CLIENT ========================================================================= */ + typedef std::map<LocationAPI*, LocationCallbacks> ClientDataMap; + ClientDataMap mClientData; + std::vector<LocMsg*> 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); } - inline LocAdapterBase(const LOC_API_ADAPTER_EVENT_MASK_T mask, - ContextBase* context, - LocAdapterProxyBase *adapterProxyBase = NULL) : - LocAdapterBase(mask, context, false, adapterProxyBase) {} + LocAdapterBase(const LOC_API_ADAPTER_EVENT_MASK_T mask, + ContextBase* context, bool isMaster = false, + LocAdapterProxyBase *adapterProxyBase = NULL); inline LOC_API_ADAPTER_EVENT_MASK_T checkMask(LOC_API_ADAPTER_EVENT_MASK_T mask) const { @@ -128,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, @@ -145,7 +158,6 @@ public: bool fromEngineHub=false); virtual void reportDataEvent(const GnssDataNotification& dataNotify, int msInWeek); virtual void reportNmeaEvent(const char* nmea, size_t length); - virtual void reportSvMeasurementEvent(GnssSvMeasurementSet &svMeasurementSet); virtual void reportSvPolynomialEvent(GnssSvPolynomial &svPolynomial); virtual void reportSvEphemerisEvent(GnssSvEphemerisReport &svEphemeris); virtual void reportStatus(LocGpsStatusValue status); @@ -162,7 +174,7 @@ public: virtual bool requestNiNotifyEvent(const GnssNiNotification ¬ify, const void* data); inline virtual bool isInSession() { return false; } ContextBase* getContext() const { return mContext; } - virtual void reportGnssMeasurementDataEvent(const GnssMeasurementsNotification& measurements, + virtual void reportGnssMeasurementsEvent(const GnssMeasurements& gnssMeasurements, int msInWeek); virtual bool reportWwanZppFix(LocGpsLocation &zppLoc); virtual bool reportZppBestAvailableFix(LocGpsLocation &zppLoc, @@ -172,6 +184,32 @@ public: virtual bool requestOdcpiEvent(OdcpiRequestInfo& request); virtual bool reportGnssEngEnergyConsumedEvent(uint64_t energyConsumedSinceFirstBoot); virtual bool reportDeleteAidingDataEvent(GnssAidingData &aidingData); + virtual bool reportKlobucharIonoModelEvent(GnssKlobucharIonoModel& ionoModel); + 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/LocAdapterProxyBase.h b/core/LocAdapterProxyBase.h index b33d7b0..727d424 100644 --- a/core/LocAdapterProxyBase.h +++ b/core/LocAdapterProxyBase.h @@ -40,8 +40,8 @@ private: LocAdapterBase *mLocAdapterBase; protected: inline LocAdapterProxyBase(const LOC_API_ADAPTER_EVENT_MASK_T mask, - ContextBase* context): - mLocAdapterBase(new LocAdapterBase(mask, context, this)) { + ContextBase* context, bool isMaster = false): + mLocAdapterBase(new LocAdapterBase(mask, context, isMaster, this)) { } inline virtual ~LocAdapterProxyBase() { delete mLocAdapterBase; diff --git a/core/LocApiBase.cpp b/core/LocApiBase.cpp index c2ee411..c172376 100644 --- a/core/LocApiBase.cpp +++ b/core/LocApiBase.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2014, 2016-2018 The Linux Foundation. All rights reserved. +/* 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 @@ -31,10 +31,11 @@ #include <dlfcn.h> #include <inttypes.h> +#include <gps_extended_c.h> #include <LocApiBase.h> #include <LocAdapterBase.h> #include <log_util.h> -#include <LocDualContext.h> +#include <LocContext.h> namespace loc_core { @@ -95,7 +96,10 @@ struct LocSsrMsg : public LocMsg { } inline virtual void proc() const { mLocApi->close(); - mLocApi->open(mLocApi->getEvtMask()); + if (LOC_API_ADAPTER_ERR_SUCCESS == mLocApi->open(mLocApi->getEvtMask())) { + // Notify adapters that engine up after SSR + mLocApi->handleEngineUpEvent(); + } } inline void locallog() const { LOC_LOGV("LocSsrMsg"); @@ -107,13 +111,17 @@ struct LocSsrMsg : public LocMsg { struct LocOpenMsg : public LocMsg { LocApiBase* mLocApi; - inline LocOpenMsg(LocApiBase* locApi) : - LocMsg(), mLocApi(locApi) + LocAdapterBase* mAdapter; + inline LocOpenMsg(LocApiBase* locApi, LocAdapterBase* adapter = nullptr) : + LocMsg(), mLocApi(locApi), mAdapter(adapter) { locallog(); } inline virtual void proc() const { - mLocApi->open(mLocApi->getEvtMask()); + if (LOC_API_ADAPTER_ERR_SUCCESS == mLocApi->open(mLocApi->getEvtMask()) && + nullptr != mAdapter) { + mAdapter->handleEngineUpEvent(); + } } inline void locallog() const { LOC_LOGv("LocOpen Mask: %" PRIx64 "\n", mLocApi->getEvtMask()); @@ -189,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; @@ -222,7 +230,7 @@ void LocApiBase::addAdapter(LocAdapterBase* adapter) for (int i = 0; i < MAX_ADAPTERS && mLocAdapters[i] != adapter; i++) { if (mLocAdapters[i] == NULL) { mLocAdapters[i] = adapter; - mMsgTask->sendMsg(new LocOpenMsg(this)); + mMsgTask->sendMsg(new LocOpenMsg(this, adapter)); break; } } @@ -295,8 +303,6 @@ void LocApiBase::updateNmeaMask(uint32_t mask) void LocApiBase::handleEngineUpEvent() { - LocDualContext::injectFeatureConfig(mContext); - // loop through adapters, and deliver to all adapters. TO_ALL_LOCADAPTERS(mLocAdapters[i]->handleEngineUpEvent()); } @@ -374,6 +380,23 @@ void LocApiBase::reportDeleteAidingDataEvent(GnssAidingData& aidingData) { TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->reportDeleteAidingDataEvent(aidingData)); } +void LocApiBase::reportKlobucharIonoModel(GnssKlobucharIonoModel & ionoModel) { + // loop through adapters, and deliver to the first handling adapter. + TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->reportKlobucharIonoModelEvent(ionoModel)); +} + +void LocApiBase::reportGnssAdditionalSystemInfo(GnssAdditionalSystemInfo& additionalSystemInfo) { + // loop through adapters, and deliver to the first handling adapter. + TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->reportGnssAdditionalSystemInfoEvent( + additionalSystemInfo)); +} + +void LocApiBase::sendNfwNotification(GnssNfwNotification& notification) +{ + // loop through adapters, and deliver to the first handling adapter. + TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportNfwNotificationEvent(notification)); + +} void LocApiBase::reportSv(GnssSvNotification& svNotify) { @@ -411,14 +434,6 @@ void LocApiBase::reportSv(GnssSvNotification& svNotify) ); } -void LocApiBase::reportSvMeasurement(GnssSvMeasurementSet &svMeasurementSet) -{ - // loop through adapters, and deliver to all adapters. - TO_ALL_LOCADAPTERS( - mLocAdapters[i]->reportSvMeasurementEvent(svMeasurementSet) - ); -} - void LocApiBase::reportSvPolynomial(GnssSvPolynomial &svPolynomial) { // loop through adapters, and deliver to all adapters. @@ -511,11 +526,10 @@ void* LocApiBase :: getSibling() LocApiProxyBase* LocApiBase :: getLocApiProxy() DEFAULT_IMPL(NULL) -void LocApiBase::reportGnssMeasurementData(GnssMeasurementsNotification& measurements, - int msInWeek) +void LocApiBase::reportGnssMeasurements(GnssMeasurements& gnssMeasurements, int msInWeek) { // loop through adapters, and deliver to all adapters. - TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportGnssMeasurementDataEvent(measurements, msInWeek)); + TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportGnssMeasurementsEvent(gnssMeasurements, msInWeek)); } void LocApiBase::reportGnssSvIdConfig(const GnssSvIdConfig& config) @@ -540,6 +554,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) @@ -588,10 +637,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) @@ -667,6 +712,10 @@ DEFAULT_IMPL(0) GnssConfigLppeUserPlaneMask LocApiBase::convertLppeUp(const uint32_t /*lppeUserPlaneMask*/) DEFAULT_IMPL(0) +LocationError LocApiBase::setEmergencyExtensionWindowSync( + const uint32_t /*emergencyExtensionSeconds*/) +DEFAULT_IMPL(LOCATION_ERROR_SUCCESS) + void LocApiBase:: getWwanZppFix() DEFAULT_IMPL() @@ -721,7 +770,103 @@ LocationError LocApiBase:: setPositionAssistedClockEstimatorMode(bool /*enabled*/) DEFAULT_IMPL(LOCATION_ERROR_SUCCESS) -LocationError LocApiBase:: - getGnssEnergyConsumed() +LocationError LocApiBase::getGnssEnergyConsumed() DEFAULT_IMPL(LOCATION_ERROR_SUCCESS) + + +void LocApiBase::addGeofence(uint32_t /*clientId*/, const GeofenceOption& /*options*/, + const GeofenceInfo& /*info*/, + LocApiResponseData<LocApiGeofenceData>* /*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<LocApiBatchData>* /*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 e5dfebf..1c2afaf 100644 --- a/core/LocApiBase.h +++ b/core/LocApiBase.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2014, 2016-2018 The Linux Foundation. All rights reserved. +/* 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 @@ -40,6 +40,7 @@ namespace loc_core { class ContextBase; struct LocApiResponse; +template <typename> struct LocApiResponseData; int hexcode(char *hexstring, int string_size, const char *data, int data_size); @@ -163,7 +164,6 @@ public: GnssDataNotification* pDataNotify = nullptr, int msInWeek = -1); void reportSv(GnssSvNotification& svNotify); - void reportSvMeasurement(GnssSvMeasurementSet &svMeasurementSet); void reportSvPolynomial(GnssSvPolynomial &svPolynomial); void reportSvEphemeris(GnssSvEphemerisReport &svEphemeris); void reportStatus(LocGpsStatusValue status); @@ -178,7 +178,7 @@ public: void requestATL(int connHandle, LocAGpsType agps_type, LocApnTypeMask apn_type_mask); void releaseATL(int connHandle); void requestNiNotify(GnssNiNotification ¬ify, const void* data); - void reportGnssMeasurementData(GnssMeasurementsNotification& measurements, int msInWeek); + void reportGnssMeasurements(GnssMeasurements& gnssMeasurements, int msInWeek); void reportWwanZppFix(LocGpsLocation &zppLoc); void reportZppBestAvailableFix(LocGpsLocation &zppLoc, GpsLocationExtended &location_extended, LocPosTechMask tech_mask); @@ -187,102 +187,69 @@ public: void requestOdcpi(OdcpiRequestInfo& request); void reportGnssEngEnergyConsumedEvent(uint64_t energyConsumedSinceFirstBoot); void reportDeleteAidingDataEvent(GnssAidingData& aidingData); + void reportKlobucharIonoModel(GnssKlobucharIonoModel& ionoModel); + void reportGnssAdditionalSystemInfo(GnssAdditionalSystemInfo& additionalSystemInfo); + void sendNfwNotification(GnssNfwNotification& notification); + + 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 - // All below functions are to be defined by adapter specific modules: - // RPC, QMI, etc. The default implementation is empty. - 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); virtual GnssConfigLppProfile convertLppProfile(const uint32_t lppProfile); virtual GnssConfigLppeControlPlaneMask convertLppeCp(const uint32_t lppeControlPlaneMask); virtual GnssConfigLppeUserPlaneMask convertLppeUp(const uint32_t lppeUserPlaneMask); + virtual LocationError setEmergencyExtensionWindowSync(const uint32_t emergencyExtensionSeconds); 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); @@ -290,12 +257,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<LocApiGeofenceData>* 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<LocApiBatchData>* 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 0000000..18d3f2d --- /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 <cutils/sched_policy.h> +#include <unistd.h> +#include <LocContext.h> +#include <msg_q.h> +#include <log_util.h> +#include <loc_log.h> + +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 index 3b3ce2c..fb7d009 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 <stdbool.h> #include <ctype.h> @@ -36,36 +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* mInjectContext; + 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); @@ -73,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 180d9dc..0000000 --- a/core/LocDualContext.cpp +++ /dev/null @@ -1,150 +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 <cutils/sched_policy.h> -#include <unistd.h> -#include <LocDualContext.h> -#include <msg_q.h> -#include <log_util.h> -#include <loc_log.h> - -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; -ContextBase* LocDualContext::mInjectContext = 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); - } - if(NULL == mInjectContext) { - LOC_LOGD("%s:%d]: mInjectContext is FgContext", __func__, __LINE__); - mInjectContext = mFgContext; - injectFeatureConfig(mInjectContext); - } - 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); - } - if(NULL == mInjectContext) { - LOC_LOGD("%s:%d]: mInjectContext is BgContext", __func__, __LINE__); - mInjectContext = mBgContext; - injectFeatureConfig(mInjectContext); - } - pthread_mutex_unlock(&LocDualContext::mGetLocContextMutex); - - if (firstMsg) { - mBgContext->sendMsg(firstMsg); - } - - return mBgContext; -} - -void LocDualContext :: injectFeatureConfig(ContextBase *curContext) -{ - LOC_LOGD("%s:%d]: Enter", __func__, __LINE__); - if(curContext == mInjectContext) { - LOC_LOGD("%s:%d]: Calling LBSProxy (%p) to inject feature config", - __func__, __LINE__, ((LocDualContext *)mInjectContext)->mLBSProxy); - ((LocDualContext *)mInjectContext)->mLBSProxy->injectFeatureConfig(curContext); - } - LOC_LOGD("%s:%d]: Exit", __func__, __LINE__); -} - -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 53059e4..ffd9357 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/core/SystemStatus.cpp b/core/SystemStatus.cpp index f4316ca..6ef4993 100644 --- a/core/SystemStatus.cpp +++ b/core/SystemStatus.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 @@ -1682,10 +1682,12 @@ bool SystemStatus::setDefaultGnssEngineStates(void) @return true when successfully done ******************************************************************************/ -bool SystemStatus::eventConnectionStatus(bool connected, int8_t type) +bool SystemStatus::eventConnectionStatus(bool connected, int8_t type, + bool roaming, NetworkHandle networkHandle) { // send networkinof dataitem to systemstatus observer clients - SystemStatusNetworkInfo s(type, "", "", connected); + SystemStatusNetworkInfo s(type, "", "", connected, roaming, + (uint64_t) networkHandle); mSysStatusObsvr.notify({&s}); return true; diff --git a/core/SystemStatus.h b/core/SystemStatus.h index 9422322..73a220a 100644 --- a/core/SystemStatus.h +++ b/core/SystemStatus.h @@ -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 @@ -32,6 +32,8 @@ #include <stdint.h> #include <sys/time.h> #include <vector> +#include <algorithm> +#include <iterator> #include <loc_pla.h> #include <log_util.h> #include <MsgTask.h> @@ -467,7 +469,8 @@ public: std::string typeName="", string subTypeName="", bool connected=false, - bool roaming=false) : + bool roaming=false, + uint64_t networkHandle=NETWORK_HANDLE_UNKNOWN) : NetworkInfoDataItemBase( (NetworkType)type, type, @@ -475,7 +478,8 @@ public: subTypeName, connected && (!roaming), connected, - roaming), + roaming, + networkHandle), mSrcObjPtr(nullptr) {} inline SystemStatusNetworkInfo(const NetworkInfoDataItemBase& itemBase) : NetworkInfoDataItemBase(itemBase), @@ -487,16 +491,24 @@ public: } inline virtual SystemStatusItemBase& collate(SystemStatusItemBase& curInfo) { uint64_t allTypes = (static_cast<SystemStatusNetworkInfo&>(curInfo)).mAllTypes; + uint64_t networkHandle = + (static_cast<SystemStatusNetworkInfo&>(curInfo)).mNetworkHandle; + int32_t type = (static_cast<SystemStatusNetworkInfo&>(curInfo)).mType; if (mConnected) { mAllTypes |= allTypes; + mAllNetworkHandles[type] = networkHandle; } else if (0 != mAllTypes) { mAllTypes = (allTypes & (~mAllTypes)); + mAllNetworkHandles[type] = NETWORK_HANDLE_UNKNOWN; } // else (mConnected == false && mAllTypes == 0) // we keep mAllTypes as 0, which means no more connections. if (nullptr != mSrcObjPtr) { // this is critical, changing mAllTypes of the original obj mSrcObjPtr->mAllTypes = mAllTypes; + memcpy(mSrcObjPtr->mAllNetworkHandles, + mAllNetworkHandles, + sizeof(mSrcObjPtr->mAllNetworkHandles)); } return *this; } @@ -830,7 +842,8 @@ public: bool setNmeaString(const char *data, uint32_t len); bool getReport(SystemStatusReports& reports, bool isLatestonly = false) const; bool setDefaultGnssEngineStates(void); - bool eventConnectionStatus(bool connected, int8_t type); + bool eventConnectionStatus(bool connected, int8_t type, + bool roaming, NetworkHandle networkHandle); }; } // namespace loc_core diff --git a/core/data-items/DataItemConcreteTypesBase.h b/core/data-items/DataItemConcreteTypesBase.h index 44be5f9..552d46a 100644 --- a/core/data-items/DataItemConcreteTypesBase.h +++ b/core/data-items/DataItemConcreteTypesBase.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-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 @@ -34,6 +34,7 @@ #include <cstring> #include <DataItemId.h> #include <IDataItemCore.h> +#include <gps_extended_c.h> #define MAC_ADDRESS_LENGTH 6 // MAC address length in bytes @@ -222,7 +223,7 @@ protected: class NetworkInfoDataItemBase : public IDataItemCore { public: enum NetworkType { - TYPE_MOBILE, + TYPE_MOBILE = 0, TYPE_WIFI, TYPE_ETHERNET, TYPE_BLUETOOTH, @@ -236,7 +237,7 @@ public: }; NetworkInfoDataItemBase( NetworkType initialType, int32_t type, string typeName, string subTypeName, - bool available, bool connected, bool roaming ): + bool available, bool connected, bool roaming, uint64_t networkHandle ): mAllTypes(typeToAllTypes(initialType)), mType(type), mTypeName(typeName), @@ -244,7 +245,12 @@ public: mAvailable(available), mConnected(connected), mRoaming(roaming), - mId(NETWORKINFO_DATA_ITEM_ID) {} + mNetworkHandle(networkHandle), + mId(NETWORKINFO_DATA_ITEM_ID) { + memset (&mAllNetworkHandles, NETWORK_HANDLE_UNKNOWN, + sizeof (mAllNetworkHandles)); + mAllNetworkHandles[type] = networkHandle; + } virtual ~NetworkInfoDataItemBase() {} inline virtual DataItemId getId() { return mId; } virtual void stringify(string& /*valueStr*/) {} @@ -253,6 +259,9 @@ public: return (NetworkType)mType; } inline uint64_t getAllTypes() { return mAllTypes; } + inline uint64_t getNetworkHandle(NetworkType type) { + return mAllNetworkHandles[type]; + } // Data members uint64_t mAllTypes; int32_t mType; @@ -261,6 +270,8 @@ public: bool mAvailable; bool mConnected; bool mRoaming; + uint64_t mAllNetworkHandles[TYPE_UNKNOWN + 1]; + uint64_t mNetworkHandle; protected: DataItemId mId; inline uint64_t typeToAllTypes(NetworkType type) { diff --git a/etc/Android.mk b/etc/Android.mk index db59eed..32a0e9c 100644 --- a/etc/Android.mk +++ b/etc/Android.mk @@ -1,13 +1,22 @@ ifneq ($(BOARD_VENDOR_QCOM_LOC_PDK_FEATURE_SET),true) 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) endif diff --git a/etc/flp.conf b/etc/flp.conf new file mode 100644 index 0000000..65d54d3 --- /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 e5be385..82a7b3c 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 0000000..6e9e870 --- /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 0000000..b8746fb --- /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 <GeofenceAdapter.h> +#include "loc_log.h" +#include <log_util.h> +#include <string> + +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<LocApiGeofenceData>(*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<LocApiGeofenceData>(*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 0000000..38f4823 --- /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 <LocAdapterBase.h> +#include <LocContext.h> +#include <LocationAPI.h> +#include <map> + +using namespace loc_core; + +#define COPY_IF_NOT_NULL(dest, src, len) do { \ + if (NULL!=dest && NULL!=src) { \ + for (size_t i=0; i<len; ++i) { \ + dest[i] = src[i]; \ + } \ + } \ +} while (0) + +typedef struct GeofenceKey { + LocationAPI* client; + uint32_t id; + inline GeofenceKey() : + client(NULL), id(0) {} + inline GeofenceKey(LocationAPI* _client, uint32_t _id) : + client(_client), id(_id) {} +} GeofenceKey; +inline bool operator <(GeofenceKey const& left, GeofenceKey const& right) { + return left.id < right.id || (left.id == right.id && left.client < right.client); +} +inline bool operator ==(GeofenceKey const& left, GeofenceKey const& right) { + return left.id == right.id && left.client == right.client; +} +inline bool operator !=(GeofenceKey const& left, GeofenceKey const& right) { + return left.id != right.id || left.client != right.client; +} +typedef struct { + GeofenceKey key; + GeofenceBreachTypeMask breachMask; + uint32_t responsiveness; + uint32_t dwellTime; + double latitude; + double longitude; + double radius; + bool paused; +} GeofenceObject; +typedef std::map<uint32_t, GeofenceObject> GeofencesMap; //map of hwId to GeofenceObject +typedef std::map<GeofenceKey, uint32_t> 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 0000000..61883ff --- /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 0000000..8e3cd81 --- /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 0000000..6a0781f --- /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 0000000..66729f4 --- /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/Agps.cpp b/gnss/Agps.cpp index a4f6a30..9de1329 100644 --- a/gnss/Agps.cpp +++ b/gnss/Agps.cpp @@ -445,15 +445,14 @@ void AgpsStateMachine::setAPN(char* apn, unsigned int len){ if (NULL != mAPN) { delete mAPN; + mAPN = NULL; } - if (apn == NULL || len <= 0) { + if (NULL == apn || len <= 0 || len > MAX_APN_LEN || strlen(apn) != len) { LOC_LOGD("Invalid apn len (%d) or null apn", len); mAPN = NULL; mAPNLen = 0; - } - - if (NULL != apn) { + } else { mAPN = new char[len+1]; if (NULL != mAPN) { memcpy(mAPN, apn, len); diff --git a/gnss/GnssAdapter.cpp b/gnss/GnssAdapter.cpp index 016356b..3563ed0 100644 --- a/gnss/GnssAdapter.cpp +++ b/gnss/GnssAdapter.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 @@ -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,8 +88,13 @@ GnssAdapter::GnssAdapter() : mSystemStatus(SystemStatus::getInstance(mMsgTask)), mServerUrl(":"), mXtraObserver(mSystemStatus->getOsObserver(), mMsgTask), + mLocSystemInfo{}, mBlockCPIInfo{}, - mLocSystemInfo{} + mNfwCb(NULL), + mPowerOn(false), + mAllowFlpNetworkFixes(0), + mGnssEnergyConsumedCb(nullptr), + mPowerStateCb(nullptr) { LOC_LOGD("%s]: Constructor %p", __func__, this); mLocPositionMode.mode = LOC_POSITION_MODE_INVALID; @@ -428,37 +434,7 @@ GnssAdapter::convertLocationInfo(GnssLocationInfoNotification& out, } } -inline uint32_t -GnssAdapter::convertGpsLock(const GnssConfigGpsLock gpsLock) -{ - switch (gpsLock) { - case GNSS_CONFIG_GPS_LOCK_MO: - return 1; - case GNSS_CONFIG_GPS_LOCK_NI: - return 2; - case GNSS_CONFIG_GPS_LOCK_MO_AND_NI: - return 3; - case GNSS_CONFIG_GPS_LOCK_NONE: - default: - return 0; - } -} -inline GnssConfigGpsLock -GnssAdapter::convertGpsLock(const uint32_t gpsLock) -{ - switch (gpsLock) { - case 1: - return GNSS_CONFIG_GPS_LOCK_MO; - case 2: - return GNSS_CONFIG_GPS_LOCK_NI; - case 3: - return GNSS_CONFIG_GPS_LOCK_MO_AND_NI; - case 0: - default: - return GNSS_CONFIG_GPS_LOCK_NONE; - } -} inline uint32_t GnssAdapter::convertSuplVersion(const GnssConfigSuplVersion suplVersion) @@ -598,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); + } } }; @@ -654,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) { @@ -681,45 +673,36 @@ GnssAdapter::setConfigCommand() mApi.sendMsg(new LocApiMsg( [&adapter, gpsConf, sapConf, oldServerUrl, oldMoServerUrl] () { - - std::string serverUrl = adapter.getServerUrl(); - std::string moServerUrl = adapter.getMoServerUrl(); - int serverUrlLen = serverUrl.length(); - int moServerUrlLen = moServerUrl.length(); - - if (gpsConf.AGPS_CONFIG_INJECT) { - adapter.mLocApi->setSUPLVersionSync( - adapter.mLocApi->convertSuplVersion(gpsConf.SUPL_VER)); - adapter.mLocApi->setLPPConfigSync( - adapter.mLocApi->convertLppProfile(gpsConf.LPP_PROFILE)); - adapter.mLocApi->setAGLONASSProtocolSync( - gpsConf.A_GLONASS_POS_PROTOCOL_SELECT); + //cache the injected configuration with GnssConfigRequested struct + GnssConfig gnssConfigRequested = {}; + gnssConfigRequested.flags |= GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT | + GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT | + GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT | + GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT; + gnssConfigRequested.gpsLock = GNSS_CONFIG_GPS_LOCK_NONE; + if (0 == adapter.getAfwControlId() || NULL != adapter.mNfwCb) { + gnssConfigRequested.gpsLock = gpsConf.GPS_LOCK; } - if ((serverUrlLen !=0) && (oldServerUrl.compare(serverUrl) != 0)) { - LocationError locErr = - adapter.mLocApi->setServerSync(serverUrl.c_str(), serverUrlLen, - LOC_AGPS_SUPL_SERVER); - if (locErr != LOCATION_ERROR_SUCCESS) { - LOC_LOGe("Error while setting SUPL_HOST server:%s", - serverUrl.c_str()); - } - } - if ((moServerUrlLen != 0) && (oldMoServerUrl.compare(moServerUrl) != 0)) { - LocationError locErr = - adapter.mLocApi->setServerSync(moServerUrl.c_str(), - moServerUrlLen, - LOC_AGPS_MO_SUPL_SERVER); - if (locErr != LOCATION_ERROR_SUCCESS) { - LOC_LOGe("Error while setting MO SUPL_HOST server:%s", - moServerUrl.c_str()); - } + if (gpsConf.AGPS_CONFIG_INJECT) { + gnssConfigRequested.flags |= GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT | + GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT | + GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT; + gnssConfigRequested.suplVersion = + adapter.mLocApi->convertSuplVersion(gpsConf.SUPL_VER); + gnssConfigRequested.lppProfile = + adapter.mLocApi->convertLppProfile(gpsConf.LPP_PROFILE); + gnssConfigRequested.aGlonassPositionProtocolMask = + gpsConf.A_GLONASS_POS_PROTOCOL_SELECT; } - - adapter.mLocApi->setLPPeProtocolCpSync( - adapter.mLocApi->convertLppeCp(gpsConf.LPPE_CP_TECHNOLOGY)); - adapter.mLocApi->setLPPeProtocolUpSync( - adapter.mLocApi->convertLppeUp(gpsConf.LPPE_UP_TECHNOLOGY)); + gnssConfigRequested.lppeControlPlaneMask = + adapter.mLocApi->convertLppeCp(gpsConf.LPPE_CP_TECHNOLOGY); + gnssConfigRequested.lppeUserPlaneMask = + adapter.mLocApi->convertLppeUp(gpsConf.LPPE_UP_TECHNOLOGY); + gnssConfigRequested.blacklistedSvIds.assign(adapter.mBlacklistedSvIds.begin(), + adapter.mBlacklistedSvIds.end()); + adapter.gnssUpdateConfig(oldServerUrl, oldMoServerUrl, gnssConfigRequested, + gnssConfigRequested); // set nmea mask type uint32_t mask = 0; @@ -778,6 +761,192 @@ GnssAdapter::setConfigCommand() sendMsg(new MsgSetConfig(*this, *mLocApi)); } +std::vector<LocationError> GnssAdapter::gnssUpdateConfig(const std::string& oldServerUrl, + const std::string& oldMoServerUrl, const GnssConfig& gnssConfigRequested, + const GnssConfig& gnssConfigNeedEngineUpdate, size_t count) { + loc_gps_cfg_s gpsConf = ContextBase::mGps_conf; + size_t index = 0; + LocationError err = LOCATION_ERROR_SUCCESS; + std::vector<LocationError> errsList = {err}; + if (count > 0) { + errsList.insert(errsList.begin(), count, LOCATION_ERROR_SUCCESS); + } + + + std::string serverUrl = getServerUrl(); + std::string moServerUrl = getMoServerUrl(); + + int serverUrlLen = serverUrl.length(); + int moServerUrlLen = moServerUrl.length(); + + if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) { + if (gnssConfigNeedEngineUpdate.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) { + err = mLocApi->setGpsLockSync(gnssConfigRequested.gpsLock); + if (index < count) { + errsList[index] = err; + } + } + index++; + } + + if (gnssConfigRequested.flags & + GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) { + if (gnssConfigNeedEngineUpdate.flags & + GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) { + if (gnssConfigNeedEngineUpdate.assistanceServer.type == + GNSS_ASSISTANCE_TYPE_SUPL) { + if ((serverUrlLen != 0) && (oldServerUrl.compare(serverUrl) !=0)) { + + err = mLocApi->setServerSync( + serverUrl.c_str(), serverUrlLen, LOC_AGPS_SUPL_SERVER); + if (index < count) { + errsList[index] = err; + } + } + if ((moServerUrlLen != 0) && (oldMoServerUrl.compare(moServerUrl) != 0)) { + LocationError locErr = + mLocApi->setServerSync(moServerUrl.c_str(), + moServerUrlLen, + LOC_AGPS_MO_SUPL_SERVER); + if (locErr != LOCATION_ERROR_SUCCESS) { + LOC_LOGe("Error while setting MO SUPL_HOST server:%s", + moServerUrl.c_str()); + } + } + } else if (gnssConfigNeedEngineUpdate.assistanceServer.type == + GNSS_ASSISTANCE_TYPE_C2K) { + struct in_addr addr; + struct hostent* hp; + bool resolveAddrSuccess = true; + + hp = gethostbyname( + gnssConfigNeedEngineUpdate.assistanceServer.hostName); + if (hp != NULL) { /* DNS OK */ + memcpy(&addr, hp->h_addr_list[0], hp->h_length); + } else { + /* Try IP representation */ + if (inet_aton( + gnssConfigNeedEngineUpdate.assistanceServer.hostName, + &addr) == 0) { + /* IP not valid */ + LOC_LOGE("%s]: hostname '%s' cannot be resolved ", + __func__, + gnssConfigNeedEngineUpdate.assistanceServer.hostName); + if (index < count) { + errsList[index] = LOCATION_ERROR_INVALID_PARAMETER; + } + } else { + resolveAddrSuccess = false; + } + } + + if (resolveAddrSuccess) { + unsigned int ip = htonl(addr.s_addr); + err = mLocApi->setServerSync(ip, + gnssConfigNeedEngineUpdate.assistanceServer.port, + LOC_AGPS_CDMA_PDE_SERVER); + if (index < count) { + errsList[index] = err; + } + } + } + } + index++; + } + + if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) { + if (gnssConfigNeedEngineUpdate.flags & + GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) { + err = mLocApi->setSUPLVersionSync(gnssConfigRequested.suplVersion); + if (index < count) { + errsList[index] = err; + } + } + index++; + } + + if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) { + if (gnssConfigNeedEngineUpdate.flags & + GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) { + err = mLocApi->setLPPConfigSync(gnssConfigRequested.lppProfile); + if (index < count) { + errsList[index] = err; + } + } + index++; + } + + if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) { + if (gnssConfigNeedEngineUpdate.flags & + GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) { + err = mLocApi->setLPPeProtocolCpSync( + gnssConfigRequested.lppeControlPlaneMask); + if (index < count) { + errsList[index] = err; + } + } + index++; + } + + if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) { + if (gnssConfigNeedEngineUpdate.flags & + GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) { + err = mLocApi->setLPPeProtocolUpSync( + gnssConfigRequested.lppeUserPlaneMask); + if (index < count) { + errsList[index] = err; + } + } + index++; + } + + if (gnssConfigRequested.flags & + GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) { + if (gnssConfigNeedEngineUpdate.flags & + GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) { + err = mLocApi->setAGLONASSProtocolSync( + gnssConfigRequested.aGlonassPositionProtocolMask); + if (index < count) { + errsList[index] = err; + } + } + index++; + } + if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT) { + // Check if feature is supported + if (!ContextBase::isFeatureSupported( + LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) { + LOC_LOGe("Feature constellation enablement not supported."); + err = LOCATION_ERROR_NOT_SUPPORTED; + } else { + // Send the SV ID Config to Modem + mBlacklistedSvIds.assign(gnssConfigRequested.blacklistedSvIds.begin(), + gnssConfigRequested.blacklistedSvIds.end()); + err = gnssSvIdConfigUpdateSync(gnssConfigRequested.blacklistedSvIds); + if (LOCATION_ERROR_SUCCESS != err) { + LOC_LOGe("Failed to send config to modem, err %d", err); + } + } + if (index < count) { + errsList[index] = err; + } + index++; + } + if (gnssConfigRequested.flags & + GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT) { + if (gnssConfigNeedEngineUpdate.flags & + GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT) { + err = mLocApi->setEmergencyExtensionWindowSync( + gnssConfigRequested.emergencyExtensionSeconds); + if (index < count) { + errsList[index] = err; + } + } + index++; + } + return errsList; +} + uint32_t* GnssAdapter::gnssUpdateConfigCommand(GnssConfig config) { @@ -832,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; @@ -845,14 +1017,15 @@ GnssAdapter::gnssUpdateConfigCommand(GnssConfig config) int index = 0; if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) { - uint32_t newGpsLock = mAdapter.convertGpsLock(gnssConfigRequested.gpsLock); - ContextBase::mGps_conf.GPS_LOCK = newGpsLock; - if (0 == ContextBase::mGps_conf.GPS_LOCK) { - ContextBase::mGps_conf.GPS_LOCK = 3; + GnssConfigGpsLock newGpsLock = gnssConfigRequested.gpsLock; + if (GNSS_CONFIG_GPS_LOCK_NONE == newGpsLock) { + newGpsLock = GNSS_CONFIG_GPS_LOCK_MO; } - if (0 != mAdapter.getPowerVoteId()) { + if (newGpsLock == ContextBase::mGps_conf.GPS_LOCK || + 0 != mAdapter.getAfwControlId()) { gnssConfigNeedEngineUpdate.flags &= ~(GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT); } + ContextBase::mGps_conf.GPS_LOCK = newGpsLock; index++; } if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) { @@ -924,24 +1097,24 @@ GnssAdapter::gnssUpdateConfigCommand(GnssConfig config) ~(GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT); } index++; - } - if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) { + } + if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) { uint32_t newEP4ES = mAdapter.convertEP4ES( gnssConfigRequested.emergencyPdnForEmergencySupl); if (newEP4ES != ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL) { ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL = newEP4ES; } index++; - } - if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) { + } + if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) { uint32_t newSuplEs = mAdapter.convertSuplEs( gnssConfigRequested.suplEmergencyServices); if (newSuplEs != ContextBase::mGps_conf.SUPL_ES) { ContextBase::mGps_conf.SUPL_ES = newSuplEs; } index++; - } - if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) { + } + if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) { uint32_t newSuplMode = mAdapter.convertSuplMode(gnssConfigRequested.suplModeMask); if (newSuplMode != ContextBase::mGps_conf.SUPL_MODE) { ContextBase::mGps_conf.SUPL_MODE = newSuplMode; @@ -961,148 +1134,11 @@ GnssAdapter::gnssUpdateConfigCommand(GnssConfig config) mApi.sendMsg(new LocApiMsg( [&adapter, gnssConfigRequested, gnssConfigNeedEngineUpdate, countOfConfigs, configCollectiveResponse, errs, oldServerUrl] () { - - size_t index = 0; - LocationError err = LOCATION_ERROR_SUCCESS; - std::vector<LocationError> errsList(errs); - std::string serverUrl = adapter.getServerUrl(); int serverUrlLen = serverUrl.length(); + std::vector<LocationError> errsList = adapter.gnssUpdateConfig(oldServerUrl, + "", gnssConfigRequested, gnssConfigNeedEngineUpdate, countOfConfigs); - if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) { - if (gnssConfigNeedEngineUpdate.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) { - err = adapter.mLocApi->setGpsLockSync(gnssConfigRequested.gpsLock); - if (index < countOfConfigs) { - errsList[index] = err; - } - } - index++; - } - if (gnssConfigRequested.flags & - GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) { - if (gnssConfigNeedEngineUpdate.flags & - GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) { - if (gnssConfigNeedEngineUpdate.assistanceServer.type == - GNSS_ASSISTANCE_TYPE_SUPL) { - if ((serverUrlLen != 0) && (oldServerUrl.compare(serverUrl) !=0)) { - err = adapter.mLocApi->setServerSync( - serverUrl.c_str(), serverUrlLen, LOC_AGPS_SUPL_SERVER); - if (index < countOfConfigs) { - errsList[index] = err; - } - } - } else if (gnssConfigNeedEngineUpdate.assistanceServer.type == - GNSS_ASSISTANCE_TYPE_C2K) { - struct in_addr addr; - struct hostent* hp; - bool resolveAddrSuccess = true; - - hp = gethostbyname( - gnssConfigNeedEngineUpdate.assistanceServer.hostName); - if (hp != NULL) { /* DNS OK */ - memcpy(&addr, hp->h_addr_list[0], hp->h_length); - } else { - /* Try IP representation */ - if (inet_aton( - gnssConfigNeedEngineUpdate.assistanceServer.hostName, - &addr) == 0) { - /* IP not valid */ - LOC_LOGE("%s]: hostname '%s' cannot be resolved ", - __func__, - gnssConfigNeedEngineUpdate.assistanceServer.hostName); - if (index < countOfConfigs) { - errsList[index] = LOCATION_ERROR_INVALID_PARAMETER; - } - } else { - resolveAddrSuccess = false; - } - } - - if (resolveAddrSuccess) { - unsigned int ip = htonl(addr.s_addr); - err = adapter.mLocApi->setServerSync(ip, - gnssConfigNeedEngineUpdate.assistanceServer.port, - LOC_AGPS_CDMA_PDE_SERVER); - if (index < countOfConfigs) { - errsList[index] = err; - } - } - } - } - index++; - } - if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) { - if (gnssConfigNeedEngineUpdate.flags & - GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) { - err = adapter.mLocApi->setSUPLVersionSync(gnssConfigRequested.suplVersion); - if (index < countOfConfigs) { - errsList[index] = err; - } - } - index++; - } - if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) { - if (gnssConfigNeedEngineUpdate.flags & - GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) { - err = adapter.mLocApi->setLPPConfigSync(gnssConfigRequested.lppProfile); - if (index < countOfConfigs) { - errsList[index] = err; - } - } - index++; - } - if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) { - if (gnssConfigNeedEngineUpdate.flags & - GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) { - err = adapter.mLocApi->setLPPeProtocolCpSync( - gnssConfigRequested.lppeControlPlaneMask); - if (index < countOfConfigs) { - errsList[index] = err; - } - } - index++; - } - if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) { - if (gnssConfigNeedEngineUpdate.flags & - GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) { - err = adapter.mLocApi->setLPPeProtocolUpSync( - gnssConfigRequested.lppeUserPlaneMask); - if (index < countOfConfigs) { - errsList[index] = err; - } - } - index++; - } - if (gnssConfigRequested.flags & - GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) { - if (gnssConfigNeedEngineUpdate.flags & - GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) { - err = adapter.mLocApi->setAGLONASSProtocolSync( - gnssConfigRequested.aGlonassPositionProtocolMask); - if (index < countOfConfigs) { - errsList[index] = err; - } - } - index++; - } - if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT) { - // Check if feature is supported - if (!ContextBase::isFeatureSupported( - LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) { - LOC_LOGe("Feature constellation enablement not supported."); - err = LOCATION_ERROR_NOT_SUPPORTED; - } else { - // Send the SV ID Config to Modem - err = adapter.gnssSvIdConfigUpdateSync(gnssConfigRequested.blacklistedSvIds); - if (LOCATION_ERROR_SUCCESS != err) { - LOC_LOGe("Failed to send config to modem, err %d", err); - } - } - if (index < countOfConfigs) { - errsList[index] = err; - } - index++; - } configCollectiveResponse->returnToSender(errsList); })); } @@ -1224,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; @@ -1300,6 +1339,12 @@ GnssAdapter::gnssGetConfigCommand(GnssConfigFlagsMask configMask) { errs[index++] = err; } } + if (mConfigMask & GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT) { + err = LOCATION_ERROR_NOT_SUPPORTED; + if (index < mCount) { + errs[index++] = LOCATION_ERROR_NOT_SUPPORTED; + } + } mAdapter.reportResponse(index, errs, mIds); delete[] errs; @@ -1493,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)) { @@ -1583,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."); @@ -1612,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."); @@ -1859,43 +1913,32 @@ GnssAdapter::addClientCommand(LocationAPI* client, const LocationCallbacks& call } void -GnssAdapter::removeClientCommand(LocationAPI* client, - removeClientCompleteCallback rmClientCb) +GnssAdapter::stopClientSessions(LocationAPI* client) { 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); - } + /* Time-based Tracking */ + std::vector<LocationSessionKey> vTimeBasedTrackingClient; + for (auto it : mTimeBasedTrackingSessions) { + if (client == it.first.client) { + vTimeBasedTrackingClient.emplace_back(it.first.client, it.first.id); } - }; - - sendMsg(new MsgRemoveClient(*this, client, rmClientCb)); -} + } + for (auto key : vTimeBasedTrackingClient) { + stopTimeBasedTrackingMultiplex(key.client, key.id); + } -void -GnssAdapter::stopClientSessions(LocationAPI* client) -{ - LOC_LOGD("%s]: client %p", __func__, client); - for (auto it = mTrackingSessions.begin(); it != mTrackingSessions.end();) { + /* 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 } @@ -1938,10 +1981,12 @@ GnssAdapter::updateClientsEventMask() if((1 == ContextBase::mGps_conf.EXTERNAL_DR_ENABLED) || (true == initEngHubProxy())) { mask |= LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT; + mask |= LOC_API_ADAPTER_BIT_GNSS_NHZ_MEASUREMENT; mask |= LOC_API_ADAPTER_BIT_GNSS_SV_POLYNOMIAL_REPORT; mask |= LOC_API_ADAPTER_BIT_PARSED_UNPROPAGATED_POSITION_REPORT; mask |= LOC_API_ADAPTER_BIT_GNSS_SV_EPHEMERIS_REPORT; mask |= LOC_API_ADAPTER_BIT_LOC_SYSTEM_INFO; + mask |= LOC_API_ADAPTER_BIT_EVENT_REPORT_INFO; LOC_LOGd("Auto usecase, Enable MEAS/POLY/EPHEMERIS - mask 0x%" PRIx64 "", mask); @@ -1973,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(); } }; @@ -1994,130 +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 = {}; - 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)); - } -} - -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; - } - 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); - } + highestPowerTrackingOptions.setLocationOptions(smallestIntervalOptions); + mLocApi->startTimeBasedTracking(highestPowerTrackingOptions, nullptr); } -} -LocationCallbacks -GnssAdapter::getClientCallbacks(LocationAPI* client) -{ - LocationCallbacks callbacks = {}; - auto it = mClientData.find(client); - if (it != mClientData.end()) { - callbacks = it->second; + for (auto it = mDistanceBasedTrackingSessions.begin(); + it != mDistanceBasedTrackingSessions.end(); ++it) { + mLocApi->startDistanceBasedTracking(it->first.id, it->second, + new LocApiResponse(*getContext(), + [] (LocationError /*err*/) {})); } - return callbacks; -} - -void -GnssAdapter::saveClient(LocationAPI* client, const LocationCallbacks& callbacks) -{ - mClientData[client] = callbacks; - updateClientsEventMask(); } void @@ -2149,21 +2105,25 @@ GnssAdapter::notifyClientOfCachedLocationSystemInfo( } } -void -GnssAdapter::eraseClient(LocationAPI* client) +bool +GnssAdapter::hasTrackingCallback(LocationAPI* client) { auto it = mClientData.find(client); - if (it != mClientData.end()) { - mClientData.erase(it); - } - updateClientsEventMask(); + return (it != mClientData.end() && (it->second.trackingCb || it->second.gnssLocationInfoCb)); } bool -GnssAdapter::hasTrackingCallback(LocationAPI* client) +GnssAdapter::isTimeBasedTrackingSession(LocationAPI* client, uint32_t sessionId) { - auto it = mClientData.find(client); - return (it != mClientData.end() && (it->second.trackingCb || it->second.gnssLocationInfoCb)); + 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 @@ -2177,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; @@ -2271,45 +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; - } - // 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); + } } } } @@ -2321,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 { @@ -2335,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) { @@ -2361,7 +2386,8 @@ 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; } @@ -2372,9 +2398,13 @@ 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); + LocPosMode locPosMode = {}; convertOptions(locPosMode, trackingOptions); @@ -2382,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); @@ -2404,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 @@ -2417,35 +2447,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) { @@ -2457,49 +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; + // 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.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, mTrackingOptions); - mAdapter.saveTrackingSession(mClient, mSessionId, mTrackingOptions); + 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 } }; @@ -2514,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 || @@ -2553,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; } @@ -2588,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); - - if (reportToClientWithNoWait) { - mAdapter.reportResponse(mClient, LOCATION_ERROR_SUCCESS, 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); + } + } 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 + } }; @@ -2608,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; @@ -2620,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 || @@ -2646,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; } @@ -2765,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); } }; @@ -2799,21 +2875,24 @@ GnssAdapter::enableCommand(LocationTechnologyType techType) mTechType(techType) {} inline virtual void proc() const { LocationError err = LOCATION_ERROR_SUCCESS; - uint32_t powerVoteId = mAdapter.getPowerVoteId(); + uint32_t powerVoteId = mAdapter.getAfwControlId(); if (mTechType != LOCATION_TECHNOLOGY_TYPE_GNSS) { err = LOCATION_ERROR_INVALID_PARAMETER; } else if (powerVoteId > 0) { err = LOCATION_ERROR_ALREADY_STARTED; } else { mContext.modemPowerVote(true); - mAdapter.setPowerVoteId(mSessionId); + mAdapter.setAfwControlId(mSessionId); - mApi.sendMsg(new LocApiMsg([&mApi = mApi] () { - mApi.setGpsLockSync(GNSS_CONFIG_GPS_LOCK_NONE); - })); - - mAdapter.mXtraObserver.updateLockStatus( - mAdapter.convertGpsLock(GNSS_CONFIG_GPS_LOCK_NONE)); + GnssConfigGpsLock gpsLock = GNSS_CONFIG_GPS_LOCK_NONE; + if (NULL != mAdapter.mNfwCb) { + ContextBase::mGps_conf.GPS_LOCK &= GNSS_CONFIG_GPS_LOCK_NI; + gpsLock = ContextBase::mGps_conf.GPS_LOCK; + } + mApi.sendMsg(new LocApiMsg([&mApi = mApi, gpsLock]() { + mApi.setGpsLockSync(gpsLock); + })); + mAdapter.mXtraObserver.updateLockStatus(gpsLock); } mAdapter.reportResponse(err, mSessionId); } @@ -2849,20 +2928,23 @@ GnssAdapter::disableCommand(uint32_t id) mSessionId(sessionId) {} inline virtual void proc() const { LocationError err = LOCATION_ERROR_SUCCESS; - uint32_t powerVoteId = mAdapter.getPowerVoteId(); + uint32_t powerVoteId = mAdapter.getAfwControlId(); if (powerVoteId != mSessionId) { err = LOCATION_ERROR_ID_UNKNOWN; } else { mContext.modemPowerVote(false); - mAdapter.setPowerVoteId(0); + mAdapter.setAfwControlId(0); - GnssConfigGpsLock gpsLock = - mAdapter.convertGpsLock(ContextBase::mGps_conf.GPS_LOCK); + if (NULL != mAdapter.mNfwCb) { + /* We need to disable MO (AFW) */ + ContextBase::mGps_conf.GPS_LOCK |= GNSS_CONFIG_GPS_LOCK_MO; + } + GnssConfigGpsLock gpsLock = ContextBase::mGps_conf.GPS_LOCK; mApi.sendMsg(new LocApiMsg([&mApi = mApi,gpsLock] () { mApi.setGpsLockSync(gpsLock); })); mAdapter.mXtraObserver.updateLockStatus( - mAdapter.convertGpsLock(ContextBase::mGps_conf.GPS_LOCK)); + ContextBase::mGps_conf.GPS_LOCK); } mAdapter.reportResponse(err, mSessionId); } @@ -2962,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, @@ -2977,53 +3059,83 @@ 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<std::string> nmeaArraystr; loc_nmea_generate_pos(ulpLocation, locationExtended, mLocSystemInfo, generate_nmea, nmeaArraystr); stringstream ss; - for (auto sentence : nmeaArraystr) { - ss << sentence; + for (auto itor = nmeaArraystr.begin(); itor != nmeaArraystr.end(); ++itor) { + ss << *itor; } string s = ss.str(); reportNmea(s.c_str(), s.length()); @@ -3114,12 +3226,13 @@ 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<std::string> nmeaArraystr; loc_nmea_generate_sv(svNotify, nmeaArraystr); stringstream ss; - for (auto sentence : nmeaArraystr) { - ss << sentence; + for (auto itor = nmeaArraystr.begin(); itor != nmeaArraystr.end(); ++itor) { + ss << *itor; } string s = ss.str(); reportNmea(s.c_str(), s.length()); @@ -3309,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; @@ -3462,20 +3575,21 @@ GnssAdapter::requestNiNotify(const GnssNiNotification& notify, const void* data) } void -GnssAdapter::reportGnssMeasurementDataEvent(const GnssMeasurementsNotification& measurements, +GnssAdapter::reportGnssMeasurementsEvent(const GnssMeasurements& gnssMeasurements, int msInWeek) { LOC_LOGD("%s]: msInWeek=%d", __func__, msInWeek); struct MsgReportGnssMeasurementData : public LocMsg { GnssAdapter& mAdapter; + GnssMeasurements mGnssMeasurements; GnssMeasurementsNotification mMeasurementsNotify; inline MsgReportGnssMeasurementData(GnssAdapter& adapter, - const GnssMeasurementsNotification& measurements, + const GnssMeasurements& gnssMeasurements, int msInWeek) : LocMsg(), mAdapter(adapter), - mMeasurementsNotify(measurements) { + mMeasurementsNotify(gnssMeasurements.gnssMeasNotification) { if (-1 != msInWeek) { mAdapter.getAgcInformation(mMeasurementsNotify, msInWeek); } @@ -3485,7 +3599,8 @@ GnssAdapter::reportGnssMeasurementDataEvent(const GnssMeasurementsNotification& } }; - sendMsg(new MsgReportGnssMeasurementData(*this, measurements, msInWeek)); + sendMsg(new MsgReportGnssMeasurementData(*this, gnssMeasurements, msInWeek)); + mEngHubProxy->gnssReportSvMeasurement(gnssMeasurements.gnssSvMeasurementSet); } void @@ -3499,13 +3614,6 @@ GnssAdapter::reportGnssMeasurementData(const GnssMeasurementsNotification& measu } void -GnssAdapter::reportSvMeasurementEvent(GnssSvMeasurementSet &svMeasurementSet) -{ - LOC_LOGD("%s]: ", __func__); - mEngHubProxy->gnssReportSvMeasurement(svMeasurementSet); -} - -void GnssAdapter::reportSvPolynomialEvent(GnssSvPolynomial &svPolynomial) { LOC_LOGD("%s]: ", __func__); @@ -3587,24 +3695,24 @@ void GnssAdapter::requestOdcpi(const OdcpiRequestInfo& request) bool GnssAdapter::reportDeleteAidingDataEvent(GnssAidingData& aidingData) { LOC_LOGD("%s]:", __func__); + mEngHubProxy->gnssDeleteAidingData(aidingData); + return true; +} - struct MsgHandleDeleteAidingDataEvent : public LocMsg { - GnssAdapter& mAdapter; - GnssAidingData mData; - inline MsgHandleDeleteAidingDataEvent(GnssAdapter& adapter, - GnssAidingData& data) : - LocMsg(), - mAdapter(adapter), - mData(data) {} - inline virtual void proc() const { - mAdapter.mEngHubProxy->gnssDeleteAidingData(mData); - } - }; - - sendMsg(new MsgHandleDeleteAidingDataEvent(*this, aidingData)); +bool GnssAdapter::reportKlobucharIonoModelEvent(GnssKlobucharIonoModel & ionoModel) +{ + LOC_LOGD("%s]:", __func__); + mEngHubProxy->gnssReportKlobucharIonoModel(ionoModel); return true; } +bool GnssAdapter::reportGnssAdditionalSystemInfoEvent( + GnssAdditionalSystemInfo & additionalSystemInfo) +{ + LOC_LOGD("%s]:", __func__); + mEngHubProxy->gnssReportAdditionalSystemInfo(additionalSystemInfo); + return true; +} void GnssAdapter::initOdcpiCommand(const OdcpiRequestCallback& callback) { @@ -3821,6 +3929,52 @@ void GnssAdapter::initAgpsCommand(const AgpsCbInfo& cbInfo){ sendMsg(new AgpsMsgInit(cbInfo, *this)); } +void GnssAdapter::initNfwCommand(const NfwCbInfo& cbInfo) { + LOC_LOGi("GnssAdapter::initNfwCommand"); + + /* Message to initialize NFW */ + struct MsgInitNfw : public LocMsg { + const NfwCbInfo mCbInfo; + GnssAdapter& mAdapter; + + inline MsgInitNfw(const NfwCbInfo& cbInfo, + GnssAdapter& adapter) : + LocMsg(), mCbInfo(cbInfo), mAdapter(adapter) { + LOC_LOGv("MsgInitNfw"); + } + + inline virtual void proc() const { + LOC_LOGv("MsgInitNfw::proc()"); + mAdapter.initNfw(mCbInfo); + } + }; + + /* Send message to initialize NFW */ + sendMsg(new MsgInitNfw(cbInfo, *this)); +} + +void GnssAdapter::reportNfwNotificationEvent(GnssNfwNotification& notification) { + LOC_LOGi("GnssAdapter::reportNfwNotificationEvent"); + + struct MsgReportNfwNotification : public LocMsg { + const GnssNfwNotification mNotification; + GnssAdapter& mAdapter; + + inline MsgReportNfwNotification(const GnssNfwNotification& notification, + GnssAdapter& adapter) : + LocMsg(), mNotification(notification), mAdapter(adapter) { + LOC_LOGv("MsgReportNfwNotification"); + } + + inline virtual void proc() const { + LOC_LOGv("MsgReportNfwNotification::proc()"); + mAdapter.reportNfwNotification(mNotification); + } + }; + + sendMsg(new MsgReportNfwNotification(notification, *this)); +} + /* GnssAdapter::requestATL * Method triggered in QMI thread as part of handling below message: * eQMI_LOC_SERVER_REQUEST_OPEN_V02 @@ -3895,6 +4049,8 @@ void GnssAdapter::dataConnOpenCommand( LOC_LOGV("AgpsMsgAtlOpenSuccess"); if (mApnName == nullptr) { LOC_LOGE("%s] new allocation failed, fatal error.", __func__); + // Reporting the failure here + mAgpsManager->reportAtlClosed(mAgpsType); return; } memcpy(mApnName, apnName, apnLen); @@ -3911,9 +4067,15 @@ void GnssAdapter::dataConnOpenCommand( mAgpsManager->reportAtlOpenSuccess(mAgpsType, mApnName, mApnLen, mBearerType); } }; - - sendMsg( new AgpsMsgAtlOpenSuccess( - &mAgpsManager, agpsType, apnName, apnLen, bearerType)); + // Added inital length checks for apnlen check to avoid security issues + // In case of failure reporting the same + if (NULL == apnName || apnLen <= 0 || apnLen > MAX_APN_LEN || (strlen(apnName) != apnLen)) { + LOC_LOGe("%s]: incorrect apnlen length or incorrect apnName", __func__); + mAgpsManager.reportAtlClosed(agpsType); + } else { + sendMsg( new AgpsMsgAtlOpenSuccess( + &mAgpsManager, agpsType, apnName, apnLen, bearerType)); + } } void GnssAdapter::dataConnClosedCommand(AGpsExtType agpsType){ @@ -4402,6 +4564,37 @@ GnssAdapter::getGnssEnergyConsumedCommand(GnssEnergyConsumedCallback energyConsu sendMsg(new MsgGetGnssEnergyConsumed(*this, *mLocApi, energyConsumedCb)); } +void +GnssAdapter::nfwControlCommand(bool enable) { + struct MsgenableNfwLocationAccess : public LocMsg { + GnssAdapter& mAdapter; + LocApiBase& mApi; + bool mEnable; + inline MsgenableNfwLocationAccess(GnssAdapter& adapter, LocApiBase& api, + bool enable) : + LocMsg(), + mAdapter(adapter), + mApi(api), + mEnable(enable) {} + inline virtual void proc() const { + GnssConfigGpsLock gpsLock; + + gpsLock = ContextBase::mGps_conf.GPS_LOCK; + if (mEnable) { + gpsLock &= ~GNSS_CONFIG_GPS_LOCK_NI; + } else { + gpsLock |= GNSS_CONFIG_GPS_LOCK_NI; + } + ContextBase::mGps_conf.GPS_LOCK = gpsLock; + mApi.sendMsg(new LocApiMsg([&mApi = mApi, gpsLock]() { + mApi.setGpsLockSync((GnssConfigGpsLock)gpsLock); + })); + } + }; + + sendMsg(new MsgenableNfwLocationAccess(*this, *mLocApi, enable)); +} + /* ==== Eng Hub Proxy ================================================================= */ /* ======== UTILITIES ================================================================= */ void diff --git a/gnss/GnssAdapter.h b/gnss/GnssAdapter.h index 1682f02..9720ba4 100644 --- a/gnss/GnssAdapter.h +++ b/gnss/GnssAdapter.h @@ -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 @@ -30,13 +30,14 @@ #define GNSS_ADAPTER_H #include <LocAdapterBase.h> -#include <LocDualContext.h> +#include <LocContext.h> #include <IOsObserver.h> #include <EngineHubProxyBase.h> #include <LocationAPI.h> #include <Agps.h> #include <SystemStatus.h> #include <XtraSystemStatusObserver.h> +#include <map> #define MAX_URL_LEN 256 #define NMEA_SENTENCE_MAX_LENGTH 200 @@ -48,6 +49,9 @@ class GnssAdapter; +typedef std::map<LocationSessionKey, LocationOptions> LocationSessionMap; +typedef std::map<LocationSessionKey, TrackingOptions> TrackingOptionsMap; + class OdcpiTimer : public LocTimer { public: OdcpiTimer(GnssAdapter* adapter) : @@ -128,19 +132,16 @@ typedef std::function<void( uint64_t gnssEnergyConsumedFromFirstBoot )> GnssEnergyConsumedCallback; -typedef void (*removeClientCompleteCallback)(LocationAPI* client); +typedef void (*powerStateCallback)(bool on); class GnssAdapter : public LocAdapterBase { /* ==== Engine Hub ===================================================================== */ EngineHubProxyBase* mEngHubProxy; - /* ==== CLIENT ========================================================================= */ - typedef std::map<LocationAPI*, LocationCallbacks> ClientDataMap; - ClientDataMap mClientData; - /* ==== TRACKING ======================================================================= */ - TrackingOptionsMap mTrackingSessions; + TrackingOptionsMap mTimeBasedTrackingSessions; + LocationSessionMap mDistanceBasedTrackingSessions; LocPosMode mLocPositionMode; GnssSvUsedInPosition mGnssSvIdUsedInPosition; bool mGnssSvIdUsedInPosAvail; @@ -162,6 +163,12 @@ class GnssAdapter : public LocAdapterBase { AgpsCbInfo mAgpsCbInfo; void initAgps(const AgpsCbInfo& cbInfo); + /* ==== NFW =========================================================================== */ + NfwStatusCb mNfwCb; + inline void initNfw(const NfwCbInfo& cbInfo) { + mNfwCb = (NfwStatusCb)cbInfo.visibilityControlCb; + } + /* ==== ODCPI ========================================================================== */ OdcpiRequestCallback mOdcpiRequestCb; bool mOdcpiRequestActive; @@ -175,12 +182,16 @@ class GnssAdapter : public LocAdapterBase { std::string mMoServerUrl; XtraSystemStatusObserver mXtraObserver; LocationSystemInfo mLocSystemInfo; + std::vector<GnssSvIdSource> mBlacklistedSvIds; /* === 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); @@ -193,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: @@ -207,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)==================================== */ @@ -230,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, @@ -244,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)==================================== */ @@ -278,6 +283,9 @@ public: uint32_t gnssDeleteAidingDataCommand(GnssAidingData& data); void deleteAidingData(const GnssAidingData &data, uint32_t sessionId); void gnssUpdateXtraThrottleCommand(const bool enabled); + std::vector<LocationError> gnssUpdateConfig(const std::string& oldServerUrl, + const std::string& oldMoServerUrl, const GnssConfig& gnssConfigRequested, + const GnssConfig& gnssConfigNeedEngineUpdate, size_t count = 0); /* ==== GNSS SV TYPE CONFIG ============================================================ */ /* ==== COMMANDS ====(Called from Client Thread)======================================== */ @@ -304,11 +312,13 @@ public: /* ======== COMMANDS ====(Called from Client Thread)==================================== */ void initDefaultAgpsCommand(); void initAgpsCommand(const AgpsCbInfo& cbInfo); + void initNfwCommand(const NfwCbInfo& cbInfo); void dataConnOpenCommand(AGpsExtType agpsType, const char* apnName, int apnLen, AGpsBearerType bearerType); void dataConnClosedCommand(AGpsExtType agpsType); void dataConnFailedCommand(AGpsExtType agpsType); void getGnssEnergyConsumedCommand(GnssEnergyConsumedCallback energyConsumedCb); + void nfwControlCommand(bool enable); /* ========= ODCPI ===================================================================== */ /* ======== COMMANDS ====(Called from Client Thread)==================================== */ @@ -321,9 +331,11 @@ public: LocationControlCallbacks& getControlCallbacks() { return mControlCallbacks; } void setControlCallbacks(const LocationControlCallbacks& controlCallbacks) { mControlCallbacks = controlCallbacks; } + void setAfwControlId(uint32_t id) { mPowerVoteId = id; } + uint32_t getAfwControlId() { return mPowerVoteId; } void setPowerVoteId(uint32_t id) { mPowerVoteId = id; } uint32_t getPowerVoteId() { return mPowerVoteId; } - virtual bool isInSession() { return !mTrackingSessions.empty(); } + virtual bool isInSession() { return !mTimeBasedTrackingSessions.empty(); } void initDefaultAgps(); bool initEngHubProxy(); void odcpiTimerExpireEvent(); @@ -342,9 +354,8 @@ public: virtual void reportNmeaEvent(const char* nmea, size_t length); virtual void reportDataEvent(const GnssDataNotification& dataNotify, int msInWeek); virtual bool requestNiNotifyEvent(const GnssNiNotification& notify, const void* data); - virtual void reportGnssMeasurementDataEvent(const GnssMeasurementsNotification& measurements, + virtual void reportGnssMeasurementsEvent(const GnssMeasurements& gnssMeasurements, int msInWeek); - virtual void reportSvMeasurementEvent(GnssSvMeasurementSet &svMeasurementSet); virtual void reportSvPolynomialEvent(GnssSvPolynomial &svPolynomial); virtual void reportSvEphemerisEvent(GnssSvEphemerisReport & svEphemeris); virtual void reportGnssSvIdConfigEvent(const GnssSvIdConfig& config); @@ -356,10 +367,15 @@ public: virtual bool releaseATL(int connHandle); virtual bool requestOdcpiEvent(OdcpiRequestInfo& request); virtual bool reportDeleteAidingDataEvent(GnssAidingData& aidingData); + virtual bool reportKlobucharIonoModelEvent(GnssKlobucharIonoModel& ionoModel); + virtual bool reportGnssAdditionalSystemInfoEvent( + GnssAdditionalSystemInfo& additionalSystemInfo); + 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, @@ -375,6 +391,11 @@ public: void invokeGnssEnergyConsumedCallback(uint64_t energyConsumedSinceFirstBoot); void saveGnssEnergyConsumedCallback(GnssEnergyConsumedCallback energyConsumedCb); void reportLocationSystemInfo(const LocationSystemInfo & locationSystemInfo); + inline void reportNfwNotification(const GnssNfwNotification& notification) { + if (NULL != mNfwCb) { + mNfwCb(notification); + } + } /*======== GNSSDEBUG ================================================================*/ bool getDebugReport(GnssDebugReport& report); @@ -389,8 +410,6 @@ public: std::string& getMoServerUrl(void) { return mMoServerUrl; } /*==== CONVERSION ===================================================================*/ - static uint32_t convertGpsLock(const GnssConfigGpsLock gpsLock); - static GnssConfigGpsLock convertGpsLock(const uint32_t gpsLock); static uint32_t convertSuplVersion(const GnssConfigSuplVersion suplVersion); static uint32_t convertLppProfile(const GnssConfigLppProfile lppProfile); static uint32_t convertEP4ES(const GnssConfigEmergencyPdnForEmergencySupl); @@ -414,6 +433,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.cpp b/gnss/XtraSystemStatusObserver.cpp index 6df5480..6e1902c 100644 --- a/gnss/XtraSystemStatusObserver.cpp +++ b/gnss/XtraSystemStatusObserver.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 @@ -56,7 +56,7 @@ using namespace loc_core; #endif #define LOG_TAG "LocSvc_XSSO" -bool XtraSystemStatusObserver::updateLockStatus(uint32_t lock) { +bool XtraSystemStatusObserver::updateLockStatus(GnssConfigGpsLock lock) { mGpsLock = lock; if (!mReqStatusReceived) { @@ -69,17 +69,21 @@ bool XtraSystemStatusObserver::updateLockStatus(uint32_t lock) { return ( send(LOC_IPC_XTRA, ss.str()) ); } -bool XtraSystemStatusObserver::updateConnections(uint64_t allConnections) { +bool XtraSystemStatusObserver::updateConnections(uint64_t allConnections, + uint64_t wifiNetworkHandle, uint64_t mobileNetworkHandle) { mIsConnectivityStatusKnown = true; mConnections = allConnections; + mWifiNetworkHandle = wifiNetworkHandle; + mMobileNetworkHandle = mobileNetworkHandle; if (!mReqStatusReceived) { return true; } stringstream ss; - ss << "connection"; - ss << " " << mConnections; + ss << "connection" << endl << mConnections << endl << wifiNetworkHandle + << endl << mobileNetworkHandle; + return ( send(LOC_IPC_XTRA, ss.str()) ); } @@ -134,6 +138,7 @@ inline bool XtraSystemStatusObserver::onStatusRequested(int32_t xtraStatusUpdate ss << "respondStatus" << endl; (mGpsLock == -1 ? ss : ss << mGpsLock) << endl; (mConnections == (uint64_t)~0 ? ss : ss << mConnections) << endl + << mWifiNetworkHandle << endl << mMobileNetworkHandle << endl << mTac << endl << mMccmnc << endl << mIsConnectivityStatusKnown; return ( send(LOC_IPC_XTRA, ss.str()) ); @@ -219,8 +224,11 @@ void XtraSystemStatusObserver::notify(const list<IDataItemCore*>& dlist) } inline ~HandleOsObserverUpdateMsg() { - for (auto each : mDataItemList) { - delete each; + for (auto itor = mDataItemList.begin(); itor != mDataItemList.end(); ++itor) { + if (*itor != nullptr) { + delete *itor; + *itor = nullptr; + } } } @@ -232,7 +240,11 @@ void XtraSystemStatusObserver::notify(const list<IDataItemCore*>& dlist) { NetworkInfoDataItemBase* networkInfo = static_cast<NetworkInfoDataItemBase*>(each); - mXtraSysStatObj->updateConnections(networkInfo->getAllTypes()); + mXtraSysStatObj->updateConnections(networkInfo->getAllTypes(), + (NetworkHandle) networkInfo->getNetworkHandle( + loc_core::NetworkInfoDataItemBase::TYPE_WIFI), + (NetworkHandle) networkInfo->getNetworkHandle( + loc_core::NetworkInfoDataItemBase::TYPE_MOBILE)); } break; diff --git a/gnss/XtraSystemStatusObserver.h b/gnss/XtraSystemStatusObserver.h index b49a0bc..b93ecf2 100644 --- a/gnss/XtraSystemStatusObserver.h +++ b/gnss/XtraSystemStatusObserver.h @@ -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 @@ -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); @@ -60,8 +60,9 @@ public : inline virtual void getName(string& name); virtual void notify(const list<IDataItemCore*>& dlist); - bool updateLockStatus(uint32_t lock); - bool updateConnections(uint64_t allConnections); + bool updateLockStatus(GnssConfigGpsLock lock); + bool updateConnections(uint64_t allConnections, + uint64_t wifiNetworkHandle, uint64_t mobileNetworkHandle); bool updateTac(const string& tac); bool updateMccMnc(const string& mccmnc); bool updateXtraThrottle(const bool enabled); @@ -74,8 +75,10 @@ protected: private: IOsObserver* mSystemStatusObsrvr; const MsgTask* mMsgTask; - int32_t mGpsLock; + GnssConfigGpsLock mGpsLock; uint64_t mConnections; + uint64_t mWifiNetworkHandle; + uint64_t mMobileNetworkHandle; string mTac; string mMccmnc; bool mXtraThrottle; diff --git a/gnss/location_gnss.cpp b/gnss/location_gnss.cpp index f9fbddc..43665b4 100644 --- a/gnss/location_gnss.cpp +++ b/gnss/location_gnss.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 @@ -65,8 +65,12 @@ static void agpsDataConnOpen(AGpsExtType agpsType, const char* apnName, int apnL static void agpsDataConnClosed(AGpsExtType agpsType); static void agpsDataConnFailed(AGpsExtType agpsType); static void getDebugReport(GnssDebugReport& report); -static void updateConnectionStatus(bool connected, int8_t type); +static void updateConnectionStatus(bool connected, int8_t type, bool roaming = false, + NetworkHandle networkHandle = NETWORK_HANDLE_UNKNOWN); static void getGnssEnergyConsumed(GnssEnergyConsumedCallback energyConsumedCb); +static void enableNfwLocationAccess(bool enable); +static void nfwInit(const NfwCbInfo& cbInfo); +static void getPowerStateChanges(void* powerStateCb); static void odcpiInit(const OdcpiRequestCallback& callback); static void odcpiInject(const Location& location); @@ -106,7 +110,10 @@ static const GnssInterface gGnssInterface = { odcpiInit, odcpiInject, blockCPI, - getGnssEnergyConsumed + getGnssEnergyConsumed, + enableNfwLocationAccess, + nfwInit, + getPowerStateChanges }; #ifndef DEBUG_X86 @@ -313,9 +320,11 @@ static void getDebugReport(GnssDebugReport& report) { } } -static void updateConnectionStatus(bool connected, int8_t type) { +static void updateConnectionStatus(bool connected, int8_t type, + bool roaming, NetworkHandle networkHandle) { if (NULL != gGnssAdapter) { - gGnssAdapter->getSystemStatus()->eventConnectionStatus(connected, type); + gGnssAdapter->getSystemStatus()->eventConnectionStatus( + connected, type, roaming, networkHandle); } } @@ -346,3 +355,21 @@ static void getGnssEnergyConsumed(GnssEnergyConsumedCallback energyConsumedCb) { gGnssAdapter->getGnssEnergyConsumedCommand(energyConsumedCb); } } + +static void enableNfwLocationAccess(bool enable) { + if (NULL != gGnssAdapter) { + gGnssAdapter->nfwControlCommand(enable); + } +} + +static void nfwInit(const NfwCbInfo& cbInfo) { + if (NULL != gGnssAdapter) { + gGnssAdapter->initNfwCommand(cbInfo); + } +} +static void getPowerStateChanges(void* powerStateCb) +{ + if (NULL != gGnssAdapter) { + gGnssAdapter->getPowerStateChangesCommand(powerStateCb); + } +} diff --git a/gps_vendor_board.mk b/gps_vendor_board.mk new file mode 100644 index 0000000..be346dc --- /dev/null +++ b/gps_vendor_board.mk @@ -0,0 +1,3 @@ +# Flags from BoardConfigVendor.mk +BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE := default + diff --git a/gps_vendor_product.mk b/gps_vendor_product.mk index cfe2b90..6e938b3 100644 --- a/gps_vendor_product.mk +++ b/gps_vendor_product.mk @@ -3,8 +3,12 @@ PRODUCT_PACKAGES += android.hardware.gnss@1.0-impl-qti PRODUCT_PACKAGES += android.hardware.gnss@1.0-service-qti PRODUCT_PACKAGES += android.hardware.gnss@1.1-impl-qti PRODUCT_PACKAGES += android.hardware.gnss@1.1-service-qti +PRODUCT_PACKAGES += android.hardware.gnss@2.0-impl-qti +PRODUCT_PACKAGES += android.hardware.gnss@2.0-service-qti PRODUCT_PACKAGES += gps.conf 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 4d859b3..a43178d 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 @@ -34,15 +34,11 @@ #include <log_util.h> #include <pthread.h> #include <map> +#include <loc_misc_utils.h> -typedef void* (getLocationInterface)(); - -typedef uint16_t LocationAdapterTypeMask; -typedef enum { - LOCATION_ADAPTER_GNSS_TYPE_BIT = (1<<0), // adapter type is GNSS - LOCATION_ADAPTER_FLP_TYPE_BIT = (1<<1), // adapter type is FLP - LOCATION_ADAPTER_GEOFENCE_TYPE_BIT = (1<<2) // adapter type is geo fence -} LocationAdapterTypeBits; +typedef const GnssInterface* (getGnssInterface)(); +typedef const GeofenceInterface* (getGeofenceInterface)(); +typedef const BatchingInterface* (getBatchingInterface)(); typedef struct { // bit mask of the adpaters that we need to wait for the removeClientCompleteCallback @@ -64,22 +60,24 @@ 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); +template <typename T1, typename T2> +static const T1* loadLocationInterface(const char* library, const char* name) { + void* libhandle = nullptr; + T2* getter = (T2*)dlGetSymFromLib(libhandle, library, name); + if (nullptr == getter) { + return (const T1*) getter; + }else { + return (*getter)(); + } } static bool isGnssClient(LocationCallbacks& locationCallbacks) @@ -90,10 +88,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) @@ -102,41 +99,14 @@ static bool isGeofenceClient(LocationCallbacks& locationCallbacks) locationCallbacks.geofenceStatusCb != nullptr); } -static void* loadLocationInterface(const char* library, const char* name) -{ - LOC_LOGD("%s]: loading %s::%s ...", __func__, library, name); - if (NULL == library || NULL == name) { - return NULL; - } - getLocationInterface* getter = NULL; - const char *error = NULL; - dlerror(); - void *handle = dlopen(library, RTLD_NOW); - if (NULL == handle || (error = dlerror()) != NULL) { - LOC_LOGW("dlopen for %s failed, error = %s", library, error); - } else { - getter = (getLocationInterface*)dlsym(handle, name); - if ((error = dlerror()) != NULL) { - LOC_LOGW("dlsym for %s::%s failed, error = %s", library, name, error); - getter = NULL; - } - } - if (NULL == getter) { - return (void*)getter; - } else { - return (*getter)(); - } -} - -void onRemoveClientCompleteCb ( - LocationAPI* client, LocationAdapterTypeMask adapterType) +void LocationAPI::onRemoveClientCompleteCb (LocationAdapterTypeMask adapterType) { bool invokeCallback = false; locationApiDestroyCompleteCallback destroyCompleteCb; LOC_LOGd("adatper type %x", adapterType); pthread_mutex_lock(&gDataMutex); - auto it = gData.destroyClientData.find(client); + auto it = gData.destroyClientData.find(this); if (it != gData.destroyClientData.end()) { it->second.waitAdapterMask &= ~adapterType; if (it->second.waitAdapterMask == 0) { @@ -151,22 +121,24 @@ void onRemoveClientCompleteCb ( LOC_LOGd("invoke client destroy cb"); (destroyCompleteCb) (); LOC_LOGd("finish invoke client destroy cb"); + + delete this; } } void onGnssRemoveClientCompleteCb (LocationAPI* client) { - onRemoveClientCompleteCb (client, LOCATION_ADAPTER_GNSS_TYPE_BIT); + client->onRemoveClientCompleteCb (LOCATION_ADAPTER_GNSS_TYPE_BIT); } -void onFlpRemoveClientCompleteCb (LocationAPI* client) +void onBatchingRemoveClientCompleteCb (LocationAPI* client) { - onRemoveClientCompleteCb (client, LOCATION_ADAPTER_FLP_TYPE_BIT); + client->onRemoveClientCompleteCb (LOCATION_ADAPTER_BATCHING_TYPE_BIT); } void onGeofenceRemoveClientCompleteCb (LocationAPI* client) { - onRemoveClientCompleteCb (client, LOCATION_ADAPTER_GEOFENCE_TYPE_BIT); + client->onRemoveClientCompleteCb (LOCATION_ADAPTER_GEOFENCE_TYPE_BIT); } LocationAPI* @@ -186,7 +158,8 @@ LocationAPI::createInstance(LocationCallbacks& locationCallbacks) if (isGnssClient(locationCallbacks)) { if (NULL == gData.gnssInterface && !gGnssLoadFailed) { gData.gnssInterface = - (GnssInterface*)loadLocationInterface("libgnss.so", "getGnssInterface"); + (GnssInterface*)loadLocationInterface<GnssInterface, + getGnssInterface>("libgnss.so", "getGnssInterface"); if (NULL == gData.gnssInterface) { gGnssLoadFailed = true; LOC_LOGW("%s:%d]: No gnss interface available", __func__, __LINE__); @@ -203,21 +176,22 @@ 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<BatchingInterface, + getBatchingInterface>("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; } } @@ -226,7 +200,8 @@ LocationAPI::createInstance(LocationCallbacks& locationCallbacks) if (isGeofenceClient(locationCallbacks)) { if (NULL == gData.geofenceInterface && !gGeofenceLoadFailed) { gData.geofenceInterface = - (GeofenceInterface*)loadLocationInterface("libgeofence.so", "getGeofenceInterface"); + (GeofenceInterface*)loadLocationInterface<GeofenceInterface, + getGeofenceInterface>("libgeofencing.so", "getGeofenceInterface"); if (NULL == gData.geofenceInterface) { gGeofenceLoadFailed = true; LOC_LOGW("%s:%d]: No geofence interface available", __func__, __LINE__); @@ -260,13 +235,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 = {}; @@ -277,7 +253,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; @@ -288,9 +264,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, @@ -310,6 +286,7 @@ LocationAPI::destroy(locationApiDestroyCompleteCallback destroyCompleteCb) pthread_mutex_unlock(&gDataMutex); if (invokeDestroyCb == true) { (destroyCompleteCb) (); + delete this; } } @@ -321,6 +298,7 @@ LocationAPI::LocationAPI() // private destructor LocationAPI::~LocationAPI() { + LOC_LOGD("LOCATION API DESTRUCTOR"); } void @@ -337,7 +315,8 @@ LocationAPI::updateCallbacks(LocationCallbacks& locationCallbacks) if (isGnssClient(locationCallbacks)) { if (NULL == gData.gnssInterface && !gGnssLoadFailed) { gData.gnssInterface = - (GnssInterface*)loadLocationInterface("libgnss.so", "getGnssInterface"); + (GnssInterface*)loadLocationInterface<GnssInterface, + getGnssInterface>("libgnss.so", "getGnssInterface"); if (NULL == gData.gnssInterface) { gGnssLoadFailed = true; LOC_LOGW("%s:%d]: No gnss interface available", __func__, __LINE__); @@ -351,27 +330,29 @@ 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<BatchingInterface, + getBatchingInterface>("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<GeofenceInterface, + getGeofenceInterface>("libgeofencing.so", "getGeofenceInterface"); if (NULL == gData.geofenceInterface) { gGeofenceLoadFailed = true; LOC_LOGW("%s:%d]: No geofence interface available", __func__, __LINE__); @@ -398,16 +379,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 { @@ -426,16 +401,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 { @@ -454,16 +423,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 { @@ -480,10 +443,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); } @@ -496,10 +459,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); } @@ -511,10 +474,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); } @@ -526,10 +489,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); } @@ -637,7 +600,8 @@ LocationControlAPI::createInstance(LocationControlCallbacks& locationControlCall if (nullptr != locationControlCallbacks.responseCb && NULL == gData.controlAPI) { if (NULL == gData.gnssInterface && !gGnssLoadFailed) { gData.gnssInterface = - (GnssInterface*)loadLocationInterface("libgnss.so", "getGnssInterface"); + (GnssInterface*)loadLocationInterface<GnssInterface, + getGnssInterface>("libgnss.so", "getGnssInterface"); if (NULL == gData.gnssInterface) { gGnssLoadFailed = true; LOC_LOGW("%s:%d]: No gnss interface available", __func__, __LINE__); diff --git a/location/LocationAPI.h b/location/LocationAPI.h index c270ef4..6f5987c 100644 --- a/location/LocationAPI.h +++ b/location/LocationAPI.h @@ -52,6 +52,8 @@ public: */ void destroy(locationApiDestroyCompleteCallback destroyCompleteCb=nullptr); + void onRemoveClientCompleteCb (LocationAdapterTypeMask adapterType); + /* updates/changes the callbacks that will be called. mandatory callbacks must be present for callbacks to be successfully updated no return value */ diff --git a/location/LocationAPIClientBase.h b/location/LocationAPIClientBase.h index da87535..fddae60 100644 --- a/location/LocationAPIClientBase.h +++ b/location/LocationAPIClientBase.h @@ -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 diff --git a/location/LocationDataTypes.h b/location/LocationDataTypes.h index 61598be..f8bb6cb 100644 --- a/location/LocationDataTypes.h +++ b/location/LocationDataTypes.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2018 The Linux Foundation. All rights reserved. +/* Copyright (c) 2018-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 @@ -38,7 +38,7 @@ #define GNSS_NI_REQUESTOR_MAX (256) #define GNSS_NI_MESSAGE_ID_MAX (2048) #define GNSS_SV_MAX (176) -#define GNSS_MEASUREMENTS_MAX (64) +#define GNSS_MEASUREMENTS_MAX (128) #define GNSS_UTC_TIME_OFFSET (3657) #define GNSS_BUGREPORT_GPS_MIN (1) @@ -48,6 +48,8 @@ #define GNSS_BUGREPORT_BDS_MIN (1) #define GNSS_BUGREPORT_GAL_MIN (1) +#define GNSS_MAX_NAME_LENGTH (8) + typedef enum { LOCATION_ERROR_SUCCESS = 0, LOCATION_ERROR_GENERAL_FAILURE, @@ -223,12 +225,13 @@ typedef enum { } LocationTechnologyType; // Configures how GPS is locked when GPS is disabled (through GnssDisable) -typedef enum { +enum { GNSS_CONFIG_GPS_LOCK_NONE = 0, // gps is not locked when GPS is disabled (GnssDisable) GNSS_CONFIG_GPS_LOCK_MO, // gps mobile originated (MO) is locked when GPS is disabled GNSS_CONFIG_GPS_LOCK_NI, // gps network initiated (NI) is locked when GPS is disabled GNSS_CONFIG_GPS_LOCK_MO_AND_NI,// gps MO and NI is locked when GPS is disabled -} GnssConfigGpsLock; +}; +typedef int32_t GnssConfigGpsLock; // SUPL version typedef enum { @@ -303,6 +306,7 @@ typedef enum { GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT = (1<<8), GNSS_CONFIG_FLAGS_SUPL_MODE_BIT = (1<<9), GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT = (1<<10), + GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT = (1<<11), } GnssConfigFlagsBits; typedef enum { @@ -374,6 +378,8 @@ typedef enum { typedef enum { GNSS_ASSISTANCE_TYPE_SUPL = 0, GNSS_ASSISTANCE_TYPE_C2K, + GNSS_ASSISTANCE_TYPE_SUPL_EIMS, + GNSS_ASSISTANCE_TYPE_SUPL_IMS, } GnssAssistanceType; typedef enum { @@ -396,12 +402,31 @@ typedef enum { typedef uint16_t GnssMeasurementsAdrStateMask; typedef enum { - GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_UNKNOWN = 0, - GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_VALID_BIT = (1<<0), - GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_RESET_BIT = (1<<1), - GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_CYCLE_SLIP_BIT = (1<<2), + GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_UNKNOWN = 0, + GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_VALID_BIT = (1<<0), + GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_RESET_BIT = (1<<1), + GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_CYCLE_SLIP_BIT = (1<<2), + GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_HALF_CYCLE_RESOLVED_BIT = (1<<3), } GnssMeasurementsAdrStateBits; +typedef enum { + GNSS_MEASUREMENTS_CODE_TYPE_A = 0, + GNSS_MEASUREMENTS_CODE_TYPE_B = 1, + GNSS_MEASUREMENTS_CODE_TYPE_C = 2, + GNSS_MEASUREMENTS_CODE_TYPE_I = 3, + GNSS_MEASUREMENTS_CODE_TYPE_L = 4, + GNSS_MEASUREMENTS_CODE_TYPE_M = 5, + GNSS_MEASUREMENTS_CODE_TYPE_P = 6, + GNSS_MEASUREMENTS_CODE_TYPE_Q = 7, + GNSS_MEASUREMENTS_CODE_TYPE_S = 8, + GNSS_MEASUREMENTS_CODE_TYPE_W = 9, + GNSS_MEASUREMENTS_CODE_TYPE_X = 10, + GNSS_MEASUREMENTS_CODE_TYPE_Y = 11, + GNSS_MEASUREMENTS_CODE_TYPE_Z = 12, + GNSS_MEASUREMENTS_CODE_TYPE_N = 13, + GNSS_MEASUREMENTS_CODE_TYPE_OTHER = 255, +} GnssMeasurementsCodeType; + typedef uint32_t GnssMeasurementsDataFlagsMask; typedef enum { GNSS_MEASUREMENTS_DATA_SV_ID_BIT = (1<<0), @@ -441,6 +466,9 @@ typedef enum { GNSS_MEASUREMENTS_STATE_GAL_E1C_2ND_CODE_LOCK_BIT = (1<<11), GNSS_MEASUREMENTS_STATE_GAL_E1B_PAGE_SYNC_BIT = (1<<12), GNSS_MEASUREMENTS_STATE_SBAS_SYNC_BIT = (1<<13), + GNSS_MEASUREMENTS_STATE_TOW_KNOWN_BIT = (1<<14), + GNSS_MEASUREMENTS_STATE_GLO_TOD_KNOWN_BIT = (1<<15), + GNSS_MEASUREMENTS_STATE_2ND_CODE_LOCK_BIT = (1<<16), } GnssMeasurementsStateBits; typedef enum { @@ -488,6 +516,22 @@ typedef enum { GNSS_AIDING_DATA_SV_TYPE_GALILEO_BIT = (1<<4), } GnssAidingDataSvTypeBits; +/* Gnss constellation type mask */ +typedef uint16_t GnssConstellationTypeMask; +typedef enum { + GNSS_CONSTELLATION_TYPE_GPS_BIT = (1<<0), + GNSS_CONSTELLATION_TYPE_GLONASS_BIT = (1<<1), + GNSS_CONSTELLATION_TYPE_QZSS_BIT = (1<<2), + GNSS_CONSTELLATION_TYPE_BEIDOU_BIT = (1<<3), + GNSS_CONSTELLATION_TYPE_GALILEO_BIT = (1<<4), + GNSS_CONSTELLATION_TYPE_SBAS_BIT = (1<<5) +} GnssConstellationTypeBits; + +#define GNSS_CONSTELLATION_TYPE_MASK_ALL\ + (GNSS_CONSTELLATION_TYPE_GPS_BIT | GNSS_CONSTELLATION_TYPE_GLONASS_BIT |\ + GNSS_CONSTELLATION_TYPE_QZSS_BIT | GNSS_CONSTELLATION_TYPE_BEIDOU_BIT |\ + GNSS_CONSTELLATION_TYPE_GALILEO_BIT | GNSS_CONSTELLATION_TYPE_SBAS_BIT) + /** GNSS Signal Type and RF Band */ typedef uint32_t GnssSignalTypeMask; typedef enum { @@ -529,21 +573,29 @@ typedef enum { GNSS_SIGNAL_SBAS_L1 = (1<<17) } GnssSignalTypeBits; +#define GNSS_SIGNAL_TYPE_MASK_ALL\ + (GNSS_SIGNAL_GPS_L1CA | GNSS_SIGNAL_GPS_L1C | GNSS_SIGNAL_GPS_L2 |\ + GNSS_SIGNAL_GPS_L5| GNSS_SIGNAL_GLONASS_G1 | GNSS_SIGNAL_GLONASS_G2 |\ + GNSS_SIGNAL_GALILEO_E1 | GNSS_SIGNAL_GALILEO_E5A | GNSS_SIGNAL_GALILEO_E5B |\ + GNSS_SIGNAL_BEIDOU_B1I | GNSS_SIGNAL_BEIDOU_B1C | GNSS_SIGNAL_BEIDOU_B2I|\ + GNSS_SIGNAL_BEIDOU_B2AI | GNSS_SIGNAL_QZSS_L1CA | GNSS_SIGNAL_QZSS_L1S |\ + GNSS_SIGNAL_QZSS_L2| GNSS_SIGNAL_QZSS_L5 | GNSS_SIGNAL_SBAS_L1) + typedef enum { + GNSS_LOC_SV_SYSTEM_UNKNOWN = 0, + /** unknown sv system. */ GNSS_LOC_SV_SYSTEM_GPS = 1, /**< GPS satellite. */ GNSS_LOC_SV_SYSTEM_GALILEO = 2, /**< GALILEO satellite. */ GNSS_LOC_SV_SYSTEM_SBAS = 3, /**< SBAS satellite. */ - GNSS_LOC_SV_SYSTEM_COMPASS = 4, - /**< COMPASS satellite. */ - GNSS_LOC_SV_SYSTEM_GLONASS = 5, + GNSS_LOC_SV_SYSTEM_GLONASS = 4, /**< GLONASS satellite. */ - GNSS_LOC_SV_SYSTEM_BDS = 6, + GNSS_LOC_SV_SYSTEM_BDS = 5, /**< BDS satellite. */ - GNSS_LOC_SV_SYSTEM_QZSS = 7 + GNSS_LOC_SV_SYSTEM_QZSS = 6 /**< QZSS satellite. */ } Gnss_LocSvSystemEnumType; @@ -590,7 +642,7 @@ typedef enum { typedef uint32_t GnssGloTimeStructTypeFlags; typedef enum { GNSS_CLO_DAYS_VALID = (1 << 0), - GNSS_GLOS_MSEC_VALID = (1 << 1), + GNSS_GLO_MSEC_VALID = (1 << 1), GNSS_GLO_CLK_TIME_BIAS_VALID = (1 << 2), GNSS_GLO_CLK_TIME_BIAS_UNC_VALID = (1 << 3), GNSS_GLO_REF_FCOUNT_VALID = (1 << 4), @@ -624,7 +676,7 @@ typedef struct { } GnssAidingData; typedef struct { - size_t size; // set to sizeof(Location) + uint32_t size; // set to sizeof(Location) LocationFlagsMask flags; // bitwise OR of LocationFlagsBits to mark which params are valid uint64_t timestamp; // UTC timestamp for location fix, milliseconds since January 1, 1970 double latitude; // in degrees @@ -641,7 +693,7 @@ typedef struct { } Location; struct LocationOptions { - size_t size; // set to sizeof(LocationOptions) + uint32_t size; // set to sizeof(LocationOptions) uint32_t minInterval; // in milliseconds uint32_t minDistance; // in meters. if minDistance > 0, gnssSvCallback/gnssNmeaCallback/ // gnssMeasurementsCallback may not be called @@ -668,7 +720,7 @@ struct TrackingOptions : LocationOptions { inline TrackingOptions() : LocationOptions(), powerMode(GNSS_POWER_MODE_INVALID), tbm(0) {} - inline TrackingOptions(size_t s, GnssPowerMode m, uint32_t t) : + inline TrackingOptions(uint32_t s, GnssPowerMode m, uint32_t t) : LocationOptions(), powerMode(m), tbm(t) { LocationOptions::size = s; } inline TrackingOptions(const LocationOptions& options) : LocationOptions(options), powerMode(GNSS_POWER_MODE_INVALID), tbm(0) {} @@ -692,7 +744,7 @@ struct BatchingOptions : LocationOptions { inline BatchingOptions() : LocationOptions(), batchingMode(BATCHING_MODE_ROUTINE) {} - inline BatchingOptions(size_t s, BatchingMode m) : + inline BatchingOptions(uint32_t s, BatchingMode m) : LocationOptions(), batchingMode(m) { LocationOptions::size = s; } inline BatchingOptions(const LocationOptions& options) : LocationOptions(options), batchingMode(BATCHING_MODE_ROUTINE) {} @@ -704,27 +756,27 @@ struct BatchingOptions : LocationOptions { }; typedef struct { - size_t size; + uint32_t size; BatchingStatus batchingStatus; } BatchingStatusInfo; typedef struct { - size_t size; // set to sizeof(GeofenceOption) + uint32_t size; // set to sizeof(GeofenceOption) GeofenceBreachTypeMask breachTypeMask; // bitwise OR of GeofenceBreachTypeBits uint32_t responsiveness; // in milliseconds uint32_t dwellTime; // in seconds } GeofenceOption; typedef struct { - size_t size; // set to sizeof(GeofenceInfo) + uint32_t size; // set to sizeof(GeofenceInfo) double latitude; // in degrees double longitude; // in degrees double radius; // in meters } GeofenceInfo; typedef struct { - size_t size; // set to sizeof(GeofenceBreachNotification) - size_t count; // number of ids in array + uint32_t size; // set to sizeof(GeofenceBreachNotification) + uint32_t count; // number of ids in array uint32_t* ids; // array of ids that have breached Location location; // location associated with breach GeofenceBreachType type; // type of breach @@ -732,7 +784,7 @@ typedef struct { } GeofenceBreachNotification; typedef struct { - size_t size; // set to sizeof(GeofenceBreachNotification) + uint32_t size; // set to sizeof(GeofenceBreachNotification) GeofenceStatusAvailable available; // GEOFENCE_STATUS_AVAILABILE_NO/_YES LocationTechnologyType techType; // GNSS } GeofenceStatusNotification; @@ -866,7 +918,7 @@ typedef struct { } GnssSystemTime; typedef struct { - size_t size; // set to sizeof(GnssLocationInfo) + uint32_t size; // set to sizeof(GnssLocationInfo) GnssLocationInfoFlagMask flags; // bitwise OR of GnssLocationInfoBits for param validity float altitudeMeanSeaLevel; // altitude wrt mean sea level float pdop; // position dilusion of precision @@ -902,7 +954,7 @@ typedef struct { } GnssLocationInfoNotification; typedef struct { - size_t size; // set to sizeof(GnssNiNotification) + uint32_t size; // set to sizeof(GnssNiNotification) GnssNiType type; // type of NI (Voice, SUPL, Control Plane) GnssNiOptionsMask options; // bitwise OR of GnssNiOptionsBits uint32_t timeout; // time (seconds) to wait for user input @@ -915,7 +967,7 @@ typedef struct { } GnssNiNotification; typedef struct { - size_t size; // set to sizeof(GnssSv) + uint32_t size; // set to sizeof(GnssSv) uint16_t svId; // Unique Identifier GnssSvType type; // type of SV (GPS, SBAS, GLONASS, QZSS, BEIDOU, GALILEO) float cN0Dbhz; // signal strength @@ -927,7 +979,7 @@ typedef struct { } GnssSv; struct GnssConfigSetAssistanceServer { - size_t size; // set to sizeof(GnssConfigSetAssistanceServer) + uint32_t size; // set to sizeof(GnssConfigSetAssistanceServer) GnssAssistanceType type; // SUPL or C2K const char* hostName; // null terminated string uint32_t port; // port of server @@ -944,7 +996,7 @@ struct GnssConfigSetAssistanceServer { }; typedef struct { - size_t size; // set to sizeof(GnssMeasurementsData) + uint32_t size; // set to sizeof(GnssMeasurementsData) GnssMeasurementsDataFlagsMask flags; // bitwise OR of GnssMeasurementsDataFlagsBits int16_t svId; GnssSvType svType; @@ -965,10 +1017,12 @@ typedef struct { GnssMeasurementsMultipathIndicator multipathIndicator; double signalToNoiseRatioDb; double agcLevelDb; + GnssMeasurementsCodeType codeType; + char otherCodeTypeName[GNSS_MAX_NAME_LENGTH]; } GnssMeasurementsData; typedef struct { - size_t size; // set to sizeof(GnssMeasurementsClock) + uint32_t size; // set to sizeof(GnssMeasurementsClock) GnssMeasurementsClockFlagsMask flags; // bitwise OR of GnssMeasurementsClockFlagsBits int16_t leapSecond; int64_t timeNs; @@ -982,29 +1036,29 @@ typedef struct { } GnssMeasurementsClock; typedef struct { - size_t size; // set to sizeof(GnssSvNotification) - size_t count; // number of SVs in the GnssSv array + uint32_t size; // set to sizeof(GnssSvNotification) + uint32_t count; // number of SVs in the GnssSv array bool gnssSignalTypeMaskValid; GnssSv gnssSvs[GNSS_SV_MAX]; // information on a number of SVs } GnssSvNotification; typedef struct { - size_t size; // set to sizeof(GnssNmeaNotification) + uint32_t size; // set to sizeof(GnssNmeaNotification) uint64_t timestamp; // timestamp const char* nmea; // nmea text - size_t length; // length of the nmea text + uint32_t length; // length of the nmea text } GnssNmeaNotification; typedef struct { - size_t size; // set to sizeof(GnssDataNotification) + uint32_t size; // set to sizeof(GnssDataNotification) GnssDataMask gnssDataMask[GNSS_LOC_MAX_NUMBER_OF_SIGNAL_TYPES]; // bitwise OR of GnssDataBits double jammerInd[GNSS_LOC_MAX_NUMBER_OF_SIGNAL_TYPES]; // Jammer Indication double agc[GNSS_LOC_MAX_NUMBER_OF_SIGNAL_TYPES]; // Automatic gain control } GnssDataNotification; typedef struct { - size_t size; // set to sizeof(GnssMeasurementsNotification) - size_t count; // number of items in GnssMeasurements array + uint32_t size; // set to sizeof(GnssMeasurementsNotification) + uint32_t count; // number of items in GnssMeasurements array GnssMeasurementsData measurements[GNSS_MEASUREMENTS_MAX]; GnssMeasurementsClock clock; // clock } GnssMeasurementsNotification; @@ -1012,9 +1066,9 @@ typedef struct { typedef uint32_t GnssSvId; struct GnssSvIdSource{ - size_t size; // set to sizeof(GnssSvIdSource) - GnssSvType constellation; // constellation for the sv to blacklist - GnssSvId svId; // sv id to blacklist + uint32_t size; // set to sizeof(GnssSvIdSource) + GnssSvType constellation; // constellation for the sv to blacklist + GnssSvId svId; // sv id to blacklist }; inline bool operator ==(GnssSvIdSource const& left, GnssSvIdSource const& right) { return left.size == right.size && @@ -1023,7 +1077,7 @@ inline bool operator ==(GnssSvIdSource const& left, GnssSvIdSource const& right) #define GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK ((uint64_t)0xFFFFFFFFFFFFFFFF) typedef struct { - size_t size; // set to sizeof(GnssSvIdConfig) + uint32_t size; // set to sizeof(GnssSvIdConfig) // GLONASS - SV 65 maps to bit 0 #define GNSS_SV_CONFIG_GLO_INITIAL_SV_ID 65 @@ -1043,7 +1097,7 @@ typedef struct { } GnssSvIdConfig; struct GnssConfig{ - size_t size; // set to sizeof(GnssConfig) + uint32_t size; // set to sizeof(GnssConfig) GnssConfigFlagsMask flags; // bitwise OR of GnssConfigFlagsBits to mark which params are valid GnssConfigGpsLock gpsLock; GnssConfigSuplVersion suplVersion; @@ -1056,6 +1110,7 @@ struct GnssConfig{ GnssConfigSuplEmergencyServices suplEmergencyServices; GnssConfigSuplModeMask suplModeMask; //bitwise OR of GnssConfigSuplModeBits std::vector<GnssSvIdSource> blacklistedSvIds; + uint32_t emergencyExtensionSeconds; inline bool equals(const GnssConfig& config) { if (flags == config.flags && @@ -1069,7 +1124,8 @@ struct GnssConfig{ emergencyPdnForEmergencySupl == config.emergencyPdnForEmergencySupl && suplEmergencyServices == config.suplEmergencyServices && suplModeMask == config.suplModeMask && - blacklistedSvIds == config.blacklistedSvIds) { + blacklistedSvIds == config.blacklistedSvIds && + emergencyExtensionSeconds == config.emergencyExtensionSeconds) { return true; } return false; @@ -1077,7 +1133,7 @@ struct GnssConfig{ }; typedef struct { - size_t size; // set to sizeof + uint32_t size; // set to sizeof bool mValid; Location mLocation; double verticalAccuracyMeters; @@ -1087,7 +1143,7 @@ typedef struct { } GnssDebugLocation; typedef struct { - size_t size; // set to sizeof + uint32_t size; // set to sizeof bool mValid; int64_t timeEstimate; float timeUncertaintyNs; @@ -1095,7 +1151,7 @@ typedef struct { } GnssDebugTime; typedef struct { - size_t size; // set to sizeof + uint32_t size; // set to sizeof uint32_t svid; GnssSvType constellation; GnssEphemerisType mEphemerisType; @@ -1107,7 +1163,7 @@ typedef struct { } GnssDebugSatelliteInfo; typedef struct { - size_t size; // set to sizeof + uint32_t size; // set to sizeof GnssDebugLocation mLocation; GnssDebugTime mTime; std::vector<GnssDebugSatelliteInfo> mSatelliteInfo; @@ -1182,7 +1238,7 @@ typedef std::function<void( collectiveResponseCallback is called for every geofence API call. ids array and LocationError array are only valid until collectiveResponseCallback returns. */ typedef std::function<void( - size_t count, // number of locations in arrays + uint32_t count, // number of locations in arrays LocationError* errs, // array of LocationError associated to the request uint32_t* ids // array of ids to be associated to the request )> collectiveResponseCallback; @@ -1198,7 +1254,7 @@ typedef std::function<void( batchingCallback is called when delivering locations in a batching session. broadcasted to all clients, no matter if a session has started by client */ typedef std::function<void( - size_t count, // number of locations in array + uint32_t count, // number of locations in array Location* location, // array of locations BatchingOptions batchingOptions // Batching options )> batchingCallback; @@ -1277,8 +1333,15 @@ typedef std::function<void( typedef std::function<void( )> locationApiDestroyCompleteCallback; +typedef uint16_t LocationAdapterTypeMask; +typedef enum { + LOCATION_ADAPTER_GNSS_TYPE_BIT = (1<<0), // adapter type is GNSS + LOCATION_ADAPTER_BATCHING_TYPE_BIT = (1<<1), // adapter type is BATCHING + LOCATION_ADAPTER_GEOFENCE_TYPE_BIT = (1<<2) // adapter type is geo fence +} LocationAdapterTypeBits; + typedef struct { - size_t size; // set to sizeof(LocationCallbacks) + uint32_t size; // set to sizeof(LocationCallbacks) capabilitiesCallback capabilitiesCb; // mandatory responseCallback responseCb; // mandatory collectiveResponseCallback collectiveResponseCb; // mandatory diff --git a/location/location_interface.h b/location/location_interface.h index 480bbdb..4235a13 100644 --- a/location/location_interface.h +++ b/location/location_interface.h @@ -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 @@ -76,29 +76,29 @@ struct GnssInterface { void (*agpsDataConnClosed)(AGpsExtType agpsType); void (*agpsDataConnFailed)(AGpsExtType agpsType); void (*getDebugReport)(GnssDebugReport& report); - void (*updateConnectionStatus)(bool connected, int8_t type); + void (*updateConnectionStatus)(bool connected, int8_t type, bool roaming, + NetworkHandle networkHandle); void (*odcpiInit)(const OdcpiRequestCallback& callback); void (*odcpiInject)(const Location& location); void (*blockCPI)(double latitude, double longitude, float accuracy, int blockDurationMsec, double latLonDiffThreshold); void (*getGnssEnergyConsumed)(GnssEnergyConsumedCallback energyConsumedCb); + void (*enableNfwLocationAccess)(bool enable); + void (*nfwInit)(const NfwCbInfo& cbInfo); + void (*getPowerStateChanges)(void* powerStateCb); }; -struct FlpInterface { +struct BatchingInterface { size_t size; void (*initialize)(void); void (*deinitialize)(void); void (*addClient)(LocationAPI* client, const LocationCallbacks& callbacks); void (*removeClient)(LocationAPI* client, removeClientCompleteCallback rmClientCb); void (*requestCapabilities)(LocationAPI* client); - uint32_t (*startTracking)(LocationAPI* client, TrackingOptions&); - void (*updateTrackingOptions)(LocationAPI* client, uint32_t id, TrackingOptions&); - void (*stopTracking)(LocationAPI* client, uint32_t id); uint32_t (*startBatching)(LocationAPI* client, BatchingOptions&); void (*stopBatching)(LocationAPI* client, uint32_t id); void (*updateBatchingOptions)(LocationAPI* client, uint32_t id, BatchingOptions&); void (*getBatchedLocations)(LocationAPI* client, uint32_t id, size_t count); - void (*getPowerStateChanges)(void* powerStateCb); }; struct GeofenceInterface { diff --git a/pla/oe/loc_pla.h b/pla/oe/loc_pla.h index 9446888..e795a23 100644 --- a/pla/oe/loc_pla.h +++ b/pla/oe/loc_pla.h @@ -30,7 +30,10 @@ #define __LOC_PLA__ #ifdef __cplusplus +#ifndef FEATURE_EXTERNAL_AP #include <utils/SystemClock.h> +#endif /* FEATURE_EXTERNAL_AP */ +#include <inttypes.h> #include <sys/time.h> #include <time.h> @@ -47,10 +50,14 @@ inline int64_t uptimeMillis() extern "C" { #endif +#ifndef FEATURE_EXTERNAL_AP #include <cutils/properties.h> #include <cutils/threads.h> #include <cutils/sched_policy.h> +#endif /* FEATURE_EXTERNAL_AP */ +#include <pthread.h> #include <sys/time.h> +#include <sys/types.h> #include <string.h> #include <stdlib.h> #ifndef OFF_TARGET @@ -76,6 +83,16 @@ extern "C" { #define LOC_PATH_XTWIFI_CONF_STR "/etc/xtwifi.conf" #define LOC_PATH_QUIPC_CONF_STR "/etc/quipc.conf" +#ifdef FEATURE_EXTERNAL_AP +#define PROPERTY_VALUE_MAX 92 + +inline int property_get(const char* key, char* value, const char* default_value) +{ + strlcpy(value, default_value, PROPERTY_VALUE_MAX - 1); + return strlen(value); +} +#endif /* FEATURE_EXTERNAL_AP */ + #ifdef __cplusplus } #endif /*__cplusplus */ diff --git a/utils/Android.mk b/utils/Android.mk index ec6bf05..3887696 100644 --- a/utils/Android.mk +++ b/utils/Android.mk @@ -9,6 +9,7 @@ include $(CLEAR_VARS) ## Libs LOCAL_SHARED_LIBRARIES := \ + libdl \ libutils \ libcutils \ liblog \ diff --git a/utils/LocIpc.h b/utils/LocIpc.h index 87f2ff8..90f9e1b 100644 --- a/utils/LocIpc.h +++ b/utils/LocIpc.h @@ -27,8 +27,8 @@ * */ -#ifndef __LOC_SOCKET__ -#define __LOC_SOCKET__ +#ifndef __LOC_IPC__ +#define __LOC_IPC__ #include <string> #include <memory> @@ -105,7 +105,7 @@ public: // This class hides generated fd and destination address object from user. inline LocIpcSender(const char* destSocket): LocIpcSender(std::make_shared<int>(::socket(AF_UNIX, SOCK_DGRAM, 0)), destSocket) { - if (-1 == *mSocket) { + if (mSocket != nullptr && -1 == *mSocket) { mSocket = nullptr; } } @@ -149,4 +149,4 @@ private: } -#endif //__LOC_SOCKET__ +#endif //__LOC_IPC__ diff --git a/utils/LocSharedLock.h b/utils/LocSharedLock.h index 7fe6237..a7af35e 100644 --- a/utils/LocSharedLock.h +++ b/utils/LocSharedLock.h @@ -30,10 +30,28 @@ #define __LOC_SHARED_LOCK__ #include <stddef.h> +#ifndef FEATURE_EXTERNAL_AP #include <cutils/atomic.h> +#endif /* FEATURE_EXTERNAL_AP */ #include <pthread.h> -// This is a utility created for use cases such that there are more than +#ifdef FEATURE_EXTERNAL_AP +#include <atomic> + +inline int32_t android_atomic_inc(volatile int32_t *addr) +{ + volatile std::atomic_int_least32_t* a = (volatile std::atomic_int_least32_t*)addr; + return std::atomic_fetch_add_explicit(a, 1, std::memory_order_release); +} + +inline int32_t android_atomic_dec(volatile int32_t *addr) +{ + volatile std::atomic_int_least32_t* a = (volatile std::atomic_int_least32_t*)addr; + return std::atomic_fetch_sub_explicit(a, 1, std::memory_order_release); +} + +#endif /* FEATURE_EXTERNAL_AP */ + // This is a utility created for use cases such that there are more than // one client who need to share the same lock, but it is not predictable // which of these clients is to last to go away. This shared lock deletes // itself when the last client calls its drop() method. To add a cient, diff --git a/utils/LocThread.cpp b/utils/LocThread.cpp index c1052cb..568a6bb 100644 --- a/utils/LocThread.cpp +++ b/utils/LocThread.cpp @@ -85,8 +85,8 @@ LocThreadDelegate::LocThreadDelegate(LocThread::tCreate creator, if (mThandle) { // set thread name char lname[16]; - int len = (sizeof(lname)>sizeof(threadName)) ? - (sizeof(threadName) -1):(sizeof(lname) - 1); + int len = (sizeof(lname) > (strlen(threadName) + 1)) ? + (strlen(threadName)):(sizeof(lname) - 1); memcpy(lname, threadName, len); lname[len] = 0; // set the thread name here diff --git a/utils/Makefile.am b/utils/Makefile.am index 33afc1b..50e1e9a 100644 --- a/utils/Makefile.am +++ b/utils/Makefile.am @@ -61,7 +61,7 @@ libgps_utils_la_LDFLAGS = -Wl,-z,defs -lpthread -shared -version-info 1:0:0 libgps_utils_la_CPPFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS) endif -libgps_utils_la_LIBADD = $(CUTILS_LIBS) +libgps_utils_la_LIBADD = $(CUTILS_LIBS) -ldl #Create and Install libraries lib_LTLIBRARIES = libgps_utils.la diff --git a/utils/MsgTask.cpp b/utils/MsgTask.cpp index ad95a83..73a77fd 100644 --- a/utils/MsgTask.cpp +++ b/utils/MsgTask.cpp @@ -83,8 +83,10 @@ void MsgTask::sendMsg(const LocMsg* msg) const { } void MsgTask::prerun() { +#ifndef FEATURE_EXTERNAL_AP // make sure we do not run in background scheduling group set_sched_policy(gettid(), SP_FOREGROUND); +#endif /* FEATURE_EXTERNAL_AP */ } bool MsgTask::run() { diff --git a/utils/configure.ac b/utils/configure.ac index 639f8c4..fd16494 100644 --- a/utils/configure.ac +++ b/utils/configure.ac @@ -28,10 +28,20 @@ AC_PROG_LN_S AC_PROG_MAKE_SET PKG_PROG_PKG_CONFIG -# Checks for libraries. -PKG_CHECK_MODULES([CUTILS], [libcutils]) -AC_SUBST([CUTILS_CFLAGS]) -AC_SUBST([CUTILS_LIBS]) +AC_ARG_WITH([external_ap], + AC_HELP_STRING([--with-external_ap=@<:@dir@:>@], + [Using External Application Processor]), + [], + with_external_ap=no) + +if test "x$with_external_ap" != "xno"; then + CPPFLAGS="${CPPFLAGS} -DFEATURE_EXTERNAL_AP" +else + # Checks for libraries. + PKG_CHECK_MODULES([CUTILS], [libcutils]) + AC_SUBST([CUTILS_CFLAGS]) + AC_SUBST([CUTILS_LIBS]) +fi AC_ARG_WITH([core_includes], AC_HELP_STRING([--with-core-includes=@<:@dir@:>@], diff --git a/utils/gps_extended_c.h b/utils/gps_extended_c.h index 8ddf488..242fe84 100644 --- a/utils/gps_extended_c.h +++ b/utils/gps_extended_c.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2018 The Linux Foundation. All rights reserved. +/* 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 @@ -199,6 +199,11 @@ typedef struct { AgpsCbPriority cbPriority; } AgpsCbInfo; +typedef struct { + void* visibilityControlCb; + void* isInEmergencySession; +} NfwCbInfo; + /** GPS extended callback structure. */ typedef struct { /** set to sizeof(LocGpsCallbacks) */ @@ -407,9 +412,18 @@ typedef uint32_t LocPosDataMask; /* Bitmask to specify whether Navigation data has Body pitch Unc*/ #define LOC_NAV_DATA_HAS_PITCH_UNC ((LocPosDataMask)0x0200) +typedef uint32_t GnssAdditionalSystemInfoMask; +/* Bitmask to specify whether Tauc is valid */ +#define GNSS_ADDITIONAL_SYSTEMINFO_HAS_TAUC ((GnssAdditionalSystemInfoMask)0x0001) +/* Bitmask to specify whether leapSec is valid */ +#define GNSS_ADDITIONAL_SYSTEMINFO_HAS_LEAP_SEC ((GnssAdditionalSystemInfoMask)0x0002) + + /** GPS PRN Range */ #define GPS_SV_PRN_MIN 1 #define GPS_SV_PRN_MAX 32 +#define SBAS_SV_PRN_MIN 33 +#define SBAS_SV_PRN_MAX 64 #define GLO_SV_PRN_MIN 65 #define GLO_SV_PRN_MAX 96 #define QZSS_SV_PRN_MIN 193 @@ -838,8 +852,8 @@ enum loc_api_adapter_event_index { LOC_API_ADAPTER_BATCH_FULL, // Batching on full LOC_API_ADAPTER_BATCHED_POSITION_REPORT, // Batching on fix LOC_API_ADAPTER_BATCHED_GENFENCE_BREACH_REPORT, // - LOC_API_ADAPTER_GNSS_MEASUREMENT_REPORT, //GNSS Measurement Report - LOC_API_ADAPTER_GNSS_SV_POLYNOMIAL_REPORT, //GNSS SV Polynomial Report + LOC_API_ADAPTER_GNSS_MEASUREMENT_REPORT, // GNSS Measurement Report + LOC_API_ADAPTER_GNSS_SV_POLYNOMIAL_REPORT, // GNSS SV Polynomial Report LOC_API_ADAPTER_GDT_UPLOAD_BEGIN_REQ, // GDT upload start request LOC_API_ADAPTER_GDT_UPLOAD_END_REQ, // GDT upload end request LOC_API_ADAPTER_GNSS_MEASUREMENT, // GNSS Measurement report @@ -853,6 +867,8 @@ enum loc_api_adapter_event_index { LOC_API_ADAPTER_BS_OBS_DATA_SERVICE_REQ, // BS observation data request LOC_API_ADAPTER_GNSS_SV_EPHEMERIS_REPORT, // GNSS SV Ephemeris Report LOC_API_ADAPTER_LOC_SYSTEM_INFO, // Location system info event + LOC_API_ADAPTER_GNSS_NHZ_MEASUREMENT_REPORT, // GNSS SV nHz measurement report + LOC_API_ADAPTER_EVENT_REPORT_INFO, // Event report info LOC_API_ADAPTER_EVENT_MAX }; @@ -893,6 +909,8 @@ enum loc_api_adapter_event_index { #define LOC_API_ADAPTER_BIT_BS_OBS_DATA_SERVICE_REQ (1ULL<<LOC_API_ADAPTER_BS_OBS_DATA_SERVICE_REQ) #define LOC_API_ADAPTER_BIT_GNSS_SV_EPHEMERIS_REPORT (1ULL<<LOC_API_ADAPTER_GNSS_SV_EPHEMERIS_REPORT) #define LOC_API_ADAPTER_BIT_LOC_SYSTEM_INFO (1ULL<<LOC_API_ADAPTER_LOC_SYSTEM_INFO) +#define LOC_API_ADAPTER_BIT_GNSS_NHZ_MEASUREMENT (1ULL<<LOC_API_ADAPTER_GNSS_NHZ_MEASUREMENT_REPORT) +#define LOC_API_ADAPTER_BIT_EVENT_REPORT_INFO (1ULL<<LOC_API_ADAPTER_EVENT_REPORT_INFO) typedef uint64_t LOC_API_ADAPTER_EVENT_MASK_T; @@ -925,7 +943,8 @@ typedef uint32_t LOC_GPS_LOCK_MASK; #define GNSS_SV_POLY_XYZ_0_TH_ORDER_COEFF_MAX_SIZE 3 #define GNSS_SV_POLY_XYZ_N_TH_ORDER_COEFF_MAX_SIZE 9 #define GNSS_SV_POLY_SV_CLKBIAS_COEFF_MAX_SIZE 4 -#define GNSS_LOC_SV_MEAS_LIST_MAX_SIZE 16 +/** Max number of GNSS SV measurement */ +#define GNSS_LOC_SV_MEAS_LIST_MAX_SIZE 128 enum ulp_gnss_sv_measurement_valid_flags{ @@ -1055,71 +1074,12 @@ typedef struct /**< System-1 to System-2 Time Bias uncertainty \n - Units: msec \n */ -}Gnss_InterSystemBiasStructType; - - -typedef struct -{ - size_t size; - uint16_t systemWeek; - /**< System week number for GPS, BDS and GAL satellite systems. \n - Set to 65535 when invalid or not available. \n - Not valid for GLONASS system. \n - */ - - uint32_t systemMsec; - /**< System time msec. Time of Week for GPS, BDS, GAL and - Time of Day for GLONASS. - - Units: msec \n - */ - float systemClkTimeBias; - /**< System clock time bias \n - - Units: msec \n - System time = systemMsec - systemClkTimeBias \n - */ - float systemClkTimeUncMs; - /**< Single sided maximum time bias uncertainty \n - - Units: msec \n - */ -}Gnss_LocSystemTimeStructType; - -typedef struct { - - size_t size; - uint8_t gloFourYear; - /**< GLONASS four year number from 1996. Refer to GLONASS ICD.\n - Applicable only for GLONASS and shall be ignored for other constellations. \n - If unknown shall be set to 255 - */ - - uint16_t gloDays; - /**< GLONASS day number in four years. Refer to GLONASS ICD. - Applicable only for GLONASS and shall be ignored for other constellations. \n - If unknown shall be set to 65535 - */ - - uint32_t gloMsec; - /**< GLONASS time of day in msec. Refer to GLONASS ICD. - - Units: msec \n - */ - - float gloClkTimeBias; - /**< System clock time bias (sub-millisecond) \n - - Units: msec \n - System time = systemMsec - systemClkTimeBias \n - */ +} Gnss_InterSystemBiasStructType; - float gloClkTimeUncMs; - /**< Single sided maximum time bias uncertainty \n - - Units: msec \n - */ -}Gnss_LocGloTimeStructType; /* Type */ typedef struct { size_t size; - uint32_t refFCount; - /**< Receiver frame counter value at reference tick */ uint8_t systemRtc_valid; /**< Validity indicator for System RTC */ @@ -1129,13 +1089,8 @@ typedef struct { - Units: msec \n */ - uint32_t sourceOfTime; - /**< Source of time information */ - }Gnss_LocGnssTimeExtStructType; - - typedef enum { GNSS_LOC_MEAS_STATUS_NULL = 0x00000000, @@ -1231,6 +1186,9 @@ typedef enum typedef struct { size_t size; + Gnss_LocSvSystemEnumType gnssSystem; + // 0 signal type mask indicates invalid value + GnssSignalTypeMask gnssSignalTypeMask; uint16_t gnssSvId; /**< GNSS SV ID. \begin{itemize1} @@ -1367,73 +1325,84 @@ typedef struct } Gnss_SVMeasurementStructType; -/**< Maximum number of satellites in measurement block for given system. */ - -typedef struct -{ - size_t size; - Gnss_LocSvSystemEnumType system; - /**< Specifies the Satellite System Type - */ - bool isSystemTimeValid; - /**< Indicates whether System Time is Valid:\n - - 0x01 (TRUE) -- System Time is valid \n - - 0x00 (FALSE) -- System Time is not valid - */ - Gnss_LocSystemTimeStructType systemTime; - /**< System Time Information \n - */ - bool isGloTime_valid; - Gnss_LocGloTimeStructType gloTime; - - bool isSystemTimeExt_valid; - Gnss_LocGnssTimeExtStructType systemTimeExt; - uint8_t numSvs; - /* Number of SVs in this report block */ +typedef uint64_t GpsSvMeasHeaderFlags; +#define GNSS_SV_MEAS_HEADER_HAS_LEAP_SECOND 0x00000001 +#define GNSS_SV_MEAS_HEADER_HAS_CLOCK_FREQ 0x00000002 +#define GNSS_SV_MEAS_HEADER_HAS_AP_TIMESTAMP 0x00000004 +#define GNSS_SV_MEAS_HEADER_HAS_GPS_GLO_INTER_SYSTEM_BIAS 0x00000008 +#define GNSS_SV_MEAS_HEADER_HAS_GPS_BDS_INTER_SYSTEM_BIAS 0x00000010 +#define GNSS_SV_MEAS_HEADER_HAS_GPS_GAL_INTER_SYSTEM_BIAS 0x00000020 +#define GNSS_SV_MEAS_HEADER_HAS_BDS_GLO_INTER_SYSTEM_BIAS 0x00000040 +#define GNSS_SV_MEAS_HEADER_HAS_GAL_GLO_INTER_SYSTEM_BIAS 0x00000080 +#define GNSS_SV_MEAS_HEADER_HAS_GAL_BDS_INTER_SYSTEM_BIAS 0x00000100 +#define GNSS_SV_MEAS_HEADER_HAS_GPS_SYSTEM_TIME 0x00000200 +#define GNSS_SV_MEAS_HEADER_HAS_GAL_SYSTEM_TIME 0x00000400 +#define GNSS_SV_MEAS_HEADER_HAS_BDS_SYSTEM_TIME 0x00000800 +#define GNSS_SV_MEAS_HEADER_HAS_QZSS_SYSTEM_TIME 0x00001000 +#define GNSS_SV_MEAS_HEADER_HAS_GLO_SYSTEM_TIME 0x00002000 +#define GNSS_SV_MEAS_HEADER_HAS_GPS_SYSTEM_TIME_EXT 0x00004000 +#define GNSS_SV_MEAS_HEADER_HAS_GAL_SYSTEM_TIME_EXT 0x00008000 +#define GNSS_SV_MEAS_HEADER_HAS_BDS_SYSTEM_TIME_EXT 0x00010000 +#define GNSS_SV_MEAS_HEADER_HAS_QZSS_SYSTEM_TIME_EXT 0x00020000 +#define GNSS_SV_MEAS_HEADER_HAS_GPSL1L5_TIME_BIAS 0x00040000 +#define GNSS_SV_MEAS_HEADER_HAS_GALE1E5A_TIME_BIAS 0x00080000 - Gnss_SVMeasurementStructType svMeasurement[GNSS_LOC_SV_MEAS_LIST_MAX_SIZE]; - /**< Satellite measurement Information \n - */ -} Gnss_ClockMeasurementStructType; typedef struct { size_t size; - uint8_t seqNum; - /**< Current message Number */ - uint8_t maxMessageNum; - /**< Maximum number of message that will be sent for present time epoch. */ + // see defines in GNSS_SV_MEAS_HEADER_HAS_XXX_XXX + uint64_t flags; - bool leapSecValid; Gnss_LeapSecondInfoStructType leapSec; - Gnss_InterSystemBiasStructType gpsGloInterSystemBias; + Gnss_LocRcvrClockFrequencyInfoStructType clockFreq; /* Freq */ - Gnss_InterSystemBiasStructType gpsBdsInterSystemBias; + Gnss_ApTimeStampStructType apBootTimeStamp; + Gnss_InterSystemBiasStructType gpsGloInterSystemBias; + Gnss_InterSystemBiasStructType gpsBdsInterSystemBias; Gnss_InterSystemBiasStructType gpsGalInterSystemBias; - Gnss_InterSystemBiasStructType bdsGloInterSystemBias; - Gnss_InterSystemBiasStructType galGloInterSystemBias; - Gnss_InterSystemBiasStructType galBdsInterSystemBias; + Gnss_InterSystemBiasStructType gpsL1L5TimeBias; + Gnss_InterSystemBiasStructType galE1E5aTimeBias; + + GnssSystemTimeStructType gpsSystemTime; + GnssSystemTimeStructType galSystemTime; + GnssSystemTimeStructType bdsSystemTime; + GnssSystemTimeStructType qzssSystemTime; + GnssGloTimeStructType gloSystemTime; + + /** GPS system RTC time information. */ + Gnss_LocGnssTimeExtStructType gpsSystemTimeExt; + /** GAL system RTC time information. */ + Gnss_LocGnssTimeExtStructType galSystemTimeExt; + /** BDS system RTC time information. */ + Gnss_LocGnssTimeExtStructType bdsSystemTimeExt; + /** QZSS system RTC time information. */ + Gnss_LocGnssTimeExtStructType qzssSystemTimeExt; + +} GnssSvMeasurementHeader; - bool clockFreqValid; - Gnss_LocRcvrClockFrequencyInfoStructType clockFreq; /* Freq */ - bool gnssMeasValid; - Gnss_ClockMeasurementStructType gnssMeas; - Gnss_ApTimeStampStructType timeStamp; - /* Extended Time Information - Cumulative Number of Clock Resets */ - uint8_t numClockResets_valid; /**< Must be set to true if numClockResets is being passed */ - uint32_t numClockResets; - bool gnssSignalTypeMaskValid; - GnssSignalTypeMask gnssSignalTypeMask; +typedef struct { + size_t size; + bool isNhz; + GnssSvMeasurementHeader svMeasSetHeader; + uint32_t svMeasCount; + Gnss_SVMeasurementStructType svMeas[GNSS_LOC_SV_MEAS_LIST_MAX_SIZE]; } GnssSvMeasurementSet; +typedef struct { + uint32_t size; // set to sizeof(GnssMeasurements) + GnssSvMeasurementSet gnssSvMeasurementSet; + GnssMeasurementsNotification gnssMeasNotification; +} GnssMeasurements; + typedef enum { GNSS_SV_POLY_COEFF_VALID = 0x01, @@ -1916,6 +1885,10 @@ typedef struct { Mandatory field */ Gnss_LocSvSystemEnumType gnssConstellation; + /** GPS System Time of the ephemeris report */ + bool isSystemTimeValid; + GnssSystemTimeStructType systemTime; + union { /** GPS Ephemeris */ GpsEphemerisResponse gpsEphemeris; @@ -1930,6 +1903,73 @@ typedef struct { } ephInfo; } GnssSvEphemerisReport; +typedef struct { + /** GPS System Time of the iono model report */ + bool isSystemTimeValid; + GnssSystemTimeStructType systemTime; + + /** Indicates GNSS Constellation Type */ + Gnss_LocSvSystemEnumType gnssConstellation; + + float alpha0; + /**< Klobuchar Model Parameter Alpha 0. + - Type: float + - Unit: Seconds + */ + + float alpha1; + /**< Klobuchar Model Parameter Alpha 1. + - Type: float + - Unit: Seconds / Semi-Circle + */ + + float alpha2; + /**< Klobuchar Model Parameter Alpha 2. + - Type: float + - Unit: Seconds / Semi-Circle^2 + */ + + float alpha3; + /**< Klobuchar Model Parameter Alpha 3. + - Type: float + - Unit: Seconds / Semi-Circle^3 + */ + + float beta0; + /**< Klobuchar Model Parameter Beta 0. + - Type: float + - Unit: Seconds + */ + + float beta1; + /**< Klobuchar Model Parameter Beta 1. + - Type: float + - Unit: Seconds / Semi-Circle + */ + + float beta2; + /**< Klobuchar Model Parameter Beta 2. + - Type: float + - Unit: Seconds / Semi-Circle^2 + */ + + float beta3; + /**< Klobuchar Model Parameter Beta 3. + - Type: float + - Unit: Seconds / Semi-Circle^3 + */ +} GnssKlobucharIonoModel; + +typedef struct { + /** GPS System Time of the report */ + bool isSystemTimeValid; + GnssSystemTimeStructType systemTime; + + GnssAdditionalSystemInfoMask validityMask; + double tauC; + int8_t leapSec; +} GnssAdditionalSystemInfo; + /* Various Short Range Node Technology type*/ typedef enum { SRN_AP_DATA_TECH_TYPE_NONE, @@ -2009,6 +2049,46 @@ struct AGnssExtStatusIpV6 { uint8_t ipV6Addr[16]; }; +/* +* Represents the the Nfw Notification structure +*/ +#define GNSS_MAX_NFW_STRING_LEN 20 + +typedef enum { + GNSS_NFW_CTRL_PLANE = 0, + GNSS_NFW_SUPL = 1, + GNSS_NFW_IMS = 10, + GNSS_NFW_SIM = 11, + GNSS_NFW_OTHER_PROTOCOL_STACK = 100 +} GnssNfwProtocolStack; + +typedef enum { + GNSS_NFW_CARRIER = 0, + GNSS_NFW_OEM = 10, + GNSS_NFW_MODEM_CHIPSET_VENDOR = 11, + GNSS_NFW_GNSS_CHIPSET_VENDOR = 12, + GNSS_NFW_OTHER_CHIPSET_VENDOR = 13, + GNSS_NFW_AUTOMOBILE_CLIENT = 20, + GNSS_NFW_OTHER_REQUESTOR = 100 +} GnssNfwRequestor; + +typedef enum { + GNSS_NFW_REJECTED = 0, + GNSS_NFW_ACCEPTED_NO_LOCATION_PROVIDED = 1, + GNSS_NFW_ACCEPTED_LOCATION_PROVIDED = 2, +} GnssNfwResponseType; + +typedef struct { + char proxyAppPackageName[GNSS_MAX_NFW_STRING_LEN]; + GnssNfwProtocolStack protocolStack; + char otherProtocolStackName[GNSS_MAX_NFW_STRING_LEN]; + GnssNfwRequestor requestor; + char requestorId[GNSS_MAX_NFW_STRING_LEN]; + GnssNfwResponseType responseType; + bool inEmergencyMode; + bool isCachedLocation; +} GnssNfwNotification; + /* ODCPI Request Info */ enum OdcpiRequestType { ODCPI_REQUEST_TYPE_START, @@ -2031,6 +2111,11 @@ typedef std::function<void(const OdcpiRequestInfo& request)> OdcpiRequestCallbac typedef void (*AgnssStatusIpV4Cb)(AGnssExtStatusIpV4 status); /* +* Callback with NFW information. +*/ +typedef void(*NfwStatusCb)(GnssNfwNotification notification); + +/* * Callback with AGNSS(IpV6) status information. * * @param status Will be of type AGnssExtStatusIpV6. @@ -2053,6 +2138,10 @@ typedef void (*LocAgpsCloseResultCb)(bool isSuccess, AGpsExtType agpsType, void* #define SOCKET_DIR_TO_CLIENT "/dev/socket/loc_client/" #define SOCKET_TO_LOCATION_CLIENT_BASE "/dev/socket/loc_client/toclient" +#define SOCKET_TO_EXTERANL_AP_LOCATION_CLIENT_BASE "/dev/socket/loc_client/extap.toclient" + +typedef uint64_t NetworkHandle; +#define NETWORK_HANDLE_UNKNOWN ~0 #ifdef __cplusplus } diff --git a/utils/linked_list.h b/utils/linked_list.h index a85f09a..0b33ecb 100644 --- a/utils/linked_list.h +++ b/utils/linked_list.h @@ -50,6 +50,8 @@ typedef enum /**< Failed because an there were not enough resources. */ eLINKED_LIST_INSUFFICIENT_BUFFER = -5, /**< Failed because an the supplied buffer was too small. */ + eLINKED_LIST_EMPTY = -6 + /**< Failed because list is empty. */ }linked_list_err_type; /*=========================================================================== diff --git a/utils/loc_cfg.cpp b/utils/loc_cfg.cpp index 8160cc1..de887ee 100644 --- a/utils/loc_cfg.cpp +++ b/utils/loc_cfg.cpp @@ -465,14 +465,9 @@ void loc_read_conf(const char* conf_file_name, const loc_param_s_type* config_ta #define LOC_FEATURE_MASK_GTP_WIFI_PREMIUM 0X02 #define LOC_FEATURE_MASK_GTP_CELL_BASIC 0X04 #define LOC_FEATURE_MASK_GTP_CELL_PREMIUM 0X08 -#define LOC_FEATURE_MASK_GTP_AP_CELL_BASIC LOC_FEATURE_MASK_GTP_CELL_BASIC -#define LOC_FEATURE_MASK_GTP_AP_CELL_PREMIUM LOC_FEATURE_MASK_GTP_CELL_PREMIUM #define LOC_FEATURE_MASK_SAP_BASIC 0x40 #define LOC_FEATURE_MASK_SAP_PREMIUM 0X80 -#define LOC_FEATURE_MASK_GTP_WAA_BASIC 0X100 -#define LOC_FEATURE_MASK_GTP_WAA_PREMIUM 0x200 #define LOC_FEATURE_MASK_GTP_MODEM_CELL_BASIC 0X400 -#define LOC_FEATURE_MASK_GTP_MODEM_CELL_PREMIUM 0X800 #define LOC_FEATURE_MASK_ODCPI 0x1000 #define LOC_FEATURE_MASK_FREE_WIFI_SCAN_INJECT 0x2000 #define LOC_FEATURE_MASK_SUPL_WIFI 0x4000 @@ -572,8 +567,6 @@ int loc_read_process_conf(const char* conf_file_name, uint32_t * process_count_p char config_mask = 0; unsigned char proc_list_length=0; int gtp_cell_ap_enabled = 0; - char arg_gtp_waa[LOC_PROCESS_MAX_ARG_STR_LENGTH] = "--"; - char arg_gtp_ap_cell[LOC_PROCESS_MAX_ARG_STR_LENGTH] = "--"; char arg_gtp_modem_cell[LOC_PROCESS_MAX_ARG_STR_LENGTH] = "--"; char arg_gtp_wifi[LOC_PROCESS_MAX_ARG_STR_LENGTH] = "--"; char arg_sap[LOC_PROCESS_MAX_ARG_STR_LENGTH] = "--"; @@ -589,8 +582,6 @@ int loc_read_process_conf(const char* conf_file_name, uint32_t * process_count_p UTIL_READ_CONF(LOC_PATH_GPS_CONF, gps_conf_parameter_table); //Form argument strings - strlcat(arg_gtp_waa, LOC_FEATURE_GTP_WAA, LOC_PROCESS_MAX_ARG_STR_LENGTH-3); - strlcat(arg_gtp_ap_cell, LOC_FEATURE_GTP_AP_CELL, LOC_PROCESS_MAX_ARG_STR_LENGTH-3); strlcat(arg_gtp_modem_cell, LOC_FEATURE_GTP_MODEM_CELL, LOC_PROCESS_MAX_ARG_STR_LENGTH-3); strlcat(arg_gtp_wifi, LOC_FEATURE_GTP_WIFI, LOC_PROCESS_MAX_ARG_STR_LENGTH-3); strlcat(arg_sap, LOC_FEATURE_SAP, LOC_PROCESS_MAX_ARG_STR_LENGTH-3); @@ -622,9 +613,6 @@ int loc_read_process_conf(const char* conf_file_name, uint32_t * process_count_p " Setting GTP WIFI to default mode: DISABLED", __func__, __LINE__); } - //Set service mask for GTP_WAA - LOC_LOGD("%s:%d]: GTP WAA DISABLED", __func__, __LINE__); - //Set service mask for SAP if(strcmp(conf.feature_sap, "PREMIUM") == 0) { LOC_LOGD("%s:%d]: Setting SAP to mode: PREMIUM", __func__, __LINE__); @@ -931,51 +919,13 @@ int loc_read_process_conf(const char* conf_file_name, uint32_t * process_count_p } if(conf.loc_feature_mask & (LOC_FEATURE_MASK_GTP_CELL_BASIC | LOC_FEATURE_MASK_GTP_CELL_PREMIUM )) { - if(loc_service_mask & LOC_FEATURE_MASK_GTP_AP_CELL_BASIC){ - strlcpy(child_proc[j].args[i++], arg_gtp_ap_cell, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - strlcpy(child_proc[j].args[i++], arg_basic, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - strlcpy(child_proc[j].args[i++], arg_gtp_modem_cell, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - strlcpy(child_proc[j].args[i++], arg_disabled, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - } - else if(loc_service_mask & LOC_FEATURE_MASK_GTP_AP_CELL_PREMIUM){ - strlcpy(child_proc[j].args[i++], arg_gtp_ap_cell, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - strlcpy(child_proc[j].args[i++], arg_premium, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - strlcpy(child_proc[j].args[i++], arg_gtp_modem_cell, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - strlcpy(child_proc[j].args[i++], arg_disabled, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - } - else if(loc_service_mask & LOC_FEATURE_MASK_GTP_MODEM_CELL_BASIC) { + if(loc_service_mask & LOC_FEATURE_MASK_GTP_MODEM_CELL_BASIC) { strlcpy(child_proc[j].args[i++], arg_gtp_modem_cell, LOC_PROCESS_MAX_ARG_STR_LENGTH); strlcpy(child_proc[j].args[i++], arg_basic, LOC_PROCESS_MAX_ARG_STR_LENGTH); - strlcpy(child_proc[j].args[i++], arg_gtp_ap_cell, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - strlcpy(child_proc[j].args[i++], arg_disabled, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - } - else if(loc_service_mask & LOC_FEATURE_MASK_GTP_MODEM_CELL_PREMIUM) { - strlcpy(child_proc[j].args[i++], arg_gtp_modem_cell, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - strlcpy(child_proc[j].args[i++], arg_premium, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - strlcpy(child_proc[j].args[i++], arg_gtp_ap_cell, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - strlcpy(child_proc[j].args[i++], arg_disabled, - LOC_PROCESS_MAX_ARG_STR_LENGTH); } else { - strlcpy(child_proc[j].args[i++], arg_gtp_ap_cell, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - strlcpy(child_proc[j].args[i++], arg_disabled, - LOC_PROCESS_MAX_ARG_STR_LENGTH); strlcpy(child_proc[j].args[i++], arg_gtp_modem_cell, LOC_PROCESS_MAX_ARG_STR_LENGTH); strlcpy(child_proc[j].args[i++], arg_disabled, @@ -983,28 +933,6 @@ int loc_read_process_conf(const char* conf_file_name, uint32_t * process_count_p } } if(conf.loc_feature_mask & - (LOC_FEATURE_MASK_GTP_WAA_BASIC | LOC_FEATURE_MASK_GTP_WAA_PREMIUM)) { - if(loc_service_mask & LOC_FEATURE_MASK_GTP_WAA_BASIC) { - strlcpy(child_proc[j].args[i++], arg_gtp_waa, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - strlcpy(child_proc[j].args[i++], arg_basic, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - } - else if(loc_service_mask & LOC_FEATURE_MASK_GTP_WAA_PREMIUM) { - strlcpy(child_proc[j].args[i++], arg_gtp_waa, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - strlcpy(child_proc[j].args[i++], arg_premium, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - } - else - { - strlcpy(child_proc[j].args[i++], arg_gtp_waa, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - strlcpy(child_proc[j].args[i++], arg_disabled, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - } - } - if(conf.loc_feature_mask & (LOC_FEATURE_MASK_SAP_BASIC | LOC_FEATURE_MASK_SAP_PREMIUM)) { if(loc_service_mask & LOC_FEATURE_MASK_SAP_BASIC) { strlcpy(child_proc[j].args[i++], arg_sap, diff --git a/utils/loc_misc_utils.cpp b/utils/loc_misc_utils.cpp index b7c8406..70fdbc3 100644 --- a/utils/loc_misc_utils.cpp +++ b/utils/loc_misc_utils.cpp @@ -30,6 +30,7 @@ #define LOG_TAG "LocSvc_misc_utils" #include <stdio.h> #include <string.h> +#include <dlfcn.h> #include <log_util.h> #include <loc_misc_utils.h> #include <ctype.h> @@ -112,3 +113,33 @@ void loc_util_trim_space(char *org_string) err: return; } + +inline void logDlError(const char* failedCall) { + const char * err = dlerror(); + LOC_LOGe("%s error: %s", failedCall, (nullptr == err) ? "unknown" : err); +} + +void* dlGetSymFromLib(void*& libHandle, const char* libName, const char* symName) +{ + void* sym = nullptr; + if ((nullptr != libHandle || nullptr != libName) && nullptr != symName) { + if (nullptr == libHandle) { + libHandle = dlopen(libName, RTLD_NOW); + if (nullptr == libHandle) { + logDlError("dlopen"); + } + } + // NOT else, as libHandle gets assigned 5 line above + if (nullptr != libHandle) { + sym = dlsym(libHandle, symName); + if (nullptr == sym) { + logDlError("dlsym"); + } + } + } else { + LOC_LOGe("Either libHandle (%p) or libName (%p) must not be null; " + "symName (%p) can not be null.", libHandle, libName, symName); + } + + return sym; +} diff --git a/utils/loc_misc_utils.h b/utils/loc_misc_utils.h index 7d66d84..fad1b6d 100644 --- a/utils/loc_misc_utils.h +++ b/utils/loc_misc_utils.h @@ -92,6 +92,34 @@ SIDE EFFECTS N/A ===========================================================================*/ void loc_util_trim_space(char *org_string); + +/*=========================================================================== +FUNCTION dlGetSymFromLib + +DESCRIPTION + Handy function to get a pointer to a symbol from a library. + + If libHandle is not null, it will be used as the handle to the library. In + that case libName wll not be used; + libHandle is an in / out parameter. + If libHandle is null, libName will be used to dlopen. + Either libHandle or libName must not be nullptr. + symName must not be null. + +DEPENDENCIES + N/A + +RETURN VALUE + pointer to symName. Could be nullptr if + Parameters are incorrect; or + libName can not be opened; or + symName can not be found. + +SIDE EFFECTS + N/A +===========================================================================*/ +void* dlGetSymFromLib(void*& libHandle, const char* libName, const char* symName); + #ifdef __cplusplus } #endif diff --git a/utils/loc_nmea.cpp b/utils/loc_nmea.cpp index e9a8f84..9cd3472 100644 --- a/utils/loc_nmea.cpp +++ b/utils/loc_nmea.cpp @@ -44,9 +44,9 @@ #define SYSTEM_ID_GPS 1 #define SYSTEM_ID_GLONASS 2 #define SYSTEM_ID_GALILEO 3 -// Extended systems -#define SYSTEM_ID_BEIDOU 4 +#define SYSTEM_ID_BDS 4 #define SYSTEM_ID_QZSS 5 +#define SYSTEM_ID_NAVIC 6 //GNSS signal id according to NMEA spec #define SIGNAL_ID_ALL_SIGNALS 0 @@ -74,11 +74,35 @@ #define SIGNAL_ID_GAL_L1A 6 #define SIGNAL_ID_GAL_L1BC 7 -//Extended signal id #define SIGNAL_ID_BDS_B1I 1 -#define SIGNAL_ID_BDS_B1C 2 -#define SIGNAL_ID_BDS_B2I 3 -#define SIGNAL_ID_BDS_B2AI 4 +#define SIGNAL_ID_BDS_B1Q 2 +#define SIGNAL_ID_BDS_B1C 3 +#define SIGNAL_ID_BDS_B1A 4 +#define SIGNAL_ID_BDS_B2A 5 +#define SIGNAL_ID_BDS_B2B 6 +#define SIGNAL_ID_BDS_B2AB 7 +#define SIGNAL_ID_BDS_B3I 8 +#define SIGNAL_ID_BDS_B3Q 9 +#define SIGNAL_ID_BDS_B3A 0xA +#define SIGNAL_ID_BDS_B2I 0xB +#define SIGNAL_ID_BDS_B2Q 0xC + +#define SIGNAL_ID_QZSS_L1CA 1 +#define SIGNAL_ID_QZSS_L1CD 2 +#define SIGNAL_ID_QZSS_L1CP 3 +#define SIGNAL_ID_QZSS_LIS 4 +#define SIGNAL_ID_QZSS_L2CM 5 +#define SIGNAL_ID_QZSS_L2CL 6 +#define SIGNAL_ID_QZSS_L5I 7 +#define SIGNAL_ID_QZSS_L5Q 8 +#define SIGNAL_ID_QZSS_L6D 9 +#define SIGNAL_ID_QZSS_L6E 0xA + +#define SIGNAL_ID_NAVIC_L5SPS 1 +#define SIGNAL_ID_NAVIC_SSPS 2 +#define SIGNAL_ID_NAVIC_L5RS 3 +#define SIGNAL_ID_NAVIC_SRS 4 +#define SIGNAL_ID_NAVIC_L1SPS 5 typedef struct loc_nmea_sv_meta_s @@ -280,13 +304,13 @@ static uint32_t convert_signalType_to_signalId(GnssSignalTypeMask signalType) signalId = SIGNAL_ID_GAL_E5B; break; case GNSS_SIGNAL_QZSS_L1CA: - signalId = SIGNAL_ID_GPS_L1CA; + signalId = SIGNAL_ID_QZSS_L1CA; break; case GNSS_SIGNAL_QZSS_L2: - signalId = SIGNAL_ID_GPS_L2CL; + signalId = SIGNAL_ID_QZSS_L2CL; break; case GNSS_SIGNAL_QZSS_L5: - signalId = SIGNAL_ID_GPS_L5Q; + signalId = SIGNAL_ID_QZSS_L5Q; break; case GNSS_SIGNAL_BEIDOU_B1I: signalId = SIGNAL_ID_BDS_B1I; @@ -298,7 +322,7 @@ static uint32_t convert_signalType_to_signalId(GnssSignalTypeMask signalType) signalId = SIGNAL_ID_BDS_B2I; break; case GNSS_SIGNAL_BEIDOU_B2AI: - signalId = SIGNAL_ID_BDS_B2AI; + signalId = SIGNAL_ID_BDS_B2A; break; default: signalId = SIGNAL_ID_ALL_SIGNALS; @@ -371,7 +395,7 @@ static loc_nmea_sv_meta* loc_nmea_sv_meta_init(loc_nmea_sv_meta& sv_meta, } break; case GNSS_SV_TYPE_QZSS: - sv_meta.talker[0] = 'P'; + sv_meta.talker[0] = 'G'; sv_meta.talker[1] = 'Q'; sv_meta.mask = sv_cache_info.qzss_used_mask; // QZSS SV ids are from 193-197. So keep svIdOffset 0 @@ -383,11 +407,11 @@ static loc_nmea_sv_meta* loc_nmea_sv_meta_init(loc_nmea_sv_meta& sv_meta, } break; case GNSS_SV_TYPE_BEIDOU: - sv_meta.talker[0] = 'P'; - sv_meta.talker[1] = 'Q'; + sv_meta.talker[0] = 'G'; + sv_meta.talker[1] = 'B'; sv_meta.mask = sv_cache_info.bds_used_mask; // BDS SV ids are from 201-235. So keep svIdOffset 0 - sv_meta.systemId = SYSTEM_ID_BEIDOU; + sv_meta.systemId = SYSTEM_ID_BDS; if (GNSS_SIGNAL_BEIDOU_B1I == signalType) { sv_meta.svCount = sv_cache_info.bds_b1_count; } else if (GNSS_SIGNAL_BEIDOU_B2AI == signalType) { @@ -626,7 +650,7 @@ static void loc_nmea_generate_GSV(const GnssSvNotification &svNotify, if (svCount <= 0) { // no svs in view, so just send a blank $--GSV sentence - snprintf(sentence, lengthRemaining, "$%sGSV,1,1,0,%d", talker, sv_meta_p->signalId); + snprintf(sentence, lengthRemaining, "$%sGSV,1,1,0,%X", talker, sv_meta_p->signalId); length = loc_nmea_put_checksum(sentence, bufSize); nmeaArraystr.push_back(sentence); return; @@ -674,6 +698,9 @@ static void loc_nmea_generate_GSV(const GnssSvNotification &svNotify, case GNSS_SV_TYPE_BEIDOU: signalType = GNSS_SIGNAL_BEIDOU_B1I; break; + case GNSS_SV_TYPE_SBAS: + signalType = GNSS_SIGNAL_SBAS_L1; + break; default: LOC_LOGE("NMEA Error unknow constellation type: %d", svNotify.gnssSvs[svNumber - 1].type); @@ -717,7 +744,7 @@ static void loc_nmea_generate_GSV(const GnssSvNotification &svNotify, } // append signalId - length = snprintf(pMarker, lengthRemaining,",%d",sv_meta_p->signalId); + length = snprintf(pMarker, lengthRemaining,",%X",sv_meta_p->signalId); pMarker += length; lengthRemaining -= length; @@ -953,6 +980,7 @@ void loc_nmea_generate_pos(const UlpLocation &location, char sentence[NMEA_SENTENCE_MAX_LENGTH] = {0}; char sentence_DTM[NMEA_SENTENCE_MAX_LENGTH] = {0}; char sentence_RMC[NMEA_SENTENCE_MAX_LENGTH] = {0}; + char sentence_GNS[NMEA_SENTENCE_MAX_LENGTH] = {0}; char sentence_GGA[NMEA_SENTENCE_MAX_LENGTH] = {0}; char* pMarker = sentence; int lengthRemaining = sizeof(sentence); @@ -1051,11 +1079,12 @@ void loc_nmea_generate_pos(const UlpLocation &location, count = loc_nmea_generate_GSA(locationExtended, sentence, sizeof(sentence), loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_QZSS, - GNSS_SIGNAL_QZSS_L1CA, false), nmeaArraystr); + GNSS_SIGNAL_QZSS_L1CA, true), nmeaArraystr); if (count > 0) { svUsedCount += count; - // talker should be default "GP". If GPS, GLO etc is used, it should be "GN" + talker[0] = sv_meta.talker[0]; + talker[1] = sv_meta.talker[1]; } // ---------------------------- @@ -1063,11 +1092,12 @@ void loc_nmea_generate_pos(const UlpLocation &location, // ---------------------------- count = loc_nmea_generate_GSA(locationExtended, sentence, sizeof(sentence), loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_BEIDOU, - GNSS_SIGNAL_BEIDOU_B1I, false), nmeaArraystr); + GNSS_SIGNAL_BEIDOU_B1I, true), nmeaArraystr); if (count > 0) { svUsedCount += count; - // talker should be default "GP". If GPS, GLO etc is used, it should be "GN" + talker[0] = sv_meta.talker[0]; + talker[1] = sv_meta.talker[1]; } // ------------------- @@ -1345,6 +1375,145 @@ void loc_nmea_generate_pos(const UlpLocation &location, length = loc_nmea_put_checksum(sentence_RMC, sizeof(sentence_RMC)); // ------------------- + // ------$--GNS------- + // ------------------- + + pMarker = sentence_GNS; + lengthRemaining = sizeof(sentence_GNS); + + length = snprintf(pMarker, lengthRemaining, "$%sGNS,%02d%02d%02d.%02d," , + talker, utcHours, utcMinutes, utcSeconds, utcMSeconds/10); + + if (length < 0 || length >= lengthRemaining) + { + LOC_LOGE("NMEA Error in string formatting"); + return; + } + pMarker += length; + lengthRemaining -= length; + + if (location.gpsLocation.flags & LOC_GPS_LOCATION_HAS_LAT_LONG) + { + double latitude = ref_lla.lat; + double longitude = ref_lla.lon; + char latHemisphere; + char lonHemisphere; + double latMinutes; + double lonMinutes; + + if (latitude > 0) + { + latHemisphere = 'N'; + } + else + { + latHemisphere = 'S'; + latitude *= -1.0; + } + + if (longitude < 0) + { + lonHemisphere = 'W'; + longitude *= -1.0; + } + else + { + lonHemisphere = 'E'; + } + + latMinutes = fmod(latitude * 60.0 , 60.0); + lonMinutes = fmod(longitude * 60.0 , 60.0); + + length = snprintf(pMarker, lengthRemaining, "%02d%09.6lf,%c,%03d%09.6lf,%c,", + (uint8_t)floor(latitude), latMinutes, latHemisphere, + (uint8_t)floor(longitude),lonMinutes, lonHemisphere); + } + else + { + length = snprintf(pMarker, lengthRemaining,",,,,"); + } + + if (length < 0 || length >= lengthRemaining) + { + LOC_LOGE("NMEA Error in string formatting"); + return; + } + pMarker += length; + lengthRemaining -= length; + + if (!(location.gpsLocation.flags & LOC_GPS_LOCATION_HAS_LAT_LONG)) + // N means no fix + length = snprintf(pMarker, lengthRemaining, "%c,", 'N'); + else if (LOC_NAV_MASK_SBAS_CORRECTION_IONO & locationExtended.navSolutionMask) + // D means differential + length = snprintf(pMarker, lengthRemaining, "%c,", 'D'); + else if (LOC_POS_TECH_MASK_SENSORS == locationExtended.tech_mask) + // E means estimated (dead reckoning) + length = snprintf(pMarker, lengthRemaining, "%c,", 'E'); + else // A means autonomous + length = snprintf(pMarker, lengthRemaining, "%c,", 'A'); + + pMarker += length; + lengthRemaining -= length; + + if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_DOP) { + length = snprintf(pMarker, lengthRemaining, "%02d,%.1f,", + svUsedCount, locationExtended.hdop); + } + else { // no hdop + length = snprintf(pMarker, lengthRemaining, "%02d,,", + svUsedCount); + } + + if (length < 0 || length >= lengthRemaining) + { + LOC_LOGE("NMEA Error in string formatting"); + return; + } + pMarker += length; + lengthRemaining -= length; + + if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL) + { + length = snprintf(pMarker, lengthRemaining, "%.1lf,", + locationExtended.altitudeMeanSeaLevel); + } + else + { + length = snprintf(pMarker, lengthRemaining,","); + } + + if (length < 0 || length >= lengthRemaining) + { + LOC_LOGE("NMEA Error in string formatting"); + return; + } + pMarker += length; + lengthRemaining -= length; + + if ((location.gpsLocation.flags & LOC_GPS_LOCATION_HAS_ALTITUDE) && + (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL)) + { + length = snprintf(pMarker, lengthRemaining, "%.1lf,,", + ref_lla.alt - locationExtended.altitudeMeanSeaLevel); + } + else + { + length = snprintf(pMarker, lengthRemaining,",,"); + } + + pMarker += length; + lengthRemaining -= length; + + // hardcode Navigation Status field to 'V' + length = snprintf(pMarker, lengthRemaining, ",%c", 'V'); + pMarker += length; + lengthRemaining -= length; + + length = loc_nmea_put_checksum(sentence_GNS, sizeof(sentence_GNS)); + + + // ------------------- // ------$--GGA------- // ------------------- @@ -1482,25 +1651,31 @@ void loc_nmea_generate_pos(const UlpLocation &location, // ------$--DTM------- nmeaArraystr.push_back(sentence_DTM); } + // ------$--GNS------- + nmeaArraystr.push_back(sentence_GNS); + if(LOC_GNSS_DATUM_PZ90 == datum_type) { + // ------$--DTM------- + nmeaArraystr.push_back(sentence_DTM); + } // ------$--GGA------- nmeaArraystr.push_back(sentence_GGA); } //Send blank NMEA reports for non-final fixes else { - strlcpy(sentence, "$GPGSA,A,1,,,,,,,,,,,,,,,", sizeof(sentence)); + strlcpy(sentence, "$GPGSA,A,1,,,,,,,,,,,,,,,,", sizeof(sentence)); length = loc_nmea_put_checksum(sentence, sizeof(sentence)); nmeaArraystr.push_back(sentence); - strlcpy(sentence, "$GNGSA,A,1,,,,,,,,,,,,,,,", sizeof(sentence)); + strlcpy(sentence, "$GNGSA,A,1,,,,,,,,,,,,,,,,", sizeof(sentence)); length = loc_nmea_put_checksum(sentence, sizeof(sentence)); nmeaArraystr.push_back(sentence); - strlcpy(sentence, "$PQGSA,A,1,,,,,,,,,,,,,,,", sizeof(sentence)); + strlcpy(sentence, "$GPVTG,,T,,M,,N,,K,N", sizeof(sentence)); length = loc_nmea_put_checksum(sentence, sizeof(sentence)); nmeaArraystr.push_back(sentence); - strlcpy(sentence, "$GPVTG,,T,,M,,N,,K,N", sizeof(sentence)); + strlcpy(sentence, "$GPDTM,,,,,,,,", sizeof(sentence)); length = loc_nmea_put_checksum(sentence, sizeof(sentence)); nmeaArraystr.push_back(sentence); @@ -1508,6 +1683,10 @@ void loc_nmea_generate_pos(const UlpLocation &location, length = loc_nmea_put_checksum(sentence, sizeof(sentence)); nmeaArraystr.push_back(sentence); + strlcpy(sentence, "$GPGNS,,,,,,N,,,,,,,V", sizeof(sentence)); + length = loc_nmea_put_checksum(sentence, sizeof(sentence)); + nmeaArraystr.push_back(sentence); + strlcpy(sentence, "$GPGGA,,,,,,0,,,,,,,,", sizeof(sentence)); length = loc_nmea_put_checksum(sentence, sizeof(sentence)); nmeaArraystr.push_back(sentence); diff --git a/utils/log_util.h b/utils/log_util.h index 4fed90b..ed7e19e 100644 --- a/utils/log_util.h +++ b/utils/log_util.h @@ -47,6 +47,14 @@ #endif /* LOG_TAG */ // LE targets with no logcat support +#ifdef FEATURE_EXTERNAL_AP +#include <syslog.h> +#define ALOGE(...) syslog(LOG_ERR, "LOC_LOGE: " __VA_ARGS__); +#define ALOGW(...) syslog(LOG_WARNING, "LOC_LOGW: " __VA_ARGS__); +#define ALOGI(...) syslog(LOG_NOTICE, "LOC_LOGI: " __VA_ARGS__); +#define ALOGD(...) syslog(LOG_DEBUG, "LOC_LOGD: " __VA_ARGS__); +#define ALOGV(...) syslog(LOG_NOTICE, "LOC_LOGV: " __VA_ARGS__); +#else /* FEATURE_EXTERNAL_AP */ #define TS_PRINTF(format, x...) \ { \ struct timeval tv; \ @@ -64,6 +72,7 @@ #define ALOGI(format, x...) TS_PRINTF("I/%s (%d): " format , LOG_TAG, getpid(), ##x) #define ALOGD(format, x...) TS_PRINTF("D/%s (%d): " format , LOG_TAG, getpid(), ##x) #define ALOGV(format, x...) TS_PRINTF("V/%s (%d): " format , LOG_TAG, getpid(), ##x) +#endif /* FEATURE_EXTERNAL_AP */ #endif /* #if defined (USE_ANDROID_LOGGING) || defined (ANDROID) */ diff --git a/utils/msg_q.c b/utils/msg_q.c index 76c1478..2d49b4a 100644 --- a/utils/msg_q.c +++ b/utils/msg_q.c @@ -267,6 +267,51 @@ msq_q_err_type msg_q_rcv(void* msg_q_data, void** msg_obj) /*=========================================================================== + FUNCTION: msg_q_rmv + + ===========================================================================*/ +msq_q_err_type msg_q_rmv(void* msg_q_data, void** msg_obj) +{ + msq_q_err_type rv; + if (msg_q_data == NULL) { + LOC_LOGE("%s: Invalid msg_q_data parameter!\n", __FUNCTION__); + return eMSG_Q_INVALID_HANDLE; + } + + if (msg_obj == NULL) { + LOC_LOGE("%s: Invalid msg_obj parameter!\n", __FUNCTION__); + return eMSG_Q_INVALID_PARAMETER; + } + + msg_q* p_msg_q = (msg_q*)msg_q_data; + + pthread_mutex_lock(&p_msg_q->list_mutex); + + if (p_msg_q->unblocked) { + LOC_LOGE("%s: Message queue has been unblocked.\n", __FUNCTION__); + pthread_mutex_unlock(&p_msg_q->list_mutex); + return eMSG_Q_UNAVAILABLE_RESOURCE; + } + + if (linked_list_empty(p_msg_q->msg_list)) { + LOC_LOGW("%s: list is empty !!\n", __FUNCTION__); + pthread_mutex_unlock(&p_msg_q->list_mutex); + return eLINKED_LIST_EMPTY; + } + + rv = convert_linked_list_err_type(linked_list_remove(p_msg_q->msg_list, msg_obj)); + + pthread_mutex_unlock(&p_msg_q->list_mutex); + + LOC_LOGV("%s: Removed message %p rv = %d\n", __FUNCTION__, *msg_obj, rv); + + return rv; +} + + + +/*=========================================================================== + FUNCTION: msg_q_flush ===========================================================================*/ diff --git a/utils/msg_q.h b/utils/msg_q.h index 453b8ce..16df494 100644 --- a/utils/msg_q.h +++ b/utils/msg_q.h @@ -158,6 +158,29 @@ SIDE EFFECTS msq_q_err_type msg_q_rcv(void* msg_q_data, void** msg_obj); /*=========================================================================== +FUNCTION msg_q_rmv + +DESCRIPTION + Remove data from the message queue. msg_obj is the oldest message received + and pointer is simply removed from message queue. + + msg_q_data: Message Queue to copy data from into msgp. + msg_obj: Pointer to space to copy msg_q contents to. + +DEPENDENCIES + N/A + +RETURN VALUE + Look at error codes above. + +SIDE EFFECTS + N/A + +===========================================================================*/ +msq_q_err_type msg_q_rmv(void* msg_q_data, void** msg_obj); + + +/*=========================================================================== FUNCTION msg_q_flush DESCRIPTION |