From eaf7e54b54a31c571560bf5fe869bb235a2aacaf Mon Sep 17 00:00:00 2001 From: Saurabh Srivastava Date: Sun, 20 May 2018 19:29:46 +0530 Subject: [PATCH] FR 45651 - GNSS SV/Constellation Control Adding support for configuring GNSS SVs and constellations to be used. Change-Id: I47d5cd9d08ac9aaf633be2fe3b1bd152a2f4293b CRs-Fixed: 2184871 --- android/Gnss.cpp | 4 + android/GnssConfiguration.cpp | 57 ++- android/GnssConfiguration.h | 3 + core/LocAdapterBase.cpp | 5 + core/LocAdapterBase.h | 2 + core/LocApiBase.cpp | 42 ++- core/LocApiBase.h | 9 + gnss/GnssAdapter.cpp | 538 +++++++++++++++++++++++++++++ gnss/GnssAdapter.h | 40 ++- gnss/location_gnss.cpp | 43 ++- location/LocationAPI.cpp | 15 + location/LocationAPI.h | 16 + location/LocationAPIClientBase.cpp | 89 +++-- location/LocationAPIClientBase.h | 28 +- location/LocationDataTypes.h | 74 +++- location/location_interface.h | 4 + utils/gps_extended_c.h | 30 +- 17 files changed, 956 insertions(+), 43 deletions(-) diff --git a/android/Gnss.cpp b/android/Gnss.cpp index 878cd202..d31a18bb 100644 --- a/android/Gnss.cpp +++ b/android/Gnss.cpp @@ -234,6 +234,10 @@ Return Gnss::updateConfiguration(GnssConfig& gnssConfig) { 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; + } } return true; } diff --git a/android/GnssConfiguration.cpp b/android/GnssConfiguration.cpp index 9eeceac2..cee928ab 100644 --- a/android/GnssConfiguration.cpp +++ b/android/GnssConfiguration.cpp @@ -23,6 +23,7 @@ #include #include "Gnss.h" #include "GnssConfiguration.h" +#include namespace android { namespace hardware { @@ -30,6 +31,8 @@ namespace gnss { namespace V1_1 { namespace implementation { +using ::android::hardware::gnss::V1_0::GnssConstellationType; + GnssConfiguration::GnssConfiguration(Gnss* gnss) : mGnss(gnss) { } @@ -222,10 +225,60 @@ Return GnssConfiguration::setEmergencySuplPdn(bool enabled) { // Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow. Return GnssConfiguration::setBlacklist( - const hidl_vec& /*blacklist*/) { + const hidl_vec& blacklist) { ENTRY_LOG_CALLFLOW(); - return true; + if (nullptr == mGnss) { + LOC_LOGe("mGnss is null"); + return false; + } + + 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++) { + setBlacklistedSource(source, blacklist[idx]); + config.blacklistedSvIds.push_back(source); + } + + return mGnss->updateConfiguration(config); +} + +void GnssConfiguration::setBlacklistedSource( + GnssSvIdSource& copyToSource, + const GnssConfiguration::BlacklistedSource& copyFromSource) { + + copyToSource.size = sizeof(GnssSvIdSource); + + switch(copyFromSource.constellation) { + case GnssConstellationType::GPS: + copyToSource.constellation = GNSS_SV_TYPE_GPS; + break; + case GnssConstellationType::SBAS: + copyToSource.constellation = GNSS_SV_TYPE_SBAS; + break; + case GnssConstellationType::GLONASS: + copyToSource.constellation = GNSS_SV_TYPE_GLONASS; + break; + case GnssConstellationType::QZSS: + copyToSource.constellation = GNSS_SV_TYPE_QZSS; + break; + case GnssConstellationType::BEIDOU: + copyToSource.constellation = GNSS_SV_TYPE_BEIDOU; + break; + case GnssConstellationType::GALILEO: + copyToSource.constellation = GNSS_SV_TYPE_GALILEO; + break; + default: + copyToSource.constellation = GNSS_SV_TYPE_UNKNOWN; + break; + } + + copyToSource.svId = copyFromSource.svid; } } // namespace implementation diff --git a/android/GnssConfiguration.h b/android/GnssConfiguration.h index f46f6071..15ee2906 100644 --- a/android/GnssConfiguration.h +++ b/android/GnssConfiguration.h @@ -64,6 +64,9 @@ struct GnssConfiguration : public IGnssConfiguration { private: Gnss* mGnss = nullptr; + void setBlacklistedSource( + GnssSvIdSource& copyToSource, + const GnssConfiguration::BlacklistedSource& copyFromSource); }; } // namespace implementation diff --git a/core/LocAdapterBase.cpp b/core/LocAdapterBase.cpp index c11b93d8..5f98456c 100644 --- a/core/LocAdapterBase.cpp +++ b/core/LocAdapterBase.cpp @@ -167,5 +167,10 @@ bool LocAdapterBase:: GpsLocationExtended& /*location_extended*/, LocPosTechMask /*tech_mask*/) DEFAULT_IMPL(false) +void LocAdapterBase::reportGnssSvIdConfigEvent(const GnssSvIdConfig& /*config*/) +DEFAULT_IMPL() + +void LocAdapterBase::reportGnssSvTypeConfigEvent(const GnssSvTypeConfig& /*config*/) +DEFAULT_IMPL() } // namespace loc_core diff --git a/core/LocAdapterBase.h b/core/LocAdapterBase.h index 263855a7..79cb25cb 100644 --- a/core/LocAdapterBase.h +++ b/core/LocAdapterBase.h @@ -157,6 +157,8 @@ public: virtual bool reportWwanZppFix(LocGpsLocation &zppLoc); virtual bool reportZppBestAvailableFix(LocGpsLocation &zppLoc, GpsLocationExtended &location_extended, LocPosTechMask tech_mask); + virtual void reportGnssSvIdConfigEvent(const GnssSvIdConfig& config); + virtual void reportGnssSvTypeConfigEvent(const GnssSvTypeConfig& config); }; } // namespace loc_core diff --git a/core/LocApiBase.cpp b/core/LocApiBase.cpp index 45a0ec48..9c547261 100644 --- a/core/LocApiBase.cpp +++ b/core/LocApiBase.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2014, 2016-2017 The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2014, 2016-2018 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 @@ -423,6 +423,28 @@ void LocApiBase::reportGnssMeasurementData(GnssMeasurementsNotification& measure TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportGnssMeasurementDataEvent(measurements, msInWeek)); } +void LocApiBase::reportGnssSvIdConfig(const GnssSvIdConfig& config) +{ + // Print the config + LOC_LOGv("gloBlacklistSvMask: %" PRIu64 ", bdsBlacklistSvMask: %" PRIu64 ",\n" + "qzssBlacklistSvMask: %" PRIu64 ", galBlacklistSvMask: %" PRIu64, + config.gloBlacklistSvMask, config.bdsBlacklistSvMask, + config.qzssBlacklistSvMask, config.galBlacklistSvMask); + + // Loop through adapters, and deliver to all adapters. + TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportGnssSvIdConfigEvent(config)); +} + +void LocApiBase::reportGnssSvTypeConfig(const GnssSvTypeConfig& config) +{ + // Print the config + LOC_LOGv("blacklistedMask: %" PRIu64 ", enabledMask: %" PRIu64, + config.blacklistedSvTypesMask, config.enabledSvTypesMask); + + // Loop through adapters, and deliver to all adapters. + TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportGnssSvTypeConfigEvent(config)); +} + enum loc_api_adapter_err LocApiBase:: open(LOC_API_ADAPTER_EVENT_MASK_T /*mask*/) DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) @@ -591,4 +613,22 @@ LocationError LocApiBase:: setXtraVersionCheckSync(uint32_t /*check*/) DEFAULT_IMPL(LOCATION_ERROR_SUCCESS) +LocationError LocApiBase::setBlacklistSvSync(const GnssSvIdConfig& /*config*/) +DEFAULT_IMPL(LOCATION_ERROR_SUCCESS) + +void LocApiBase::setBlacklistSv(const GnssSvIdConfig& /*config*/) +DEFAULT_IMPL() + +void LocApiBase::getBlacklistSv() +DEFAULT_IMPL() + +void LocApiBase::setConstellationControl(const GnssSvTypeConfig& /*config*/) +DEFAULT_IMPL() + +void LocApiBase::getConstellationControl() +DEFAULT_IMPL() + +void LocApiBase::resetConstellationControl() +DEFAULT_IMPL() + } // namespace loc_core diff --git a/core/LocApiBase.h b/core/LocApiBase.h index f9fdf4d6..17ccc4ef 100644 --- a/core/LocApiBase.h +++ b/core/LocApiBase.h @@ -157,6 +157,8 @@ public: void reportWwanZppFix(LocGpsLocation &zppLoc); void reportZppBestAvailableFix(LocGpsLocation &zppLoc, GpsLocationExtended &location_extended, LocPosTechMask tech_mask); + void reportGnssSvIdConfig(const GnssSvIdConfig& config); + void reportGnssSvTypeConfig(const GnssSvTypeConfig& config); // downward calls // All below functions are to be defined by adapter specific modules: @@ -260,6 +262,13 @@ public: virtual LocationError setXtraVersionCheckSync(uint32_t check); + /* Requests for SV/Constellation Control */ + virtual LocationError setBlacklistSvSync(const GnssSvIdConfig& config); + virtual void setBlacklistSv(const GnssSvIdConfig& config); + virtual void getBlacklistSv(); + virtual void setConstellationControl(const GnssSvTypeConfig& config); + virtual void getConstellationControl(); + virtual void resetConstellationControl(); }; typedef LocApiBase* (getLocApi_t)(LOC_API_ADAPTER_EVENT_MASK_T exMask, diff --git a/gnss/GnssAdapter.cpp b/gnss/GnssAdapter.cpp index ab2dac56..cedd27b6 100644 --- a/gnss/GnssAdapter.cpp +++ b/gnss/GnssAdapter.cpp @@ -74,6 +74,9 @@ GnssAdapter::GnssAdapter() : mControlCallbacks(), mPowerVoteId(0), mNmeaMask(0), + mGnssSvIdConfig(), + mGnssSvTypeConfig(), + mGnssSvTypeConfigCb(nullptr), mNiData(), mAgpsManager(), mAgpsCbInfo(), @@ -1037,6 +1040,24 @@ GnssAdapter::gnssUpdateConfigCommand(GnssConfig config) } } } + if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT) { + index++; + // 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; + } + } configCollectiveResponse->returnToSender(errsList); })); } @@ -1051,6 +1072,521 @@ GnssAdapter::gnssUpdateConfigCommand(GnssConfig config) return ids; } +void +GnssAdapter::gnssSvIdConfigUpdate(const std::vector& blacklistedSvIds) +{ + // Clear the existing config + memset(&mGnssSvIdConfig, 0, sizeof(GnssSvIdConfig)); + + // Convert the sv id lists to masks + convertToGnssSvIdConfig(blacklistedSvIds, mGnssSvIdConfig); + + // Now send to Modem + gnssSvIdConfigUpdate(); +} + +void +GnssAdapter::gnssSvIdConfigUpdate() +{ + LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64 + ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64, + mGnssSvIdConfig.bdsBlacklistSvMask, mGnssSvIdConfig.gloBlacklistSvMask, + mGnssSvIdConfig.qzssBlacklistSvMask, mGnssSvIdConfig.galBlacklistSvMask); + + // Now set required blacklisted SVs + mLocApi->setBlacklistSv(mGnssSvIdConfig); +} + +LocationError +GnssAdapter::gnssSvIdConfigUpdateSync(const std::vector& blacklistedSvIds) +{ + // Clear the existing config + memset(&mGnssSvIdConfig, 0, sizeof(GnssSvIdConfig)); + + // Convert the sv id lists to masks + convertToGnssSvIdConfig(blacklistedSvIds, mGnssSvIdConfig); + + // Now send to Modem + return gnssSvIdConfigUpdateSync(); +} + +LocationError +GnssAdapter::gnssSvIdConfigUpdateSync() +{ + LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64 + ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64, + mGnssSvIdConfig.bdsBlacklistSvMask, mGnssSvIdConfig.gloBlacklistSvMask, + mGnssSvIdConfig.qzssBlacklistSvMask, mGnssSvIdConfig.galBlacklistSvMask); + + // Now set required blacklisted SVs + return mLocApi->setBlacklistSvSync(mGnssSvIdConfig); +} + +uint32_t* +GnssAdapter::gnssGetConfigCommand(GnssConfigFlagsMask configMask) { + + // count the number of bits set + GnssConfigFlagsMask flagsCopy = configMask; + size_t count = 0; + while (flagsCopy > 0) { + if (flagsCopy & 1) { + count++; + } + flagsCopy >>= 1; + } + std::string idsString = "["; + uint32_t* ids = NULL; + if (count > 0) { + ids = new uint32_t[count]; + if (nullptr == ids) { + LOC_LOGe("new allocation failed, fatal error."); + return nullptr; + } + for (size_t i=0; i < count; ++i) { + ids[i] = generateSessionId(); + IF_LOC_LOGD { + idsString += std::to_string(ids[i]) + " "; + } + } + } + idsString += "]"; + + LOC_LOGd("ids %s flags 0x%X", idsString.c_str(), configMask); + + struct MsgGnssGetConfig : public LocMsg { + GnssAdapter& mAdapter; + LocApiBase& mApi; + GnssConfigFlagsMask mConfigMask; + uint32_t* mIds; + size_t mCount; + inline MsgGnssGetConfig(GnssAdapter& adapter, + LocApiBase& api, + GnssConfigFlagsMask configMask, + uint32_t* ids, + size_t count) : + LocMsg(), + mAdapter(adapter), + mApi(api), + mConfigMask(configMask), + mIds(ids), + mCount(count) {} + inline virtual ~MsgGnssGetConfig() + { + delete[] mIds; + } + inline virtual void proc() const { + + LocationError* errs = new LocationError[mCount]; + LocationError err = LOCATION_ERROR_SUCCESS; + uint32_t index = 0; + + if (nullptr == errs) { + LOC_LOGE("%s] new allocation failed, fatal error.", __func__); + return; + } + + if (mConfigMask & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) { + if (index < mCount) { + errs[index++] = LOCATION_ERROR_NOT_SUPPORTED; + } + } + if (mConfigMask & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) { + if (index < mCount) { + errs[index++] = LOCATION_ERROR_NOT_SUPPORTED; + } + } + if (mConfigMask & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) { + if (index < mCount) { + errs[index++] = LOCATION_ERROR_NOT_SUPPORTED; + } + } + if (mConfigMask & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) { + if (index < mCount) { + errs[index++] = LOCATION_ERROR_NOT_SUPPORTED; + } + } + if (mConfigMask & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) { + if (index < mCount) { + errs[index++] = LOCATION_ERROR_NOT_SUPPORTED; + } + } + if (mConfigMask & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) { + if (index < mCount) { + errs[index++] = LOCATION_ERROR_NOT_SUPPORTED; + } + } + if (mConfigMask & GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) { + if (index < mCount) { + errs[index++] = LOCATION_ERROR_NOT_SUPPORTED; + } + } + if (mConfigMask & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) { + if (index < mCount) { + errs[index++] = LOCATION_ERROR_NOT_SUPPORTED; + } + } + if (mConfigMask & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) { + if (index < mCount) { + errs[index++] = LOCATION_ERROR_NOT_SUPPORTED; + } + } + if (mConfigMask & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) { + err = LOCATION_ERROR_NOT_SUPPORTED; + if (index < mCount) { + errs[index++] = LOCATION_ERROR_NOT_SUPPORTED; + } + } + if (mConfigMask & GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT) { + // Check if feature is supported + if (!ContextBase::isFeatureSupported( + LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) { + LOC_LOGe("Feature not supported."); + err = LOCATION_ERROR_NOT_SUPPORTED; + } else { + // Send request to Modem to fetch the config + mApi.getBlacklistSv(); + err = LOCATION_ERROR_SUCCESS; + } + if (index < mCount) { + errs[index++] = err; + } + } + + mAdapter.reportResponse(index, errs, mIds); + delete[] errs; + } + }; + + if (NULL != ids) { + sendMsg(new MsgGnssGetConfig(*this, *mLocApi, configMask, ids, count)); + } else { + LOC_LOGe("No GNSS config items to Get"); + } + + return ids; +} + +void +GnssAdapter::convertToGnssSvIdConfig( + const std::vector& blacklistedSvIds, GnssSvIdConfig& config) +{ + config.size = sizeof(GnssSvIdConfig); + + // Empty vector => Clear any previous blacklisted SVs + if (0 == blacklistedSvIds.size()) { + config.gloBlacklistSvMask = 0; + config.bdsBlacklistSvMask = 0; + config.qzssBlacklistSvMask = 0; + config.galBlacklistSvMask = 0; + } else { + // Parse the vector and convert SV IDs to mask values + for (GnssSvIdSource source : blacklistedSvIds) { + uint64_t* svMaskPtr = NULL; + GnssSvId initialSvId = 0; + switch(source.constellation) { + case GNSS_SV_TYPE_GLONASS: + svMaskPtr = &config.gloBlacklistSvMask; + initialSvId = GNSS_SV_CONFIG_GLO_INITIAL_SV_ID; + break; + case GNSS_SV_TYPE_BEIDOU: + svMaskPtr = &config.bdsBlacklistSvMask; + initialSvId = GNSS_SV_CONFIG_BDS_INITIAL_SV_ID; + break; + case GNSS_SV_TYPE_QZSS: + svMaskPtr = &config.qzssBlacklistSvMask; + initialSvId = GNSS_SV_CONFIG_QZSS_INITIAL_SV_ID; + break; + case GNSS_SV_TYPE_GALILEO: + svMaskPtr = &config.galBlacklistSvMask; + initialSvId = GNSS_SV_CONFIG_GAL_INITIAL_SV_ID; + break; + default: + break; + } + + if (NULL == svMaskPtr) { + LOC_LOGe("Invalid constellation %d", source.constellation); + } else { + // SV ID 0 = All SV IDs + if (0 == source.svId) { + *svMaskPtr = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK; + } else if (source.svId < initialSvId || source.svId >= initialSvId + 64) { + LOC_LOGe("Invalid sv id %d for sv type %d", + source.svId, source.constellation); + } else { + *svMaskPtr |= (1 << (source.svId - initialSvId)); + } + } + } + } +} + +void GnssAdapter::convertFromGnssSvIdConfig( + const GnssSvIdConfig& svConfig, GnssConfig& config) +{ + // Convert blacklisted SV mask values to vectors + if (svConfig.bdsBlacklistSvMask) { + convertGnssSvIdMaskToList( + svConfig.bdsBlacklistSvMask, config.blacklistedSvIds, + GNSS_SV_CONFIG_BDS_INITIAL_SV_ID, GNSS_SV_TYPE_BEIDOU); + config.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT; + } + if (svConfig.galBlacklistSvMask) { + convertGnssSvIdMaskToList( + svConfig.galBlacklistSvMask, config.blacklistedSvIds, + GNSS_SV_CONFIG_GAL_INITIAL_SV_ID, GNSS_SV_TYPE_GALILEO); + config.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT; + } + if (svConfig.gloBlacklistSvMask) { + convertGnssSvIdMaskToList( + svConfig.gloBlacklistSvMask, config.blacklistedSvIds, + GNSS_SV_CONFIG_GLO_INITIAL_SV_ID, GNSS_SV_TYPE_GLONASS); + config.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT; + } + if (svConfig.qzssBlacklistSvMask) { + convertGnssSvIdMaskToList( + svConfig.qzssBlacklistSvMask, config.blacklistedSvIds, + GNSS_SV_CONFIG_QZSS_INITIAL_SV_ID, GNSS_SV_TYPE_QZSS); + config.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT; + } +} + +void GnssAdapter::convertGnssSvIdMaskToList( + uint64_t svIdMask, std::vector& svIds, + GnssSvId initialSvId, GnssSvType svType) +{ + GnssSvIdSource source = {}; + source.size = sizeof(GnssSvIdSource); + source.constellation = svType; + + // SV ID 0 => All SV IDs in mask + if (GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK == svIdMask) { + source.svId = 0; + svIds.push_back(source); + return; + } + + // Convert each bit in svIdMask to vector entry + uint32_t bitNumber = 0; + while (svIdMask > 0) { + if (svIdMask & 0x1) { + source.svId = bitNumber + initialSvId; + svIds.push_back(source); + } + bitNumber++; + svIdMask >>= 1; + } +} + +void GnssAdapter::reportGnssSvIdConfigEvent(const GnssSvIdConfig& config) +{ + struct MsgReportGnssSvIdConfig : public LocMsg { + GnssAdapter& mAdapter; + const GnssSvIdConfig mConfig; + inline MsgReportGnssSvIdConfig(GnssAdapter& adapter, + const GnssSvIdConfig& config) : + LocMsg(), + mAdapter(adapter), + mConfig(config) {} + inline virtual void proc() const { + mAdapter.reportGnssSvIdConfig(mConfig); + } + }; + + sendMsg(new MsgReportGnssSvIdConfig(*this, config)); +} + +void GnssAdapter::reportGnssSvIdConfig(const GnssSvIdConfig& svIdConfig) +{ + GnssConfig config = {}; + config.size = sizeof(GnssConfig); + + // Invoke control clients config callback + if (nullptr != mControlCallbacks.gnssConfigCb && + svIdConfig.size == sizeof(GnssSvIdConfig)) { + convertFromGnssSvIdConfig(svIdConfig, config); + LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64 + ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64, + svIdConfig.bdsBlacklistSvMask, svIdConfig.gloBlacklistSvMask, + svIdConfig.qzssBlacklistSvMask, svIdConfig.galBlacklistSvMask); + mControlCallbacks.gnssConfigCb(config); + } else { + LOC_LOGe("Failed to report, size %d", (uint32_t)config.size); + } +} + +void +GnssAdapter::gnssUpdateSvTypeConfigCommand(GnssSvTypeConfig config) +{ + struct MsgGnssUpdateSvTypeConfig : public LocMsg { + GnssAdapter* mAdapter; + LocApiBase* mApi; + GnssSvTypeConfig mConfig; + inline MsgGnssUpdateSvTypeConfig( + GnssAdapter* adapter, + LocApiBase* api, + GnssSvTypeConfig& config) : + LocMsg(), + mAdapter(adapter), + mApi(api), + mConfig(config) {} + inline virtual void proc() const { + + // Check if feature is supported + if (!ContextBase::isFeatureSupported( + LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) { + LOC_LOGe("Feature not supported."); + } else { + // Send update request to modem + mAdapter->gnssSvTypeConfigUpdate(mConfig); + } + } + }; + + sendMsg(new MsgGnssUpdateSvTypeConfig(this, mLocApi, config)); +} + +void +GnssAdapter::gnssSvTypeConfigUpdate(const GnssSvTypeConfig& config) +{ + gnssSetSvTypeConfig(config); + gnssSvTypeConfigUpdate(); +} + +void +GnssAdapter::gnssSvTypeConfigUpdate() +{ + LOC_LOGd("constellations blacklisted 0x%" PRIx64 ", enabled 0x%" PRIx64, + mGnssSvTypeConfig.blacklistedSvTypesMask, mGnssSvTypeConfig.enabledSvTypesMask); + + if (mGnssSvTypeConfig.size == sizeof(mGnssSvTypeConfig)) { + GnssSvIdConfig blacklistConfig = {}; + // Revert to previously blacklisted SVs for each enabled constellation + blacklistConfig = mGnssSvIdConfig; + // Blacklist all SVs for each disabled constellation + if (mGnssSvTypeConfig.blacklistedSvTypesMask) { + if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_GLO_BIT) { + blacklistConfig.gloBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK; + } + if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_BDS_BIT) { + blacklistConfig.bdsBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK; + } + if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_QZSS_BIT) { + blacklistConfig.qzssBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK; + } + if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_GAL_BIT) { + blacklistConfig.galBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK; + } + } + + // Send blacklist info + mLocApi->setBlacklistSv(blacklistConfig); + + // Send only enabled constellation config + if (mGnssSvTypeConfig.enabledSvTypesMask) { + GnssSvTypeConfig svTypeConfig = {sizeof(GnssSvTypeConfig), 0, 0}; + svTypeConfig.enabledSvTypesMask = mGnssSvTypeConfig.enabledSvTypesMask; + mLocApi->setConstellationControl(svTypeConfig); + } + } else { + LOC_LOGE("Invalid GnssSvTypeConfig size"); + } +} + +void +GnssAdapter::gnssGetSvTypeConfigCommand(GnssSvTypeConfigCallback callback) +{ + struct MsgGnssGetSvTypeConfig : public LocMsg { + GnssAdapter* mAdapter; + LocApiBase* mApi; + GnssSvTypeConfigCallback mCallback; + inline MsgGnssGetSvTypeConfig( + GnssAdapter* adapter, + LocApiBase* api, + GnssSvTypeConfigCallback callback) : + LocMsg(), + mAdapter(adapter), + mApi(api), + mCallback(callback) {} + inline virtual void proc() const { + + if (!ContextBase::isFeatureSupported( + LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) { + LOC_LOGe("Feature not supported."); + } else { + // Save the callback + mAdapter->gnssSetSvTypeConfigCallback(mCallback); + // Send GET request to modem + mApi->getConstellationControl(); + } + } + }; + + sendMsg(new MsgGnssGetSvTypeConfig(this, mLocApi, callback)); +} + +void +GnssAdapter::gnssResetSvTypeConfigCommand() +{ + struct MsgGnssResetSvTypeConfig : public LocMsg { + GnssAdapter* mAdapter; + LocApiBase* mApi; + inline MsgGnssResetSvTypeConfig( + GnssAdapter* adapter, + LocApiBase* api) : + LocMsg(), + mAdapter(adapter), + mApi(api) {} + inline virtual void proc() const { + + if (!ContextBase::isFeatureSupported( + LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) { + LOC_LOGe("Feature not supported."); + } else { + // Reset constellation config + mAdapter->gnssSetSvTypeConfig({sizeof(GnssSvTypeConfig), 0, 0}); + // Re-enforce SV blacklist config + mAdapter->gnssSvIdConfigUpdate(); + // Send reset request to modem + mApi->resetConstellationControl(); + } + } + }; + + sendMsg(new MsgGnssResetSvTypeConfig(this, mLocApi)); +} + +void GnssAdapter::reportGnssSvTypeConfigEvent(const GnssSvTypeConfig& config) +{ + struct MsgReportGnssSvTypeConfig : public LocMsg { + GnssAdapter& mAdapter; + const GnssSvTypeConfig mConfig; + inline MsgReportGnssSvTypeConfig(GnssAdapter& adapter, + const GnssSvTypeConfig& config) : + LocMsg(), + mAdapter(adapter), + mConfig(config) {} + inline virtual void proc() const { + mAdapter.reportGnssSvTypeConfig(mConfig); + } + }; + + sendMsg(new MsgReportGnssSvTypeConfig(*this, config)); +} + +void GnssAdapter::reportGnssSvTypeConfig(const GnssSvTypeConfig& config) +{ + // Invoke Get SV Type Callback + if (NULL != mGnssSvTypeConfigCb && + config.size == sizeof(GnssSvTypeConfig)) { + LOC_LOGd("constellations blacklisted 0x%" PRIx64 ", enabled 0x%" PRIx64, + config.blacklistedSvTypesMask, config.enabledSvTypesMask); + mGnssSvTypeConfigCb(config); + } else { + LOC_LOGe("Failed to report, size %d", (uint32_t)config.size); + } +} + void GnssAdapter::deleteAidingData(const GnssAidingData &data, uint32_t sessionId) { mLocApi->deleteAidingData(data, new LocApiResponse(*getContext(), [this, sessionId] (LocationError err) { @@ -1345,6 +1881,8 @@ GnssAdapter::handleEngineUpEvent() mAdapter.broadcastCapabilities(mAdapter.getCapabilities()); // restart sessions mAdapter.restartSessions(); + mAdapter.gnssSvIdConfigUpdate(); + mAdapter.gnssSvTypeConfigUpdate(); } }; diff --git a/gnss/GnssAdapter.h b/gnss/GnssAdapter.h index c9491f06..b906e484 100644 --- a/gnss/GnssAdapter.h +++ b/gnss/GnssAdapter.h @@ -103,6 +103,9 @@ class GnssAdapter : public LocAdapterBase { LocationControlCallbacks mControlCallbacks; uint32_t mPowerVoteId; uint32_t mNmeaMask; + GnssSvIdConfig mGnssSvIdConfig; + GnssSvTypeConfig mGnssSvTypeConfig; + GnssSvTypeConfigCallback mGnssSvTypeConfigCb; /* ==== NI ============================================================================= */ NiData mNiData; @@ -200,7 +203,7 @@ public: bool hasNiNotifyCallback(LocationAPI* client); NiData& getNiData() { return mNiData; } - /* ==== CONTROL ======================================================================== */ + /* ==== CONTROL CLIENT ================================================================= */ /* ======== COMMANDS ====(Called from Client Thread)==================================== */ uint32_t enableCommand(LocationTechnologyType techType); void disableCommand(uint32_t id); @@ -210,10 +213,34 @@ public: void requestUlpCommand(); void initEngHubProxyCommand(); uint32_t* gnssUpdateConfigCommand(GnssConfig config); + uint32_t* gnssGetConfigCommand(GnssConfigFlagsMask mask); uint32_t gnssDeleteAidingDataCommand(GnssAidingData& data); void deleteAidingData(const GnssAidingData &data, uint32_t sessionId); void gnssUpdateXtraThrottleCommand(const bool enabled); + /* ==== GNSS SV TYPE CONFIG ============================================================ */ + /* ==== COMMANDS ====(Called from Client Thread)======================================== */ + /* ==== These commands are received directly from client bypassing Location API ======== */ + void gnssUpdateSvTypeConfigCommand(GnssSvTypeConfig config); + void gnssGetSvTypeConfigCommand(GnssSvTypeConfigCallback callback); + void gnssResetSvTypeConfigCommand(); + + /* ==== UTILITIES ====================================================================== */ + LocationError gnssSvIdConfigUpdateSync(const std::vector& blacklistedSvIds); + LocationError gnssSvIdConfigUpdateSync(); + void gnssSvIdConfigUpdate(const std::vector& blacklistedSvIds); + void gnssSvIdConfigUpdate(); + void gnssSvTypeConfigUpdate(const GnssSvTypeConfig& config); + void gnssSvTypeConfigUpdate(); + inline void gnssSetSvTypeConfig(const GnssSvTypeConfig& config) + { mGnssSvTypeConfig = config; } + inline void gnssSetSvTypeConfigCallback(GnssSvTypeConfigCallback callback) + { mGnssSvTypeConfigCb = callback; } + inline GnssSvTypeConfigCallback gnssGetSvTypeConfigCallback() + { return mGnssSvTypeConfigCb; } + + /* ========= AGPS ====================================================================== */ + /* ======== COMMANDS ====(Called from Client Thread)==================================== */ void initDefaultAgpsCommand(); void initAgpsCommand(const AgpsCbInfo& cbInfo); void dataConnOpenCommand(AGpsExtType agpsType, @@ -251,6 +278,8 @@ public: int msInWeek); virtual void reportSvMeasurementEvent(GnssSvMeasurementSet &svMeasurementSet); virtual void reportSvPolynomialEvent(GnssSvPolynomial &svPolynomial); + virtual void reportGnssSvIdConfigEvent(const GnssSvIdConfig& config); + virtual void reportGnssSvTypeConfigEvent(const GnssSvTypeConfig& config); virtual bool requestATL(int connHandle, LocAGpsType agps_type, LocApnTypeMask mask); virtual bool releaseATL(int connHandle); @@ -271,6 +300,8 @@ public: void reportNmea(const char* nmea, size_t length); bool requestNiNotify(const GnssNiNotification& notify, const void* data); void reportGnssMeasurementData(const GnssMeasurementsNotification& measurements); + void reportGnssSvIdConfig(const GnssSvIdConfig& config); + void reportGnssSvTypeConfig(const GnssSvTypeConfig& config); /*======== GNSSDEBUG ================================================================*/ bool getDebugReport(GnssDebugReport& report); @@ -296,6 +327,13 @@ public: static void convertSatelliteInfo(std::vector& out, const GnssSvType& in_constellation, const SystemStatusReports& in); + static void convertToGnssSvIdConfig( + const std::vector& blacklistedSvIds, GnssSvIdConfig& config); + static void convertFromGnssSvIdConfig( + const GnssSvIdConfig& svConfig, GnssConfig& config); + static void convertGnssSvIdMaskToList( + uint64_t svIdMask, std::vector& svIds, + GnssSvId initialSvId, GnssSvType svType); void injectLocationCommand(double latitude, double longitude, float accuracy); void injectTimeCommand(int64_t time, int64_t timeReference, int32_t uncertainty); diff --git a/gnss/location_gnss.cpp b/gnss/location_gnss.cpp index 3e989c97..0dac13d5 100644 --- a/gnss/location_gnss.cpp +++ b/gnss/location_gnss.cpp @@ -51,6 +51,11 @@ static void setControlCallbacks(LocationControlCallbacks& controlCallbacks); static uint32_t enable(LocationTechnologyType techType); static void disable(uint32_t id); static uint32_t* gnssUpdateConfig(GnssConfig config); +static uint32_t* gnssGetConfig(GnssConfigFlagsMask mask); + +static void gnssUpdateSvTypeConfig(GnssSvTypeConfig& config); +static void gnssGetSvTypeConfig(GnssSvTypeConfigCallback& callback); +static void gnssResetSvTypeConfig(); static void injectLocation(double latitude, double longitude, float accuracy); static void injectTime(int64_t time, int64_t timeReference, int32_t uncertainty); @@ -77,6 +82,10 @@ static const GnssInterface gGnssInterface = { enable, disable, gnssUpdateConfig, + gnssGetConfig, + gnssUpdateSvTypeConfig, + gnssGetSvTypeConfig, + gnssResetSvTypeConfig, gnssDeleteAidingData, gnssUpdateXtraThrottle, injectLocation, @@ -167,7 +176,7 @@ static void gnssNiResponse(LocationAPI* client, uint32_t id, GnssNiResponse resp static void setControlCallbacks(LocationControlCallbacks& controlCallbacks) { if (NULL != gGnssAdapter) { - return gGnssAdapter->setControlCallbacksCommand(controlCallbacks); + gGnssAdapter->setControlCallbacksCommand(controlCallbacks); } } @@ -183,7 +192,7 @@ static uint32_t enable(LocationTechnologyType techType) static void disable(uint32_t id) { if (NULL != gGnssAdapter) { - return gGnssAdapter->disableCommand(id); + gGnssAdapter->disableCommand(id); } } @@ -196,6 +205,36 @@ static uint32_t* gnssUpdateConfig(GnssConfig config) } } +static uint32_t* gnssGetConfig(GnssConfigFlagsMask mask) +{ + if (NULL != gGnssAdapter) { + return gGnssAdapter->gnssGetConfigCommand(mask); + } else { + return NULL; + } +} + +static void gnssUpdateSvTypeConfig(GnssSvTypeConfig& config) +{ + if (NULL != gGnssAdapter) { + gGnssAdapter->gnssUpdateSvTypeConfigCommand(config); + } +} + +static void gnssGetSvTypeConfig(GnssSvTypeConfigCallback& callback) +{ + if (NULL != gGnssAdapter) { + gGnssAdapter->gnssGetSvTypeConfigCommand(callback); + } +} + +static void gnssResetSvTypeConfig() +{ + if (NULL != gGnssAdapter) { + gGnssAdapter->gnssResetSvTypeConfigCommand(); + } +} + static uint32_t gnssDeleteAidingData(GnssAidingData& data) { if (NULL != gGnssAdapter) { diff --git a/location/LocationAPI.cpp b/location/LocationAPI.cpp index e43d9e03..060ce5f2 100644 --- a/location/LocationAPI.cpp +++ b/location/LocationAPI.cpp @@ -628,6 +628,21 @@ LocationControlAPI::gnssUpdateConfig(GnssConfig config) return ids; } +uint32_t* LocationControlAPI::gnssGetConfig(GnssConfigFlagsMask mask) { + + uint32_t* ids = NULL; + pthread_mutex_lock(&gDataMutex); + + if (NULL != gData.gnssInterface) { + ids = gData.gnssInterface->gnssGetConfig(mask); + } else { + LOC_LOGe("No gnss interface available for Control API client %p", this); + } + + pthread_mutex_unlock(&gDataMutex); + return ids; +} + uint32_t LocationControlAPI::gnssDeleteAidingData(GnssAidingData& data) { diff --git a/location/LocationAPI.h b/location/LocationAPI.h index ce38bc6b..cfdb19f2 100644 --- a/location/LocationAPI.h +++ b/location/LocationAPI.h @@ -178,6 +178,7 @@ typedef struct { size_t size; // set to sizeof(LocationControlCallbacks) responseCallback responseCb; // mandatory collectiveResponseCallback collectiveResponseCb; // mandatory + gnssConfigCallback gnssConfigCb; // optional } LocationControlCallbacks; class LocationControlAPI : public ILocationControlAPI @@ -231,6 +232,21 @@ public: LOCATION_ERROR_GENERAL_FAILURE if failure for any other reason */ virtual uint32_t* gnssUpdateConfig(GnssConfig config) override; + /* gnssGetConfig fetches the current constellation and SV configuration + on the GNSS engine. + Returns a session id array with an id for each of the bits set in + the mask parameter, order from low bits to high bits. + Response is sent via the registered gnssConfigCallback. + This effect is global for all clients of LocationAPI + collectiveResponseCallback returns: + LOCATION_ERROR_SUCCESS if session was successful + LOCATION_ERROR_INVALID_PARAMETER if any parameter is invalid + LOCATION_ERROR_CALLBACK_MISSING If no gnssConfigCallback + was passed in createInstance + LOCATION_ERROR_NOT_SUPPORTED If read of requested configuration + is not supported */ + uint32_t* gnssGetConfig(GnssConfigFlagsMask mask); + /* delete specific gnss aiding data for testing, which returns a session id that will be returned in responseCallback to match command with response. Only allowed in userdebug builds. This effect is global for all clients of LocationAPI diff --git a/location/LocationAPIClientBase.cpp b/location/LocationAPIClientBase.cpp index 626968c9..65a09847 100644 --- a/location/LocationAPIClientBase.cpp +++ b/location/LocationAPIClientBase.cpp @@ -26,7 +26,7 @@ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#define LOG_NDDEBUG 0 +#define LOG_NDEBUG 0 #define LOG_TAG "LocSvc_APIClientBase" #include @@ -45,7 +45,7 @@ LocationAPIControlClient::LocationAPIControlClient() : pthread_mutex_init(&mMutex, nullptr); for (int i = 0; i < CTRL_REQUEST_MAX; i++) { - mRequestQueues[i].reset(0); + mRequestQueues[i].reset((uint32_t)0); } memset(&mConfig, 0, sizeof(GnssConfig)); @@ -75,7 +75,7 @@ LocationAPIControlClient::~LocationAPIControlClient() } for (int i = 0; i < CTRL_REQUEST_MAX; i++) { - mRequestQueues[i].reset(0); + mRequestQueues[i].reset((uint32_t)0); } pthread_mutex_unlock(&mMutex); @@ -142,24 +142,43 @@ void LocationAPIControlClient::locAPIDisable() uint32_t LocationAPIControlClient::locAPIGnssUpdateConfig(GnssConfig config) { uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE; - if (memcmp(&mConfig, &config, sizeof(GnssConfig)) == 0) { - LOC_LOGV("%s:%d] GnssConfig is identical to previous call", __FUNCTION__, __LINE__); - retVal = LOCATION_ERROR_SUCCESS; - return retVal; + + pthread_mutex_lock(&mMutex); + if (mLocationControlAPI) { + if (mConfig.equals(config)) { + LOC_LOGv("GnssConfig is identical to previous call"); + retVal = LOCATION_ERROR_SUCCESS; + } else { + mConfig = config; + uint32_t* idArray = mLocationControlAPI->gnssUpdateConfig(config); + LOC_LOGv("gnssUpdateConfig return array: %p", idArray); + if (nullptr != idArray) { + if (nullptr != mRequestQueues[CTRL_REQUEST_CONFIG_UPDATE].getSessionArrayPtr()) { + mRequestQueues[CTRL_REQUEST_CONFIG_UPDATE].reset(idArray); + } + mRequestQueues[CTRL_REQUEST_CONFIG_UPDATE].push(new GnssUpdateConfigRequest(*this)); + retVal = LOCATION_ERROR_SUCCESS; + } + } } + pthread_mutex_unlock(&mMutex); + return retVal; +} + +uint32_t LocationAPIControlClient::locAPIGnssGetConfig(GnssConfigFlagsMask mask) +{ + uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE; pthread_mutex_lock(&mMutex); if (mLocationControlAPI) { - memcpy(&mConfig, &config, sizeof(GnssConfig)); - - uint32_t* idArray = mLocationControlAPI->gnssUpdateConfig(config); - LOC_LOGV("%s:%d] gnssUpdateConfig return array: %p", __FUNCTION__, __LINE__, idArray); - if (idArray != nullptr) { - if (mRequestQueues[CTRL_REQUEST_CONFIG].getSession() != CONFIG_SESSION_ID) { - mRequestQueues[CTRL_REQUEST_CONFIG].reset(CONFIG_SESSION_ID); + uint32_t* idArray = mLocationControlAPI->gnssGetConfig(mask); + LOC_LOGv("gnssGetConfig return array: %p", idArray); + if (nullptr != idArray) { + if (nullptr != mRequestQueues[CTRL_REQUEST_CONFIG_GET].getSessionArrayPtr()) { + mRequestQueues[CTRL_REQUEST_CONFIG_GET].reset(idArray); } - mRequestQueues[CTRL_REQUEST_CONFIG].push(new GnssUpdateConfigRequest(*this)); + mRequestQueues[CTRL_REQUEST_CONFIG_GET].push(new GnssGetConfigRequest(*this)); retVal = LOCATION_ERROR_SUCCESS; } } @@ -191,12 +210,7 @@ void LocationAPIControlClient::onCtrlCollectiveResponseCb( LOC_LOGV("%s:%d] SUCCESS: %d id: %d", __FUNCTION__, __LINE__, errors[i], ids[i]); } } - LocationAPIRequest* request = nullptr; - pthread_mutex_lock(&mMutex); - if (mRequestQueues[CTRL_REQUEST_CONFIG].getSession() == CONFIG_SESSION_ID) { - request = mRequestQueues[CTRL_REQUEST_CONFIG].pop(); - } - pthread_mutex_unlock(&mMutex); + LocationAPIRequest* request = getRequestBySessionArrayPtr(ids); if (request) { request->onCollectiveResponse(count, errors, ids); delete request; @@ -207,13 +221,30 @@ LocationAPIRequest* LocationAPIControlClient::getRequestBySession(uint32_t sessi { pthread_mutex_lock(&mMutex); LocationAPIRequest* request = nullptr; - for (int i = 0; i < CTRL_REQUEST_MAX; i++) { - if (i != CTRL_REQUEST_CONFIG && - mRequestQueues[i].getSession() == session) { - request = mRequestQueues[i].pop(); - break; - } + + if (mRequestQueues[CTRL_REQUEST_DELETEAIDINGDATA].getSession() == session) { + request = mRequestQueues[CTRL_REQUEST_DELETEAIDINGDATA].pop(); + } else if (mRequestQueues[CTRL_REQUEST_CONTROL].getSession() == session) { + request = mRequestQueues[CTRL_REQUEST_CONTROL].pop(); } + + pthread_mutex_unlock(&mMutex); + return request; +} + +LocationAPIRequest* +LocationAPIControlClient::getRequestBySessionArrayPtr( + uint32_t* sessionArrayPtr) +{ + pthread_mutex_lock(&mMutex); + LocationAPIRequest* request = nullptr; + + if (mRequestQueues[CTRL_REQUEST_CONFIG_UPDATE].getSessionArrayPtr() == sessionArrayPtr) { + request = mRequestQueues[CTRL_REQUEST_CONFIG_UPDATE].pop(); + } else if (mRequestQueues[CTRL_REQUEST_CONFIG_GET].getSessionArrayPtr() == sessionArrayPtr) { + request = mRequestQueues[CTRL_REQUEST_CONFIG_GET].pop(); + } + pthread_mutex_unlock(&mMutex); return request; } @@ -234,7 +265,7 @@ LocationAPIClientBase::LocationAPIClientBase() : pthread_mutex_init(&mMutex, &attr); for (int i = 0; i < REQUEST_MAX; i++) { - mRequestQueues[i].reset(0); + mRequestQueues[i].reset((uint32_t)0); } } @@ -291,7 +322,7 @@ LocationAPIClientBase::~LocationAPIClientBase() } for (int i = 0; i < REQUEST_MAX; i++) { - mRequestQueues[i].reset(0); + mRequestQueues[i].reset((uint32_t)0); } pthread_mutex_unlock(&mMutex); diff --git a/location/LocationAPIClientBase.h b/location/LocationAPIClientBase.h index 4bd1466b..4d48932a 100644 --- a/location/LocationAPIClientBase.h +++ b/location/LocationAPIClientBase.h @@ -57,7 +57,8 @@ enum REQUEST_TYPE { enum CTRL_REQUEST_TYPE { CTRL_REQUEST_DELETEAIDINGDATA = 0, CTRL_REQUEST_CONTROL, - CTRL_REQUEST_CONFIG, + CTRL_REQUEST_CONFIG_UPDATE, + CTRL_REQUEST_CONFIG_GET, CTRL_REQUEST_MAX, }; @@ -74,12 +75,13 @@ public: class RequestQueue { public: - RequestQueue(): mSession(0) { + RequestQueue(): mSession(0), mSessionArrayPtr(nullptr) { } virtual ~RequestQueue() { - reset(0); + reset((uint32_t)0); } void inline setSession(uint32_t session) { mSession = session; } + void inline setSessionArrayPtr(uint32_t* ptr) { mSessionArrayPtr = ptr; } void reset(uint32_t session) { LocationAPIRequest* request = nullptr; while (!mQueue.empty()) { @@ -89,6 +91,10 @@ public: } mSession = session; } + void reset(uint32_t* sessionArrayPtr) { + reset((uint32_t)0); + mSessionArrayPtr = sessionArrayPtr; + } void push(LocationAPIRequest* request) { mQueue.push(request); } @@ -101,8 +107,10 @@ public: return request; } uint32_t getSession() { return mSession; } + uint32_t* getSessionArrayPtr() { return mSessionArrayPtr; } private: uint32_t mSession; + uint32_t* mSessionArrayPtr; std::queue mQueue; }; @@ -114,12 +122,15 @@ public: LocationAPIControlClient& operator=(const LocationAPIControlClient&) = delete; LocationAPIRequest* getRequestBySession(uint32_t session); + LocationAPIRequest* getRequestBySessionArrayPtr(uint32_t* sessionArrayPtr); // LocationControlAPI uint32_t locAPIGnssDeleteAidingData(GnssAidingData& data); uint32_t locAPIEnable(LocationTechnologyType techType); void locAPIDisable(); uint32_t locAPIGnssUpdateConfig(GnssConfig config); + uint32_t locAPIGnssGetConfig(GnssConfigFlagsMask config); + inline LocationControlAPI* getControlAPI() { return mLocationControlAPI; } // callbacks void onCtrlResponseCb(LocationError error, uint32_t id); @@ -130,6 +141,8 @@ public: inline virtual void onDisableCb(LocationError /*error*/) {} inline virtual void onGnssUpdateConfigCb( size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {} + inline virtual void onGnssGetConfigCb( + size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {} class GnssDeleteAidingDataRequest : public LocationAPIRequest { public: @@ -167,6 +180,15 @@ public: LocationAPIControlClient& mAPI; }; + class GnssGetConfigRequest : public LocationAPIRequest { + public: + GnssGetConfigRequest(LocationAPIControlClient& API) : mAPI(API) {} + inline void onCollectiveResponse(size_t count, LocationError* errors, uint32_t* ids) { + mAPI.onGnssGetConfigCb(count, errors, ids); + } + LocationAPIControlClient& mAPI; + }; + private: pthread_mutex_t mMutex; LocationControlAPI* mLocationControlAPI; diff --git a/location/LocationDataTypes.h b/location/LocationDataTypes.h index 00cca183..5d1c8093 100644 --- a/location/LocationDataTypes.h +++ b/location/LocationDataTypes.h @@ -270,6 +270,7 @@ typedef enum { GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT = (1<<7), 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), } GnssConfigFlagsBits; typedef enum { @@ -740,12 +741,22 @@ typedef struct { GnssSvOptionsMask gnssSvOptionsMask; // Bitwise OR of GnssSvOptionsBits } GnssSv; -typedef struct { +struct GnssConfigSetAssistanceServer { size_t size; // set to sizeof(GnssConfigSetAssistanceServer) GnssAssistanceType type; // SUPL or C2K const char* hostName; // null terminated string uint32_t port; // port of server -} GnssConfigSetAssistanceServer; + + inline bool equals(const GnssConfigSetAssistanceServer& config) { + if (config.type == type && config.port == port && + ((NULL == config.hostName && NULL == hostName) || + (NULL != config.hostName && NULL != hostName && + 0 == strcmp(config.hostName, hostName)))) { + return true; + } + return false; + } +}; typedef struct { size_t size; // set to sizeof(GnssMeasurementsData) @@ -805,7 +816,40 @@ typedef struct { GnssMeasurementsClock clock; // clock } GnssMeasurementsNotification; +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 +}; +inline bool operator ==(GnssSvIdSource const& left, GnssSvIdSource const& right) { + return left.size == right.size && + left.constellation == right.constellation && left.svId == right.svId; +} + +#define GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK ((uint64_t)0xFFFFFFFFFFFFFFFF) typedef struct { + size_t size; // set to sizeof(GnssSvIdConfig) + + // GLONASS - SV 65 maps to bit 0 +#define GNSS_SV_CONFIG_GLO_INITIAL_SV_ID 65 + uint64_t gloBlacklistSvMask; + + // BEIDOU - SV 201 maps to bit 0 +#define GNSS_SV_CONFIG_BDS_INITIAL_SV_ID 201 + uint64_t bdsBlacklistSvMask; + + // QZSS - SV 193 maps to bit 0 +#define GNSS_SV_CONFIG_QZSS_INITIAL_SV_ID 193 + uint64_t qzssBlacklistSvMask; + + // GAL - SV 301 maps to bit 0 +#define GNSS_SV_CONFIG_GAL_INITIAL_SV_ID 301 + uint64_t galBlacklistSvMask; +} GnssSvIdConfig; + +struct GnssConfig{ size_t size; // set to sizeof(GnssConfig) GnssConfigFlagsMask flags; // bitwise OR of GnssConfigFlagsBits to mark which params are valid GnssConfigGpsLock gpsLock; @@ -818,7 +862,26 @@ typedef struct { GnssConfigEmergencyPdnForEmergencySupl emergencyPdnForEmergencySupl; GnssConfigSuplEmergencyServices suplEmergencyServices; GnssConfigSuplModeMask suplModeMask; //bitwise OR of GnssConfigSuplModeBits -} GnssConfig; + std::vector blacklistedSvIds; + + inline bool equals(const GnssConfig& config) { + if (flags == config.flags && + gpsLock == config.gpsLock && + suplVersion == config.suplVersion && + assistanceServer.equals(config.assistanceServer) && + lppProfile == config.lppProfile && + lppeControlPlaneMask == config.lppeControlPlaneMask && + lppeUserPlaneMask == config.lppeUserPlaneMask && + aGlonassPositionProtocolMask == config.aGlonassPositionProtocolMask && + emergencyPdnForEmergencySupl == config.emergencyPdnForEmergencySupl && + suplEmergencyServices == config.suplEmergencyServices && + suplModeMask == config.suplModeMask && + blacklistedSvIds == config.blacklistedSvIds) { + return true; + } + return false; + } +}; typedef struct { size_t size; // set to sizeof @@ -947,6 +1010,11 @@ typedef std::function gnssMeasurementsCallback; +/* Provides the current GNSS configuration to the client */ +typedef std::function gnssConfigCallback; + typedef struct { size_t size; // set to sizeof(LocationCallbacks) capabilitiesCallback capabilitiesCb; // mandatory diff --git a/location/location_interface.h b/location/location_interface.h index 27589f71..f4f904d9 100644 --- a/location/location_interface.h +++ b/location/location_interface.h @@ -47,6 +47,10 @@ struct GnssInterface { uint32_t (*enable)(LocationTechnologyType techType); void (*disable)(uint32_t id); uint32_t* (*gnssUpdateConfig)(GnssConfig config); + uint32_t* (*gnssGetConfig)(GnssConfigFlagsMask config); + void (*gnssUpdateSvTypeConfig)(GnssSvTypeConfig& config); + void (*gnssGetSvTypeConfig)(GnssSvTypeConfigCallback& callback); + void (*gnssResetSvTypeConfig)(); uint32_t (*gnssDeleteAidingData)(GnssAidingData& data); void (*gnssUpdateXtraThrottle)(const bool enabled); void (*injectLocation)(double latitude, double longitude, float accuracy); diff --git a/utils/gps_extended_c.h b/utils/gps_extended_c.h index bc6e384b..5c5405fe 100644 --- a/utils/gps_extended_c.h +++ b/utils/gps_extended_c.h @@ -119,8 +119,8 @@ typedef enum { LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02, /**< Support debug NMEA feature */ LOC_SUPPORTED_FEATURE_GNSS_ONLY_POSITION_REPORT, /**< Support GNSS Only position reports */ LOC_SUPPORTED_FEATURE_FDCL, /**< Support FDCL */ - LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT, /**< Support constellation enablement */ - LOC_SUPPORTED_FEATURE_AGPM, /**< Support AGPM feature */ + LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02, /**< Support constellation enablement */ + LOC_SUPPORTED_FEATURE_AGPM_V02, /**< Support AGPM feature */ LOC_SUPPORTED_FEATURE_XTRA_INTEGRITY /**< Support XTRA integrity */ } loc_supported_feature_enum; @@ -1461,6 +1461,32 @@ typedef struct Gnss_Srn_MacAddr_Type macAddrType; /* SRN AP MAC Address type */ } GnssSrnDataReq; +/* Mask indicating enabled or disabled constellations */ +typedef uint64_t GnssSvTypesMask; +typedef enum { + GNSS_SV_TYPES_MASK_GLO_BIT = (1<<0), + GNSS_SV_TYPES_MASK_BDS_BIT = (1<<1), + GNSS_SV_TYPES_MASK_QZSS_BIT = (1<<2), + GNSS_SV_TYPES_MASK_GAL_BIT = (1<<3), +} GnssSvTypesMaskBits; + +/* This SV Type config is injected directly to GNSS Adapter + * bypassing Location API */ +typedef struct { + size_t size; // set to sizeof(GnssSvTypeConfig) + // Enabled Constellations + GnssSvTypesMask enabledSvTypesMask; + // Disabled Constellations + GnssSvTypesMask blacklistedSvTypesMask; +} GnssSvTypeConfig; + +/* Provides the current GNSS SV Type configuration to the client. + * This is fetched via direct call to GNSS Adapter bypassing + * Location API */ +typedef std::function GnssSvTypeConfigCallback; + /* * Represents the status of AGNSS augmented to support IPv4. */