diff --git a/gps/android/2.1/AGnss.cpp b/gps/android/2.1/AGnss.cpp index c759492..ce7b3aa 100644 --- a/gps/android/2.1/AGnss.cpp +++ b/gps/android/2.1/AGnss.cpp @@ -32,7 +32,7 @@ namespace implementation { static AGnss* spAGnss = nullptr; -AGnss::AGnss(Gnss* gnss) : mGnss(gnss) { +AGnss::AGnss(Gnss* gnss) : mGnss(gnss), mType(LOC_AGPS_TYPE_INVALID) { spAGnss = this; } @@ -51,6 +51,9 @@ void AGnss::statusCb(AGpsExtType type, LocAGpsStatusValue status) { V2_0::IAGnssCallback::AGnssType aType; IAGnssCallback::AGnssStatusValue aStatus; + // cache the AGps Type + mType = type; + switch (type) { case LOC_AGPS_TYPE_SUPL: aType = IAGnssCallback::AGnssType::SUPL; @@ -138,18 +141,20 @@ Return AGnss::dataConnFailed() { Return AGnss::dataConnOpen(uint64_t /*networkHandle*/, const hidl_string& apn, V2_0::IAGnss::ApnIpType apnIpType) { - if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){ + if (mGnss == nullptr || mGnss->getGnssInterface() == nullptr){ LOC_LOGE("Null GNSS interface"); return false; } - /* Validate */ - if(apn.empty()){ - LOC_LOGE("Invalid APN"); - return false; + std::string apnString(apn.c_str()); + // During Emergency SUPL, an apn name of "sos" means that no + // apn was found, like in the simless case, so apn is cleared + if (LOC_AGPS_TYPE_SUPL_ES == mType && "sos" == apnString) { + LOC_LOGD("dataConnOpen APN name = [sos] cleared"); + apnString.clear(); } - LOC_LOGD("dataConnOpen APN name = [%s]", apn.c_str()); + LOC_LOGD("dataConnOpen APN name = [%s]", apnString.c_str()); AGpsBearerType bearerType; switch (apnIpType) { @@ -168,7 +173,7 @@ Return AGnss::dataConnOpen(uint64_t /*networkHandle*/, const hidl_string& } mGnss->getGnssInterface()->agpsDataConnOpen( - LOC_AGPS_TYPE_SUPL, apn.c_str(), apn.size(), (int)bearerType); + LOC_AGPS_TYPE_SUPL, apnString.c_str(), apnString.size(), (int)bearerType); return true; } diff --git a/gps/android/2.1/AGnss.h b/gps/android/2.1/AGnss.h index f6ea997..cf9c8a7 100644 --- a/gps/android/2.1/AGnss.h +++ b/gps/android/2.1/AGnss.h @@ -67,6 +67,8 @@ struct AGnss : public V2_0::IAGnss { private: Gnss* mGnss = nullptr; sp mAGnssCbIface = nullptr; + + AGpsExtType mType; }; } // namespace implementation diff --git a/gps/android/2.1/AGnssRil.cpp b/gps/android/2.1/AGnssRil.cpp index 65fb300..f413e93 100644 --- a/gps/android/2.1/AGnssRil.cpp +++ b/gps/android/2.1/AGnssRil.cpp @@ -54,6 +54,7 @@ Return AGnssRil::updateNetworkState(bool connected, NetworkType type, bool const int NetworkType_BLUETOOTH = 7; const int NetworkType_ETHERNET = 9; const int NetworkType_PROXY = 16; + std::string apn(""); // for XTRA if (nullptr != mGnss && ( nullptr != mGnss->getGnssInterface() )) { @@ -102,13 +103,13 @@ Return AGnssRil::updateNetworkState(bool connected, NetworkType type, bool } break; } - mGnss->getGnssInterface()->updateConnectionStatus(connected, false, typeout, 0); + mGnss->getGnssInterface()->updateConnectionStatus(connected, typeout, false, 0, apn); } return true; } Return AGnssRil::updateNetworkState_2_0(const V2_0::IAGnssRil::NetworkAttributes& attributes) { ENTRY_LOG_CALLFLOW(); - + std::string apn = attributes.apn; if (nullptr != mGnss && (nullptr != mGnss->getGnssInterface())) { int8_t typeout = loc_core::TYPE_UNKNOWN; bool roaming = false; @@ -120,8 +121,9 @@ Return AGnssRil::updateNetworkState_2_0(const V2_0::IAGnssRil::NetworkAttr if (attributes.capabilities & IAGnssRil::NetworkCapability::NOT_ROAMING) { roaming = false; } + LOC_LOGd("apn string received is: %s", apn.c_str()); mGnss->getGnssInterface()->updateConnectionStatus(attributes.isConnected, - typeout, roaming, (NetworkHandle) attributes.networkHandle); + typeout, roaming, (NetworkHandle) attributes.networkHandle, apn); } return true; } diff --git a/gps/android/2.1/Gnss.cpp b/gps/android/2.1/Gnss.cpp index a83271e..37e1cc5 100644 --- a/gps/android/2.1/Gnss.cpp +++ b/gps/android/2.1/Gnss.cpp @@ -86,6 +86,7 @@ void Gnss::GnssDeathRecipient::serviceDied(uint64_t cookie, const wp& who LOC_LOGE("%s] service died. cookie: %llu, who: %p", __FUNCTION__, static_cast(cookie), &who); if (mGnss != nullptr) { + mGnss->getGnssInterface()->resetNetworkInfo(); mGnss->cleanup(); } } diff --git a/gps/android/2.1/location_api/BatchingAPIClient.cpp b/gps/android/2.1/location_api/BatchingAPIClient.cpp old mode 100755 new mode 100644 index f1f1fe4..0c871b7 --- a/gps/android/2.1/location_api/BatchingAPIClient.cpp +++ b/gps/android/2.1/location_api/BatchingAPIClient.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2021, 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,9 +30,10 @@ #define LOG_NDEBUG 0 #define LOG_TAG "LocSvc_BatchingAPIClient" +#include #include #include - +#include #include "LocationUtil.h" #include "BatchingAPIClient.h" @@ -81,10 +82,10 @@ BatchingAPIClient::~BatchingAPIClient() LOC_LOGD("%s]: ()", __FUNCTION__); } -int BatchingAPIClient::getBatchSize() -{ - LOC_LOGD("%s]: ()", __FUNCTION__); - return locAPIGetBatchSize(); +int BatchingAPIClient::getBatchSize() { + int batchSize = locAPIGetBatchSize(); + LOC_LOGd("batchSize: %d", batchSize); + return batchSize; } void BatchingAPIClient::setCallbacks() @@ -132,8 +133,10 @@ void BatchingAPIClient::gnssUpdateCallbacks_2_0(const sp(opts.periodNanos), static_cast(opts.flags)); int retVal = -1; @@ -167,10 +170,13 @@ int BatchingAPIClient::updateSessionOptions(const IGnssBatching::Options& opts) return retVal; } -int BatchingAPIClient::stopSession() -{ +int BatchingAPIClient::stopSession() { + mMutex.lock(); + mState = STOPPING; + mMutex.unlock(); LOC_LOGD("%s]: ", __FUNCTION__); int retVal = -1; + locAPIGetBatchedLocations(mDefaultId, SIZE_MAX); if (locAPIStopSession(mDefaultId) == LOCATION_ERROR_SUCCESS) { retVal = 1; } @@ -183,50 +189,86 @@ void BatchingAPIClient::getBatchedLocation(int last_n_locations) locAPIGetBatchedLocations(mDefaultId, last_n_locations); } -void BatchingAPIClient::flushBatchedLocations() -{ +void BatchingAPIClient::flushBatchedLocations() { LOC_LOGD("%s]: ()", __FUNCTION__); - locAPIGetBatchedLocations(mDefaultId, SIZE_MAX); + uint32_t retVal = locAPIGetBatchedLocations(mDefaultId, SIZE_MAX); + // when flush a stopped session or one doesn't exist, just report an empty batch. + if (LOCATION_ERROR_ID_UNKNOWN == retVal) { + BatchingOptions opt = {}; + ::std::thread thd(&BatchingAPIClient::onBatchingCb, this, 0, nullptr, opt); + thd.detach(); + } } void BatchingAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask) { - LOC_LOGD("%s]: (%02x)", __FUNCTION__, capabilitiesMask); + LOC_LOGD("%s]: (%" PRIu64 ")", __FUNCTION__, capabilitiesMask); mLocationCapabilitiesMask = capabilitiesMask; } void BatchingAPIClient::onBatchingCb(size_t count, Location* location, - BatchingOptions /*batchOptions*/) -{ + BatchingOptions /*batchOptions*/) { + bool processReport = false; + LOC_LOGd("(count: %zu)", count); mMutex.lock(); - auto gnssBatchingCbIface(mGnssBatchingCbIface); - auto gnssBatchingCbIface_2_0(mGnssBatchingCbIface_2_0); - mMutex.unlock(); - - LOC_LOGD("%s]: (count: %zu)", __FUNCTION__, count); - if (gnssBatchingCbIface_2_0 != nullptr && count > 0) { - hidl_vec locationVec; - locationVec.resize(count); - for (size_t i = 0; i < count; i++) { - convertGnssLocation(location[i], locationVec[i]); - } - auto r = gnssBatchingCbIface_2_0->gnssLocationBatchCb(locationVec); - if (!r.isOk()) { - LOC_LOGE("%s] Error from gnssLocationBatchCb 2_0 description=%s", - __func__, r.description().c_str()); - } - } else if (gnssBatchingCbIface != nullptr && count > 0) { - hidl_vec locationVec; - locationVec.resize(count); - for (size_t i = 0; i < count; i++) { - convertGnssLocation(location[i], locationVec[i]); - } - auto r = gnssBatchingCbIface->gnssLocationBatchCb(locationVec); - if (!r.isOk()) { - LOC_LOGE("%s] Error from gnssLocationBatchCb 1.0 description=%s", - __func__, r.description().c_str()); - } + // back to back stop() and flush() could bring twice onBatchingCb(). Each one might come first. + // Combine them both (the first goes to cache, the second in location*) before report to FW + switch (mState) { + case STOPPING: + mState = STOPPED; + for (size_t i = 0; i < count; i++) { + mBatchedLocationInCache.push_back(location[i]); + } + break; + case STARTED: + case STOPPED: // flush() always trigger report, even on a stopped session + processReport = true; + break; + default: + break; } + // report location batch when in STARTED state or flush(), combined with cache in last stop() + if (processReport) { + auto gnssBatchingCbIface(mGnssBatchingCbIface); + auto gnssBatchingCbIface_2_0(mGnssBatchingCbIface_2_0); + size_t batchCacheCnt = mBatchedLocationInCache.size(); + LOC_LOGd("(batchCacheCnt: %zu)", batchCacheCnt); + if (gnssBatchingCbIface_2_0 != nullptr) { + hidl_vec locationVec; + if (count+batchCacheCnt > 0) { + locationVec.resize(count+batchCacheCnt); + for (size_t i = 0; i < batchCacheCnt; ++i) { + convertGnssLocation(mBatchedLocationInCache[i], locationVec[i]); + } + for (size_t i = 0; i < count; i++) { + convertGnssLocation(location[i], locationVec[i+batchCacheCnt]); + } + } + auto r = gnssBatchingCbIface_2_0->gnssLocationBatchCb(locationVec); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssLocationBatchCb 2_0 description=%s", + __func__, r.description().c_str()); + } + } else if (gnssBatchingCbIface != nullptr) { + hidl_vec locationVec; + if (count+batchCacheCnt > 0) { + locationVec.resize(count+batchCacheCnt); + for (size_t i = 0; i < batchCacheCnt; ++i) { + convertGnssLocation(mBatchedLocationInCache[i], locationVec[i]); + } + for (size_t i = 0; i < count; i++) { + convertGnssLocation(location[i], locationVec[i+batchCacheCnt]); + } + } + auto r = gnssBatchingCbIface->gnssLocationBatchCb(locationVec); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssLocationBatchCb 1.0 description=%s", + __func__, r.description().c_str()); + } + } + mBatchedLocationInCache.clear(); + } + mMutex.unlock(); } static void convertBatchOption(const IGnssBatching::Options& in, LocationOptions& out, diff --git a/gps/android/2.1/location_api/BatchingAPIClient.h b/gps/android/2.1/location_api/BatchingAPIClient.h index 08d7d23..2d9ab74 100755 --- a/gps/android/2.1/location_api/BatchingAPIClient.h +++ b/gps/android/2.1/location_api/BatchingAPIClient.h @@ -43,6 +43,9 @@ namespace gnss { namespace V2_1 { namespace implementation { + +enum BATCHING_STATE { STARTED, STOPPING, STOPPED }; + class BatchingAPIClient : public LocationAPIClientBase { public: @@ -72,6 +75,9 @@ private: uint32_t mDefaultId; LocationCapabilitiesMask mLocationCapabilitiesMask; sp mGnssBatchingCbIface_2_0; + volatile BATCHING_STATE mState = STOPPED; + + std::vector mBatchedLocationInCache; }; } // namespace implementation diff --git a/gps/android/2.1/location_api/GnssAPIClient.cpp b/gps/android/2.1/location_api/GnssAPIClient.cpp index efcd90d..07f617d 100644 --- a/gps/android/2.1/location_api/GnssAPIClient.cpp +++ b/gps/android/2.1/location_api/GnssAPIClient.cpp @@ -31,6 +31,7 @@ #define LOG_TAG "LocSvc_GnssAPIClient" #define SINGLE_SHOT_MIN_TRACKING_INTERVAL_MSEC (590 * 60 * 60 * 1000) // 590 hours +#include #include #include @@ -141,9 +142,7 @@ void GnssAPIClient::setCallbacks() locationCallbacks.gnssNiCb = nullptr; if (mGnssNiCbIface != nullptr) { loc_core::ContextBase* context = - loc_core::LocContext::getLocContext( - NULL, NULL, - loc_core::LocContext::mLocationHalName, false); + loc_core::LocContext::getLocContext(loc_core::LocContext::mLocationHalName); if (!context->hasAgpsExtendedCapabilities()) { LOC_LOGD("Registering NI CB"); locationCallbacks.gnssNiCb = [this](uint32_t id, GnssNiNotification gnssNiNotify) { @@ -382,7 +381,7 @@ void GnssAPIClient::requestCapabilities() { // callbacks void GnssAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask) { - LOC_LOGD("%s]: (%02x)", __FUNCTION__, capabilitiesMask); + LOC_LOGD("%s]: (%" PRIu64 ")", __FUNCTION__, capabilitiesMask); mLocationCapabilitiesMask = capabilitiesMask; mLocationCapabilitiesCached = true; diff --git a/gps/android/2.1/location_api/LocationUtil.cpp b/gps/android/2.1/location_api/LocationUtil.cpp index 859d68c..5154e70 100644 --- a/gps/android/2.1/location_api/LocationUtil.cpp +++ b/gps/android/2.1/location_api/LocationUtil.cpp @@ -85,109 +85,22 @@ void convertGnssLocation(Location& in, V1_0::GnssLocation& out) out.timestamp = static_cast(in.timestamp); } -bool getCurrentTime(struct timespec& currentTime, int64_t& sinceBootTimeNanos) -{ - struct timespec sinceBootTime; - struct timespec sinceBootTimeTest; - bool clockGetTimeSuccess = false; - const uint32_t MAX_TIME_DELTA_VALUE_NANOS = 10000; - const uint32_t MAX_GET_TIME_COUNT = 20; - /* Attempt to get CLOCK_REALTIME and CLOCK_BOOTIME in succession without an interruption - or context switch (for up to MAX_GET_TIME_COUNT times) to avoid errors in the calculation */ - for (uint32_t i = 0; i < MAX_GET_TIME_COUNT; i++) { - if (clock_gettime(CLOCK_BOOTTIME, &sinceBootTime) != 0) { - break; - }; - if (clock_gettime(CLOCK_REALTIME, ¤tTime) != 0) { - break; - } - if (clock_gettime(CLOCK_BOOTTIME, &sinceBootTimeTest) != 0) { - break; - }; - sinceBootTimeNanos = sinceBootTime.tv_sec * 1000000000 + sinceBootTime.tv_nsec; - int64_t sinceBootTimeTestNanos = - sinceBootTimeTest.tv_sec * 1000000000 + sinceBootTimeTest.tv_nsec; - int64_t sinceBootTimeDeltaNanos = sinceBootTimeTestNanos - sinceBootTimeNanos; - - /* sinceBootTime and sinceBootTimeTest should have a close value if there was no - interruption or context switch between clock_gettime for CLOCK_BOOTIME and - clock_gettime for CLOCK_REALTIME */ - if (sinceBootTimeDeltaNanos < MAX_TIME_DELTA_VALUE_NANOS) { - clockGetTimeSuccess = true; - break; - } else { - LOC_LOGd("Delta:%" PRIi64 "ns time too large, retry number #%u...", - sinceBootTimeDeltaNanos, i + 1); - } - } - return clockGetTimeSuccess; -} - void convertGnssLocation(Location& in, V2_0::GnssLocation& out) { memset(&out, 0, sizeof(V2_0::GnssLocation)); convertGnssLocation(in, out.v1_0); - struct timespec currentTime; - int64_t sinceBootTimeNanos; - - if (getCurrentTime(currentTime, sinceBootTimeNanos)) { - if (in.flags & LOCATION_HAS_ELAPSED_REAL_TIME) { - uint64_t qtimerDiff = 0; - uint64_t qTimerTickCount = getQTimerTickCount(); - if (qTimerTickCount >= in.elapsedRealTime) { - qtimerDiff = qTimerTickCount - in.elapsedRealTime; - } - LOC_LOGv("sinceBootTimeNanos:%" PRIi64 " in.elapsedRealTime=%" PRIi64 "" - " qTimerTickCount=%" PRIi64 " qtimerDiff=%" PRIi64 "", - sinceBootTimeNanos, in.elapsedRealTime, qTimerTickCount, qtimerDiff); - uint64_t qTimerDiffNanos = qTimerTicksToNanos(double(qtimerDiff)); - - /* If the time difference between Qtimer on modem side and Qtimer on AP side - is greater than one second we assume this is a dual-SoC device such as - Kona and will try to get Qtimer on modem side and on AP side and - will adjust our difference accordingly */ - if (qTimerDiffNanos > 1000000000) { - uint64_t qtimerDelta = getQTimerDeltaNanos(); - if (qTimerDiffNanos >= qtimerDelta) { - qTimerDiffNanos -= qtimerDelta; - } - } - - if (sinceBootTimeNanos >= qTimerDiffNanos) { - out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIMESTAMP_NS; - out.elapsedRealtime.timestampNs = sinceBootTimeNanos - qTimerDiffNanos; - out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS; - out.elapsedRealtime.timeUncertaintyNs = in.elapsedRealTimeUnc; - } - } else { - int64_t currentTimeNanos = currentTime.tv_sec*1000000000 + currentTime.tv_nsec; - int64_t locationTimeNanos = in.timestamp*1000000; - LOC_LOGv("sinceBootTimeNanos:%" PRIi64 " currentTimeNanos:%" PRIi64 "" - " locationTimeNanos:%" PRIi64 "", - sinceBootTimeNanos, currentTimeNanos, locationTimeNanos); - if (currentTimeNanos >= locationTimeNanos) { - int64_t ageTimeNanos = currentTimeNanos - locationTimeNanos; - LOC_LOGv("ageTimeNanos:%" PRIi64 ")", ageTimeNanos); - // the max trusted propagation time 100ms for ageTimeNanos to avoid user setting - // wrong time, it will affect elapsedRealtimeNanos - if (ageTimeNanos <= 100000000) { - out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIMESTAMP_NS; - out.elapsedRealtime.timestampNs = sinceBootTimeNanos - ageTimeNanos; - out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS; - // time uncertainty is the max value between abs(AP_UTC - MP_UTC) and 100ms, to - // verify if user change the sys time - out.elapsedRealtime.timeUncertaintyNs = - std::max(ageTimeNanos, (int64_t)100000000); - } - } - } + if (in.flags & LOCATION_HAS_ELAPSED_REAL_TIME) { + out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIMESTAMP_NS; + out.elapsedRealtime.timestampNs = in.elapsedRealTime; + out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS; + out.elapsedRealtime.timeUncertaintyNs = in.elapsedRealTimeUnc; + LOC_LOGd("out.elapsedRealtime.timestampNs=%" PRIi64 "" + " out.elapsedRealtime.timeUncertaintyNs=%" PRIi64 "" + " out.elapsedRealtime.flags=0x%X", + out.elapsedRealtime.timestampNs, + out.elapsedRealtime.timeUncertaintyNs, out.elapsedRealtime.flags); } - LOC_LOGv("out.elapsedRealtime.timestampNs=%" PRIi64 "" - " out.elapsedRealtime.timeUncertaintyNs=%" PRIi64 "" - " out.elapsedRealtime.flags=0x%X", - out.elapsedRealtime.timestampNs, - out.elapsedRealtime.timeUncertaintyNs, out.elapsedRealtime.flags); } void convertGnssLocation(const V1_0::GnssLocation& in, Location& out) @@ -305,7 +218,11 @@ void convertGnssSvid(GnssSv& in, int16_t& out) out = in.svId; break; case GNSS_SV_TYPE_GLONASS: - out = in.svId - GLO_SV_PRN_MIN + 1; + if (!isGloSlotUnknown(in.svId)) { // OSN is known + out = in.svId - GLO_SV_PRN_MIN + 1; + } else { // OSN is not known, report FCN + out = in.gloFrequency + 92; + } break; case GNSS_SV_TYPE_QZSS: out = in.svId; @@ -317,8 +234,6 @@ void convertGnssSvid(GnssSv& in, int16_t& out) out = in.svId - GAL_SV_PRN_MIN + 1; break; case GNSS_SV_TYPE_NAVIC: - /*Android doesn't define Navic svid range yet, use Naviv svid [1, 14] now - will update this once Android give Navic svid definiitons */ out = in.svId - NAVIC_SV_PRN_MIN + 1; break; default: @@ -337,7 +252,7 @@ void convertGnssSvid(GnssMeasurementsData& in, int16_t& out) out = in.svId; break; case GNSS_SV_TYPE_GLONASS: - if (in.svId != 255) { // OSN is known + if (!isGloSlotUnknown(in.svId)) { // OSN is known out = in.svId - GLO_SV_PRN_MIN + 1; } else { // OSN is not known, report FCN out = in.gloFrequency + 92; @@ -353,8 +268,6 @@ void convertGnssSvid(GnssMeasurementsData& in, int16_t& out) out = in.svId - GAL_SV_PRN_MIN + 1; break; case GNSS_SV_TYPE_NAVIC: - /*Android doesn't define Navic svid range yet, use Naviv svid [1, 14] now - will update this once Android give Navic svid definiitons */ out = in.svId - NAVIC_SV_PRN_MIN + 1; break; default: diff --git a/gps/android/2.1/location_api/LocationUtil.h b/gps/android/2.1/location_api/LocationUtil.h index fde1595..2d95a2d 100644 --- a/gps/android/2.1/location_api/LocationUtil.h +++ b/gps/android/2.1/location_api/LocationUtil.h @@ -56,7 +56,6 @@ void convertGnssSvid(GnssMeasurementsData& in, int16_t& out); void convertGnssEphemerisType(GnssEphemerisType& in, GnssDebug::SatelliteEphemerisType& out); void convertGnssEphemerisSource(GnssEphemerisSource& in, GnssDebug::SatelliteEphemerisSource& out); void convertGnssEphemerisHealth(GnssEphemerisHealth& in, GnssDebug::SatelliteEphemerisHealth& out); -bool getCurrentTime(struct timespec& currentTime, int64_t& sinceBootTimeNanos); void convertSingleSatCorrections(const SingleSatCorrection& in, GnssSingleSatCorrection& out); void convertMeasurementCorrections(const MeasurementCorrectionsV1_0& in, GnssMeasurementCorrections& out); diff --git a/gps/android/2.1/location_api/MeasurementAPIClient.cpp b/gps/android/2.1/location_api/MeasurementAPIClient.cpp index 5869774..0028074 100644 --- a/gps/android/2.1/location_api/MeasurementAPIClient.cpp +++ b/gps/android/2.1/location_api/MeasurementAPIClient.cpp @@ -623,80 +623,16 @@ static void convertGnssData_2_1(GnssMeasurementsNotification& in, static void convertElapsedRealtimeNanos(GnssMeasurementsNotification& in, ::android::hardware::gnss::V2_0::ElapsedRealtime& elapsedRealtime) { - struct timespec currentTime; - int64_t sinceBootTimeNanos; - - if (getCurrentTime(currentTime, sinceBootTimeNanos)) { - if (in.clock.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_ELAPSED_REAL_TIME_BIT) { - uint64_t qtimerDiff = 0; - uint64_t qTimerTickCount = getQTimerTickCount(); - if (qTimerTickCount >= in.clock.elapsedRealTime) { - qtimerDiff = qTimerTickCount - in.clock.elapsedRealTime; - } - LOC_LOGv("sinceBootTimeNanos:%" PRIi64 " in.clock.elapsedRealTime=%" PRIi64 "" - " qTimerTickCount=%" PRIi64 " qtimerDiff=%" PRIi64 "", - sinceBootTimeNanos, in.clock.elapsedRealTime, qTimerTickCount, qtimerDiff); - uint64_t qTimerDiffNanos = qTimerTicksToNanos(double(qtimerDiff)); - - /* If the time difference between Qtimer on modem side and Qtimer on AP side - is greater than one second we assume this is a dual-SoC device such as - Kona and will try to get Qtimer on modem side and on AP side and - will adjust our difference accordingly */ - if (qTimerDiffNanos > 1000000000) { - uint64_t qtimerDelta = getQTimerDeltaNanos(); - if (qTimerDiffNanos >= qtimerDelta) { - qTimerDiffNanos -= qtimerDelta; - } - } - - if (sinceBootTimeNanos >= qTimerDiffNanos) { - elapsedRealtime.flags |= V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS; - elapsedRealtime.timestampNs = sinceBootTimeNanos - qTimerDiffNanos; - elapsedRealtime.flags |= V2_0::ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS; - elapsedRealtime.timeUncertaintyNs = in.clock.elapsedRealTimeUnc; - } - } else { - const uint32_t UTC_TO_GPS_SECONDS = 315964800; - - if (in.clock.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_LEAP_SECOND_BIT && - in.clock.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_FULL_BIAS_BIT && - in.clock.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_BIT && - in.clock.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_UNCERTAINTY_BIT) { - int64_t currentTimeNanos = currentTime.tv_sec * 1000000000 + currentTime.tv_nsec; - int64_t measTimeNanos = (int64_t)in.clock.timeNs - (int64_t)in.clock.fullBiasNs - - (int64_t)in.clock.biasNs - (int64_t)in.clock.leapSecond * 1000000000 - + (int64_t)UTC_TO_GPS_SECONDS * 1000000000; - - LOC_LOGv("sinceBootTimeNanos:%" PRIi64 " currentTimeNanos:%" PRIi64 "" - " measTimeNanos:%" PRIi64 "", - sinceBootTimeNanos, currentTimeNanos, measTimeNanos); - if (currentTimeNanos >= measTimeNanos) { - int64_t ageTimeNanos = currentTimeNanos - measTimeNanos; - LOC_LOGv("ageTimeNanos:%" PRIi64 ")", ageTimeNanos); - // the max trusted propagation time 100ms for ageTimeNanos to avoid user - // setting wrong time, it will affect elapsedRealtimeNanos - if (ageTimeNanos <= 100000000) { - elapsedRealtime.flags |= V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS; - elapsedRealtime.timestampNs = sinceBootTimeNanos - ageTimeNanos; - elapsedRealtime.flags |= - V2_0::ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS; - // time uncertainty is 1 ms since it is calculated from utc time that - // is in ms - // time uncertainty is the max value between abs(AP_UTC - MP_UTC) and 100ms, - // to verify if user change the sys time - elapsedRealtime.timeUncertaintyNs = - std::max(ageTimeNanos, (int64_t)100000000); - } - } - } else { - LOC_LOGe("Failed to calculate elapsedRealtimeNanos timestamp"); - } - } + if (in.clock.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_ELAPSED_REAL_TIME_BIT) { + elapsedRealtime.flags |= V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS; + elapsedRealtime.timestampNs = in.clock.elapsedRealTime; + elapsedRealtime.flags |= V2_0::ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS; + elapsedRealtime.timeUncertaintyNs = in.clock.elapsedRealTimeUnc; + LOC_LOGd("elapsedRealtime.timestampNs=%" PRIi64 "" + " elapsedRealtime.timeUncertaintyNs=%" PRIi64 " elapsedRealtime.flags=0x%X", + elapsedRealtime.timestampNs, + elapsedRealtime.timeUncertaintyNs, elapsedRealtime.flags); } - LOC_LOGv("elapsedRealtime.timestampNs=%" PRIi64 "" - " elapsedRealtime.timeUncertaintyNs=%" PRIi64 " elapsedRealtime.flags=0x%X", - elapsedRealtime.timestampNs, - elapsedRealtime.timeUncertaintyNs, elapsedRealtime.flags); } } // namespace implementation diff --git a/gps/android/utils/battery_listener.cpp b/gps/android/utils/battery_listener.cpp index e8a092e..9cbfabd 100644 --- a/gps/android/utils/battery_listener.cpp +++ b/gps/android/utils/battery_listener.cpp @@ -45,8 +45,6 @@ using android::hardware::interfacesEqual; using android::hardware::Return; using android::hardware::Void; using android::hardware::health::V1_0::BatteryStatus; -using android::hardware::health::V1_0::toString; -using android::hardware::health::V2_0::get_health_service; using android::hardware::health::V2_1::HealthInfo; using android::hardware::health::V2_1::IHealthInfoCallback; using android::hardware::health::V2_1::IHealth; @@ -98,7 +96,7 @@ status_t BatteryListenerImpl::init() return INVALID_OPERATION; do { - mHealth = IHealth::getService("default", true); + mHealth = IHealth::getService(); if (mHealth != NULL) break; usleep(GET_HEALTH_SVC_WAIT_TIME_MS * 1000); diff --git a/gps/batching/BatchingAdapter.cpp b/gps/batching/BatchingAdapter.cpp index 135f0ed..4f1a43c 100644 --- a/gps/batching/BatchingAdapter.cpp +++ b/gps/batching/BatchingAdapter.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2020, 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,11 +38,8 @@ using namespace loc_core; BatchingAdapter::BatchingAdapter() : LocAdapterBase(0, - LocContext::getLocContext( - NULL, - NULL, - LocContext::mLocationHalName, - false)), + LocContext::getLocContext(LocContext::mLocationHalName), + false, nullptr, true), mOngoingTripDistance(0), mOngoingTripTBFInterval(0), mTripWithOngoingTBFDropped(false), @@ -55,6 +52,10 @@ BatchingAdapter::BatchingAdapter() : LOC_LOGD("%s]: Constructor", __func__); readConfigCommand(); setConfigCommand(); + + // at last step, let us inform adapater base that we are done + // with initialization, e.g.: ready to process handleEngineUpEvent + doneInit(); } void diff --git a/gps/core/ContextBase.cpp b/gps/core/ContextBase.cpp index 411c990..87e98dc 100644 --- a/gps/core/ContextBase.cpp +++ b/gps/core/ContextBase.cpp @@ -50,6 +50,7 @@ uint64_t ContextBase::sSupportedMsgMask = 0; bool ContextBase::sGnssMeasurementSupported = false; uint8_t ContextBase::sFeaturesSupported[MAX_FEATURE_LENGTH]; GnssNMEARptRate ContextBase::sNmeaReportRate = GNSS_NMEA_REPORT_RATE_NHZ; +LocationCapabilitiesMask ContextBase::sQwesFeatureMask = 0; const loc_param_s_type ContextBase::mGps_conf_table[] = { @@ -92,6 +93,7 @@ const loc_param_s_type ContextBase::mGps_conf_table[] = {"GNSS_DEPLOYMENT", &mGps_conf.GNSS_DEPLOYMENT, NULL, 'n'}, {"CUSTOM_NMEA_GGA_FIX_QUALITY_ENABLED", &mGps_conf.CUSTOM_NMEA_GGA_FIX_QUALITY_ENABLED, NULL, 'n'}, + {"NMEA_TAG_BLOCK_GROUPING_ENABLED", &mGps_conf.NMEA_TAG_BLOCK_GROUPING_ENABLED, NULL, 'n'}, {"NI_SUPL_DENY_ON_NFW_LOCKED", &mGps_conf.NI_SUPL_DENY_ON_NFW_LOCKED, NULL, 'n'}, {"ENABLE_NMEA_PRINT", &mGps_conf.ENABLE_NMEA_PRINT, NULL, 'n'} }; @@ -191,6 +193,8 @@ void ContextBase::readConfig() /* default configuration QTI GNSS H/W */ mGps_conf.GNSS_DEPLOYMENT = 0; mGps_conf.CUSTOM_NMEA_GGA_FIX_QUALITY_ENABLED = 0; + /* default NMEA Tag Block Grouping is disabled */ + mGps_conf.NMEA_TAG_BLOCK_GROUPING_ENABLED = 0; /* default configuration for NI_SUPL_DENY_ON_NFW_LOCKED */ mGps_conf.NI_SUPL_DENY_ON_NFW_LOCKED = 1; /* By default NMEA Printing is disabled */ diff --git a/gps/core/ContextBase.h b/gps/core/ContextBase.h index 85095c4..34cad60 100644 --- a/gps/core/ContextBase.h +++ b/gps/core/ContextBase.h @@ -35,6 +35,11 @@ #include #include #include +#ifdef NO_UNORDERED_SET_OR_MAP + #include +#else + #include +#endif /* GPS.conf support */ /* NOTE: the implementaiton of the parser casts number @@ -77,6 +82,7 @@ typedef struct loc_gps_cfg_s uint32_t CUSTOM_NMEA_GGA_FIX_QUALITY_ENABLED; uint32_t NI_SUPL_DENY_ON_NFW_LOCKED; uint32_t ENABLE_NMEA_PRINT; + uint32_t NMEA_TAG_BLOCK_GROUPING_ENABLED; } loc_gps_cfg_s_type; /* NOTE: the implementation of the parser casts number @@ -110,6 +116,8 @@ typedef struct double VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY; } loc_sap_cfg_s_type; +using namespace loc_util; + namespace loc_core { class LocAdapterBase; @@ -158,6 +166,7 @@ public: static uint8_t sFeaturesSupported[MAX_FEATURE_LENGTH]; static bool sGnssMeasurementSupported; static GnssNMEARptRate sNmeaReportRate; + static LocationCapabilitiesMask sQwesFeatureMask; void readConfig(); static uint32_t getCarrierCapabilities(); @@ -190,6 +199,118 @@ public: */ static bool gnssConstellationConfig(); + /* + set QWES feature status info + */ + static inline void setQwesFeatureStatus( + const std::unordered_map &featureMap) { + std::unordered_map::const_iterator itr; + static LocationQwesFeatureType locQwesFeatType[LOCATION_QWES_FEATURE_TYPE_MAX]; + for (itr = featureMap.begin(); itr != featureMap.end(); ++itr) { + LOC_LOGi("Feature : %d isValid: %d", itr->first, itr->second); + locQwesFeatType[itr->first] = itr->second; + switch (itr->first) { + case LOCATION_QWES_FEATURE_TYPE_CARRIER_PHASE: + if (itr->second) { + sQwesFeatureMask |= LOCATION_CAPABILITIES_QWES_CARRIER_PHASE_BIT; + } else { + sQwesFeatureMask &= ~LOCATION_CAPABILITIES_QWES_CARRIER_PHASE_BIT; + } + break; + case LOCATION_QWES_FEATURE_TYPE_SV_POLYNOMIAL: + if (itr->second) { + sQwesFeatureMask |= LOCATION_CAPABILITIES_QWES_SV_POLYNOMIAL_BIT; + } else { + sQwesFeatureMask &= ~LOCATION_CAPABILITIES_QWES_SV_POLYNOMIAL_BIT; + } + break; + case LOCATION_QWES_FEATURE_TYPE_GNSS_SINGLE_FREQUENCY: + if (itr->second) { + sQwesFeatureMask |= LOCATION_CAPABILITIES_QWES_GNSS_SINGLE_FREQUENCY; + } else { + sQwesFeatureMask &= ~LOCATION_CAPABILITIES_QWES_GNSS_SINGLE_FREQUENCY; + } + break; + case LOCATION_QWES_FEATURE_TYPE_SV_EPH: + if (itr->second) { + sQwesFeatureMask |= LOCATION_CAPABILITIES_QWES_SV_EPHEMERIS_BIT; + } else { + sQwesFeatureMask &= ~LOCATION_CAPABILITIES_QWES_SV_EPHEMERIS_BIT; + } + break; + case LOCATION_QWES_FEATURE_TYPE_GNSS_MULTI_FREQUENCY: + if (itr->second) { + sQwesFeatureMask |= LOCATION_CAPABILITIES_QWES_GNSS_MULTI_FREQUENCY; + } else { + sQwesFeatureMask &= ~LOCATION_CAPABILITIES_QWES_GNSS_MULTI_FREQUENCY; + } + break; + case LOCATION_QWES_FEATURE_TYPE_PPE: + if (itr->second) { + sQwesFeatureMask |= LOCATION_CAPABILITIES_QWES_PPE; + } else { + sQwesFeatureMask &= ~LOCATION_CAPABILITIES_QWES_PPE; + } + break; + case LOCATION_QWES_FEATURE_TYPE_QDR2: + if (itr->second) { + sQwesFeatureMask |= LOCATION_CAPABILITIES_QWES_QDR2; + } else { + sQwesFeatureMask &= ~LOCATION_CAPABILITIES_QWES_QDR2; + } + break; + case LOCATION_QWES_FEATURE_TYPE_QDR3: + if (itr->second) { + sQwesFeatureMask |= LOCATION_CAPABILITIES_QWES_QDR3; + } else { + sQwesFeatureMask &= ~LOCATION_CAPABILITIES_QWES_QDR3; + } + break; + case LOCATION_QWES_FEATURE_TYPE_VPE: + if (itr->second) { + sQwesFeatureMask |= LOCATION_CAPABILITIES_QWES_VPE; + } else { + sQwesFeatureMask &= ~LOCATION_CAPABILITIES_QWES_VPE; + } + break; + } + } + + // Set CV2X basic when time freq and tunc is set + // CV2X_BASIC = LOCATION_QWES_FEATURE_TYPE_TIME_FREQUENCY & + // LOCATION_QWES_FEATURE_TYPE_TIME_UNCERTAINTY + + // Set CV2X premium when time freq and tunc is set + // CV2X_PREMIUM = CV2X_BASIC & LOCATION_QWES_FEATURE_TYPE_QDR3 & + // LOCATION_QWES_FEATURE_TYPE_CLOCK_ESTIMATE + + bool cv2xBasicEnabled = (1 == locQwesFeatType[LOCATION_QWES_FEATURE_TYPE_TIME_FREQUENCY]) && + (1 == locQwesFeatType[LOCATION_QWES_FEATURE_TYPE_TIME_UNCERTAINTY]); + bool cv2xPremiumEnabled = cv2xBasicEnabled && + (1 == locQwesFeatType[LOCATION_QWES_FEATURE_TYPE_QDR3]) && + (1 == locQwesFeatType[LOCATION_QWES_FEATURE_TYPE_CLOCK_ESTIMATE]); + + LOC_LOGd("CV2X_BASIC:%d, CV2X_PREMIUM:%d", cv2xBasicEnabled, cv2xPremiumEnabled); + if (cv2xBasicEnabled) { + sQwesFeatureMask |= LOCATION_CAPABILITIES_QWES_CV2X_LOCATION_BASIC; + } else { + sQwesFeatureMask &= ~LOCATION_CAPABILITIES_QWES_CV2X_LOCATION_BASIC; + } + if (cv2xPremiumEnabled) { + sQwesFeatureMask |= LOCATION_CAPABILITIES_QWES_CV2X_LOCATION_PREMIUM; + } else { + sQwesFeatureMask &= ~LOCATION_CAPABILITIES_QWES_CV2X_LOCATION_PREMIUM; + } + } + + /* + get QWES feature status info + */ + static inline LocationCapabilitiesMask getQwesFeatureStatus() { + return (ContextBase::sQwesFeatureMask); + } + + }; struct LocApiResponse: LocMsg { diff --git a/gps/core/EngineHubProxyBase.h b/gps/core/EngineHubProxyBase.h index f7fe4d2..468a8f0 100644 --- a/gps/core/EngineHubProxyBase.h +++ b/gps/core/EngineHubProxyBase.h @@ -28,9 +28,16 @@ */ #ifndef ENGINE_HUB_PROXY_BASE_H #define ENGINE_HUB_PROXY_BASE_H +#ifdef NO_UNORDERED_SET_OR_MAP + #include +#else + #include +#endif namespace loc_core { +using namespace loc_util; + class EngineHubProxyBase { public: inline EngineHubProxyBase() { @@ -112,6 +119,13 @@ public: (void) dreConfig; return false; } + + inline virtual bool configEngineRunState( + PositioningEngineMask engType, LocEngineRunState engState) { + (void) engType; + (void) engState; + return false; + } }; typedef std::function @@ -127,6 +141,9 @@ typedef std::function typedef std::function GnssAdapterUpdateNHzRequirementCb; +typedef std::function &featureMap)> + GnssAdapterUpdateQwesFeatureStatusCb; + // potential parameters: message queue: MsgTask * msgTask; // callback function to report back dr and ppe position and sv report typedef EngineHubProxyBase* (getEngHubProxyFn)( @@ -135,7 +152,8 @@ typedef EngineHubProxyBase* (getEngHubProxyFn)( GnssAdapterReportEnginePositionsEventCb positionEventCb, GnssAdapterReportSvEventCb svEventCb, GnssAdapterReqAidingDataCb reqAidingDataCb, - GnssAdapterUpdateNHzRequirementCb updateNHzRequirementCb); + GnssAdapterUpdateNHzRequirementCb updateNHzRequirementCb, + GnssAdapterUpdateQwesFeatureStatusCb updateQwesFeatureStatusCb); } // namespace loc_core diff --git a/gps/core/LocAdapterBase.cpp b/gps/core/LocAdapterBase.cpp index 5ada84b..95f2728 100644 --- a/gps/core/LocAdapterBase.cpp +++ b/gps/core/LocAdapterBase.cpp @@ -428,4 +428,12 @@ LocAdapterBase::requestCapabilitiesCommand(LocationAPI* client) sendMsg(new MsgRequestCapabilities(*this, client)); } +void +LocAdapterBase::reportLatencyInfoEvent(const GnssLatencyInfo& /*gnssLatencyInfo*/) +DEFAULT_IMPL() + +bool LocAdapterBase:: + reportQwesCapabilities(const std::unordered_map &featureMap) +DEFAULT_IMPL(false) + } // namespace loc_core diff --git a/gps/core/LocAdapterBase.h b/gps/core/LocAdapterBase.h index 4a5d1ab..51b2306 100644 --- a/gps/core/LocAdapterBase.h +++ b/gps/core/LocAdapterBase.h @@ -156,7 +156,7 @@ public: return ContextBase::isFeatureSupported(featureVal); } - uint32_t generateSessionId(); + static uint32_t generateSessionId(); inline bool isAdapterMaster() { return mIsMaster; @@ -236,6 +236,9 @@ public: removeClientCompleteCallback rmClientCb); void requestCapabilitiesCommand(LocationAPI* client); + virtual void reportLatencyInfoEvent(const GnssLatencyInfo& gnssLatencyInfo); + virtual bool reportQwesCapabilities( + const std::unordered_map &featureMap); }; } // namespace loc_core diff --git a/gps/core/LocApiBase.cpp b/gps/core/LocApiBase.cpp index 55ba72e..6a0ff84 100644 --- a/gps/core/LocApiBase.cpp +++ b/gps/core/LocApiBase.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2014, 2016-2020 The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2014, 2016-2021 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,6 +36,7 @@ #include #include #include +#include namespace loc_core { @@ -160,7 +161,7 @@ LocApiBase::LocApiBase(LOC_API_ADAPTER_EVENT_MASK_T excludedMask, android_atomic_inc(&mMsgTaskRefCount); if (nullptr == mMsgTask) { - mMsgTask = new MsgTask("LocApiMsgTask", false); + mMsgTask = new MsgTask("LocApiMsgTask"); } } @@ -483,6 +484,14 @@ void LocApiBase::reportLocationSystemInfo(const LocationSystemInfo& locationSyst TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportLocationSystemInfoEvent(locationSystemInfo)); } +void LocApiBase::reportQwesCapabilities +( + const std::unordered_map &featureMap +) +{ + // loop through adapters, and deliver to all adapters. + TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportQwesCapabilities(featureMap)); +} void LocApiBase::requestXtraData() { // loop through adapters, and deliver to the first handling adapter. @@ -600,6 +609,12 @@ void LocApiBase::reportGnssConfig(uint32_t sessionId, const GnssConfig& gnssConf TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportGnssConfigEvent(sessionId, gnssConfig)); } +void LocApiBase::reportLatencyInfo(GnssLatencyInfo& gnssLatencyInfo) +{ + // loop through adapters, and deliver to the first handling adapter. + TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportLatencyInfoEvent(gnssLatencyInfo)); +} + enum loc_api_adapter_err LocApiBase:: open(LOC_API_ADAPTER_EVENT_MASK_T /*mask*/) DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) @@ -635,10 +650,6 @@ void LocApiBase:: setTime(LocGpsUtcTime /*time*/, int64_t /*timeReference*/, int /*uncertainty*/) DEFAULT_IMPL() -enum loc_api_adapter_err LocApiBase:: - setXtraData(char* /*data*/, int /*length*/) -DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) - void LocApiBase:: atlOpenStatus(int /*handle*/, int /*is_succ*/, char* /*apn*/, uint32_t /*apnLen*/, AGpsBearerType /*bear*/, LocAGpsType /*agpsType*/, @@ -725,9 +736,9 @@ LocationError LocApiBase::setEmergencyExtensionWindowSync( const uint32_t /*emergencyExtensionSeconds*/) DEFAULT_IMPL(LOCATION_ERROR_SUCCESS) -LocationError LocApiBase::setMeasurementCorrections( - const GnssMeasurementCorrections /*gnssMeasurementCorrections*/) -DEFAULT_IMPL(LOCATION_ERROR_SUCCESS) +void LocApiBase::setMeasurementCorrections( + const GnssMeasurementCorrections& /*gnssMeasurementCorrections*/) +DEFAULT_IMPL() void LocApiBase:: getWwanZppFix() @@ -745,12 +756,6 @@ void LocApiBase:: requestForAidingData(GnssAidingDataSvMask /*svDataMask*/) DEFAULT_IMPL() -void LocApiBase:: - installAGpsCert(const LocDerEncodedCertificate* /*pData*/, - size_t /*length*/, - uint32_t /*slotBitMask*/) -DEFAULT_IMPL() - LocationError LocApiBase:: setXtraVersionCheckSync(uint32_t /*check*/) DEFAULT_IMPL(LOCATION_ERROR_SUCCESS) @@ -787,8 +792,8 @@ void LocApiBase:: LocApiResponse* /*adapterResponse*/) DEFAULT_IMPL() -LocationError LocApiBase::getGnssEnergyConsumed() -DEFAULT_IMPL(LOCATION_ERROR_SUCCESS) +void LocApiBase::getGnssEnergyConsumed() +DEFAULT_IMPL() void LocApiBase::addGeofence(uint32_t /*clientId*/, const GeofenceOption& /*options*/, @@ -923,4 +928,142 @@ DEFAULT_IMPL() void LocApiBase:: getConstellationMultiBandConfig(uint32_t sessionId, LocApiResponse* /*adapterResponse*/) DEFAULT_IMPL() + +int64_t ElapsedRealtimeEstimator::getElapsedRealtimeEstimateNanos(int64_t curDataTimeNanos, + bool isCurDataTimeTrustable, int64_t tbf) { + //The algorithm works follow below steps: + //When isCurDataTimeTrustable is meet (means Modem timestamp is already stable), + //1, Wait for mFixTimeStablizationThreshold fixes; While waiting for modem time + // stable, we set the traveltime to a default value; + //2, When the mFixTimeStablizationThreshold fix comes, we think now the mode time + // is already stable, calculate the initial AP-Modem clock diff(mCurrentClockDiff) + // using formula: + // mCurrentClockDiff = currentTimeNanos - locationTimeNanos - currentTravelTimeNanos + //3, since then, when the nth fix comes, + // 3.1 First update mCurrentClockDiff using below formula: + // mCurrentClockDiff = mCurrentClockDiff + (currentTimeNanos - sinceBootTimeNanos) + // - (mPrevUtcTimeNanos - mPrevBootTimeNanos) + // 3.2 Calculate currentTravelTimeNanos: + // currentTravelTimeNanos = currentTimeNanos - locationTimeNanos - mCurrentClockDiff + //4, It is possible that locationTimeNanos will jump, + // reset mFixTimeStablizationThreshold to default value, jump to step 2 to continue. + + int64_t currentTravelTimeNanos = mInitialTravelTime; + struct timespec currentTime; + int64_t sinceBootTimeNanos; + if (getCurrentTime(currentTime, sinceBootTimeNanos)) { + if (isCurDataTimeTrustable) { + if (tbf > 0 && tbf != curDataTimeNanos - mPrevDataTimeNanos) { + mFixTimeStablizationThreshold = 5; + } + int64_t currentTimeNanos = (int64_t)currentTime.tv_sec*1000000000 + currentTime.tv_nsec; + LOC_LOGd("sinceBootTimeNanos:%" PRIi64 " currentTimeNanos:%" PRIi64 "" + " locationTimeNanos:%" PRIi64 "", + sinceBootTimeNanos, currentTimeNanos, curDataTimeNanos); + if (mFixTimeStablizationThreshold == 0) { + currentTravelTimeNanos = mInitialTravelTime; + mCurrentClockDiff = currentTimeNanos - curDataTimeNanos - currentTravelTimeNanos; + } else if (mFixTimeStablizationThreshold < 0) { + mCurrentClockDiff = mCurrentClockDiff + (currentTimeNanos - sinceBootTimeNanos) + - (mPrevUtcTimeNanos - mPrevBootTimeNanos); + currentTravelTimeNanos = currentTimeNanos - curDataTimeNanos - mCurrentClockDiff; + } + + mPrevUtcTimeNanos = currentTimeNanos; + mPrevBootTimeNanos = sinceBootTimeNanos; + mPrevDataTimeNanos = curDataTimeNanos; + mFixTimeStablizationThreshold--; + } + } else { + return -1; + } + LOC_LOGd("Estimated travel time: %" PRIi64 "", currentTravelTimeNanos); + return (sinceBootTimeNanos - currentTravelTimeNanos); +} + +void ElapsedRealtimeEstimator::reset() { + mCurrentClockDiff = 0; + mPrevDataTimeNanos = 0; + mPrevUtcTimeNanos = 0; + mPrevBootTimeNanos = 0; + mFixTimeStablizationThreshold = 5; +} + +int64_t ElapsedRealtimeEstimator::getElapsedRealtimeQtimer(int64_t qtimerTicksAtOrigin) { + struct timespec currentTime; + int64_t sinceBootTimeNanos; + int64_t elapsedRealTimeNanos; + + if (getCurrentTime(currentTime, sinceBootTimeNanos)) { + uint64_t qtimerDiff = 0; + uint64_t qTimerTickCount = getQTimerTickCount(); + if (qTimerTickCount >= qtimerTicksAtOrigin) { + qtimerDiff = qTimerTickCount - qtimerTicksAtOrigin; + } + LOC_LOGd("sinceBootTimeNanos:%" PRIi64 " qtimerTicksAtOrigin=%" PRIi64 "" + " qTimerTickCount=%" PRIi64 " qtimerDiff=%" PRIi64 "", + sinceBootTimeNanos, qtimerTicksAtOrigin, qTimerTickCount, qtimerDiff); + uint64_t qTimerDiffNanos = qTimerTicksToNanos(double(qtimerDiff)); + + /* If the time difference between Qtimer on modem side and Qtimer on AP side + is greater than one second we assume this is a dual-SoC device such as + Kona and will try to get Qtimer on modem side and on AP side and + will adjust our difference accordingly */ + if (qTimerDiffNanos > 1000000000) { + uint64_t qtimerDelta = getQTimerDeltaNanos(); + if (qTimerDiffNanos >= qtimerDelta) { + qTimerDiffNanos -= qtimerDelta; + } + } + + LOC_LOGd("Qtimer travel time: %" PRIi64 "", qTimerDiffNanos); + if (sinceBootTimeNanos >= qTimerDiffNanos) { + elapsedRealTimeNanos = sinceBootTimeNanos - qTimerDiffNanos; + } else { + elapsedRealTimeNanos = -1; + } + } else { + elapsedRealTimeNanos = -1; + } + return elapsedRealTimeNanos; +} + +bool ElapsedRealtimeEstimator::getCurrentTime( + struct timespec& currentTime, int64_t& sinceBootTimeNanos) +{ + struct timespec sinceBootTime; + struct timespec sinceBootTimeTest; + bool clockGetTimeSuccess = false; + const uint32_t MAX_TIME_DELTA_VALUE_NANOS = 10000; + const uint32_t MAX_GET_TIME_COUNT = 20; + /* Attempt to get CLOCK_REALTIME and CLOCK_BOOTIME in succession without an interruption + or context switch (for up to MAX_GET_TIME_COUNT times) to avoid errors in the calculation */ + for (uint32_t i = 0; i < MAX_GET_TIME_COUNT; i++) { + if (clock_gettime(CLOCK_BOOTTIME, &sinceBootTime) != 0) { + break; + }; + if (clock_gettime(CLOCK_REALTIME, ¤tTime) != 0) { + break; + } + if (clock_gettime(CLOCK_BOOTTIME, &sinceBootTimeTest) != 0) { + break; + }; + sinceBootTimeNanos = (int64_t)sinceBootTime.tv_sec * 1000000000 + sinceBootTime.tv_nsec; + int64_t sinceBootTimeTestNanos = + (int64_t)sinceBootTimeTest.tv_sec * 1000000000 + sinceBootTimeTest.tv_nsec; + int64_t sinceBootTimeDeltaNanos = sinceBootTimeTestNanos - sinceBootTimeNanos; + + /* sinceBootTime and sinceBootTimeTest should have a close value if there was no + interruption or context switch between clock_gettime for CLOCK_BOOTIME and + clock_gettime for CLOCK_REALTIME */ + if (sinceBootTimeDeltaNanos < MAX_TIME_DELTA_VALUE_NANOS) { + clockGetTimeSuccess = true; + break; + } else { + LOC_LOGd("Delta:%" PRIi64 "ns time too large, retry number #%u...", + sinceBootTimeDeltaNanos, i + 1); + } + } + return clockGetTimeSuccess; +} } // namespace loc_core diff --git a/gps/core/LocApiBase.h b/gps/core/LocApiBase.h index db0f490..121f795 100644 --- a/gps/core/LocApiBase.h +++ b/gps/core/LocApiBase.h @@ -36,6 +36,15 @@ #include #include #include +#ifdef NO_UNORDERED_SET_OR_MAP + #include +#else + #include +#endif +#include +#include + +using namespace loc_util; namespace loc_core { @@ -120,7 +129,7 @@ protected: inline virtual ~LocApiBase() { android_atomic_dec(&mMsgTaskRefCount); if (nullptr != mMsgTask && 0 == mMsgTaskRefCount) { - mMsgTask->destroy(); + delete mMsgTask; mMsgTask = nullptr; } } @@ -192,6 +201,11 @@ public: void reportGnssAdditionalSystemInfo(GnssAdditionalSystemInfo& additionalSystemInfo); void sendNfwNotification(GnssNfwNotification& notification); void reportGnssConfig(uint32_t sessionId, const GnssConfig& gnssConfig); + void reportLatencyInfo(GnssLatencyInfo& gnssLatencyInfo); + void reportQwesCapabilities + ( + const std::unordered_map &featureMap + ); void geofenceBreach(size_t count, uint32_t* hwIds, Location& location, GeofenceBreachType breachType, uint64_t timestamp); @@ -216,7 +230,6 @@ public: 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); @@ -244,13 +257,11 @@ public: virtual GnssConfigLppeControlPlaneMask convertLppeCp(const uint32_t lppeControlPlaneMask); virtual GnssConfigLppeUserPlaneMask convertLppeUp(const uint32_t lppeUserPlaneMask); virtual LocationError setEmergencyExtensionWindowSync(const uint32_t emergencyExtensionSeconds); - virtual LocationError setMeasurementCorrections( - const GnssMeasurementCorrections gnssMeasurementCorrections); + virtual void setMeasurementCorrections( + const GnssMeasurementCorrections& gnssMeasurementCorrections); virtual void getWwanZppFix(); virtual void getBestAvailableZppFix(); - 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); @@ -270,7 +281,7 @@ public: LocApiResponse* adapterResponse=nullptr); virtual void setPositionAssistedClockEstimatorMode(bool enabled, LocApiResponse* adapterResponse=nullptr); - virtual LocationError getGnssEnergyConsumed(); + virtual void getGnssEnergyConsumed(); virtual void addGeofence(uint32_t clientId, const GeofenceOption& options, const GeofenceInfo& info, LocApiResponseData* adapterResponseData); @@ -335,6 +346,27 @@ public: LocApiResponse* adapterResponse=nullptr); }; +class ElapsedRealtimeEstimator { +private: + int64_t mCurrentClockDiff; + int64_t mPrevUtcTimeNanos; + int64_t mPrevBootTimeNanos; + int64_t mFixTimeStablizationThreshold; + int64_t mInitialTravelTime; + int64_t mPrevDataTimeNanos; +public: + + ElapsedRealtimeEstimator(int64_t travelTimeNanosEstimate): + mInitialTravelTime(travelTimeNanosEstimate) {reset();} + int64_t getElapsedRealtimeEstimateNanos(int64_t curDataTimeNanos, + bool isCurDataTimeTrustable, int64_t tbf); + inline int64_t getElapsedRealtimeUncNanos() { return 5000000;} + void reset(); + + static int64_t getElapsedRealtimeQtimer(int64_t qtimerTicksAtOrigin); + static bool getCurrentTime(struct timespec& currentTime, int64_t& sinceBootTimeNanos); +}; + typedef LocApiBase* (getLocApi_t)(LOC_API_ADAPTER_EVENT_MASK_T exMask, ContextBase *context); diff --git a/gps/core/LocContext.cpp b/gps/core/LocContext.cpp index 18d3f2d..272c08c 100644 --- a/gps/core/LocContext.cpp +++ b/gps/core/LocContext.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2014, 2016-2019 The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2014, 2016-2020 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,36 +50,25 @@ const char* LocContext::mLBSLibName = "liblbs_core.so.1"; pthread_mutex_t LocContext::mGetLocContextMutex = PTHREAD_MUTEX_INITIALIZER; -const MsgTask* LocContext::getMsgTask(LocThread::tCreate tCreator, - const char* name, bool joinable) +const MsgTask* LocContext::getMsgTask(const char* name) { if (NULL == mMsgTask) { - mMsgTask = new MsgTask(tCreator, name, joinable); + mMsgTask = new MsgTask(name); } 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) +ContextBase* LocContext::getLocContext(const char* name) { 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); + const MsgTask* msgTask = getMsgTask(name); mContext = new LocContext(msgTask); } pthread_mutex_unlock(&LocContext::mGetLocContextMutex); - if (firstMsg) { - mContext->sendMsg(firstMsg); - } - return mContext; } diff --git a/gps/core/LocContext.h b/gps/core/LocContext.h index fb7d009..628ed93 100644 --- a/gps/core/LocContext.h +++ b/gps/core/LocContext.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2014, 2017-2019 The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2014, 2017-2020 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 @@ -39,9 +39,7 @@ namespace loc_core { class LocContext : public ContextBase { static const MsgTask* mMsgTask; 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 const MsgTask* getMsgTask(const char* name); static pthread_mutex_t mGetLocContextMutex; protected: @@ -52,11 +50,7 @@ public: static const char* mLBSLibName; static const char* mLocationHalName; - static ContextBase* getLocContext(LocThread::tCreate tCreator, LocMsg* firstMsg, - const char* name, bool joinable = true); - inline static ContextBase* getLocContext(const char* name, bool joinable = true) { - return getLocContext(NULL, NULL, name, joinable); - } + static ContextBase* getLocContext(const char* name); static void injectFeatureConfig(ContextBase *context); }; diff --git a/gps/core/SystemStatus.cpp b/gps/core/SystemStatus.cpp index ffe7a9c..fe11de0 100644 --- a/gps/core/SystemStatus.cpp +++ b/gps/core/SystemStatus.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2021, 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 @@ -1287,6 +1287,14 @@ void SystemStatus::destroyInstance() mInstance = NULL; } +void SystemStatus::resetNetworkInfo() { + for (int i=0; igetId(), ret); return ret; } @@ -1724,11 +1733,12 @@ bool SystemStatus::setDefaultGnssEngineStates(void) @return true when successfully done ******************************************************************************/ bool SystemStatus::eventConnectionStatus(bool connected, int8_t type, - bool roaming, NetworkHandle networkHandle) + bool roaming, NetworkHandle networkHandle, + string& apn) { // send networkinof dataitem to systemstatus observer clients SystemStatusNetworkInfo s(type, "", "", connected, roaming, - (uint64_t) networkHandle); + (uint64_t) networkHandle, apn); mSysStatusObsvr.notify({&s}); return true; diff --git a/gps/core/SystemStatus.h b/gps/core/SystemStatus.h index 8d5d9ac..bd4279e 100644 --- a/gps/core/SystemStatus.h +++ b/gps/core/SystemStatus.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2021, 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 @@ -482,12 +482,13 @@ class SystemStatusNetworkInfo : public SystemStatusItemBase, NetworkInfoDataItemBase* mSrcObjPtr; public: inline SystemStatusNetworkInfo( - int32_t type=0, - std::string typeName="", - string subTypeName="", - bool connected=false, - bool roaming=false, - uint64_t networkHandle=NETWORK_HANDLE_UNKNOWN) : + int32_t type = 0, + std::string typeName = "", + string subTypeName = "", + bool connected = false, + bool roaming = false, + uint64_t networkHandle = NETWORK_HANDLE_UNKNOWN, + string apn = "") : NetworkInfoDataItemBase( (NetworkType)type, type, @@ -496,30 +497,33 @@ public: connected && (!roaming), connected, roaming, - networkHandle), + networkHandle, apn), mSrcObjPtr(nullptr) {} inline SystemStatusNetworkInfo(const NetworkInfoDataItemBase& itemBase) : NetworkInfoDataItemBase(itemBase), mSrcObjPtr((NetworkInfoDataItemBase*)&itemBase) { - mType = itemBase.getType(); + mType = (int32_t)itemBase.getType(); } inline bool equals(const SystemStatusNetworkInfo& peer) { - for (uint8_t i = 0; i < MAX_NETWORK_HANDLES; ++i) { - if (!(mAllNetworkHandles[i] == peer.mAllNetworkHandles[i])) { - return false; - } - } - return true; + bool rtv = (peer.mConnected == mConnected); + for (uint8_t i = 0; rtv && i < MAX_NETWORK_HANDLES; ++i) { + rtv &= (mAllNetworkHandles[i] == peer.mAllNetworkHandles[i]); + } + return rtv & peer.mApn.compare(mApn); } inline virtual SystemStatusItemBase& collate(SystemStatusItemBase& curInfo) { + LOC_LOGv("NetworkInfo: mAllTypes=%" PRIx64 " connected=%u mType=%x mApn=%s", + mAllTypes, mConnected, mType, mApn.c_str()); uint64_t allTypes = (static_cast(curInfo)).mAllTypes; - uint64_t networkHandle = - (static_cast(curInfo)).mNetworkHandle; - int32_t type = (static_cast(curInfo)).mType; + string& apn = (static_cast(curInfo)).mApn; // Replace current with cached table for now and then update memcpy(mAllNetworkHandles, (static_cast(curInfo)).getNetworkHandle(), sizeof(mAllNetworkHandles)); + // Update the apn for non-mobile type connections. + if (TYPE_MOBILE != mType && apn.compare("") != 0) { + mApn = apn; + } if (mConnected) { mAllTypes |= allTypes; for (uint8_t i = 0; i < MAX_NETWORK_HANDLES; ++i) { @@ -542,21 +546,21 @@ public: ++lastValidIndex) { // Maintain count for number of network handles still // connected for given type - if (mType == mAllNetworkHandles[lastValidIndex].networkType) { - typeCount++; + if (mType == (int32_t)mAllNetworkHandles[lastValidIndex].networkType) { + if (mNetworkHandle == mAllNetworkHandles[lastValidIndex].networkHandle) { + deletedIndex = lastValidIndex; + } else { + typeCount++; + } } - if (mNetworkHandle == mAllNetworkHandles[lastValidIndex].networkHandle) { - deletedIndex = lastValidIndex; - typeCount--; - } } - if (MAX_NETWORK_HANDLES == lastValidIndex) { + if (lastValidIndex > 0) { --lastValidIndex; } if (MAX_NETWORK_HANDLES != deletedIndex) { - LOC_LOGD("deletedIndex:%u, lastValidIndex:%u, typeCount:%u", + LOC_LOGd("deletedIndex:%u, lastValidIndex:%u, typeCount:%u", deletedIndex, lastValidIndex, typeCount); mAllNetworkHandles[deletedIndex] = mAllNetworkHandles[lastValidIndex]; mAllNetworkHandles[lastValidIndex].networkHandle = NETWORK_HANDLE_UNKNOWN; @@ -581,8 +585,8 @@ public: return *this; } inline void dump(void) override { - LOC_LOGD("NetworkInfo: mAllTypes=%" PRIx64 " connected=%u mType=%x", - mAllTypes, mConnected, mType); + LOC_LOGD("NetworkInfo: mAllTypes=%" PRIx64 " connected=%u mType=%x mApn=%s", + mAllTypes, mConnected, mType, mApn.c_str()); } }; @@ -911,8 +915,9 @@ public: bool getReport(SystemStatusReports& reports, bool isLatestonly = false) const; bool setDefaultGnssEngineStates(void); bool eventConnectionStatus(bool connected, int8_t type, - bool roaming, NetworkHandle networkHandle); + bool roaming, NetworkHandle networkHandle, string& apn); bool updatePowerConnectState(bool charging); + void resetNetworkInfo(); }; } // namespace loc_core diff --git a/gps/core/data-items/DataItemConcreteTypesBase.h b/gps/core/data-items/DataItemConcreteTypesBase.h index c32d65d..11a3cce 100644 --- a/gps/core/data-items/DataItemConcreteTypesBase.h +++ b/gps/core/data-items/DataItemConcreteTypesBase.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, 2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2017, 2020, 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 @@ -284,7 +284,7 @@ class NetworkInfoDataItemBase : public IDataItemCore { public: NetworkInfoDataItemBase( NetworkType initialType, int32_t type, string typeName, string subTypeName, - bool available, bool connected, bool roaming, uint64_t networkHandle ): + bool available, bool connected, bool roaming, uint64_t networkHandle, string apn): mAllTypes(typeToAllTypes(initialType)), mType(type), mTypeName(typeName), @@ -293,7 +293,7 @@ public: mConnected(connected), mRoaming(roaming), mNetworkHandle(networkHandle), - mId(NETWORKINFO_DATA_ITEM_ID) { + mId(NETWORKINFO_DATA_ITEM_ID), mApn(apn) { mAllNetworkHandles[0].networkHandle = networkHandle; mAllNetworkHandles[0].networkType = initialType; } @@ -318,6 +318,7 @@ public: bool mRoaming; NetworkInfoType mAllNetworkHandles[MAX_NETWORK_HANDLES]; uint64_t mNetworkHandle; + string mApn; protected: DataItemId mId; inline uint64_t typeToAllTypes(NetworkType type) { diff --git a/gps/etc/seccomp_policy/gnss@2.0-base.policy b/gps/etc/seccomp_policy/gnss@2.0-base.policy index 7b93037..0a2e17b 100644 --- a/gps/etc/seccomp_policy/gnss@2.0-base.policy +++ b/gps/etc/seccomp_policy/gnss@2.0-base.policy @@ -93,3 +93,27 @@ sendmsg: 1 sendto: 1 recvfrom: 1 +getsockname: 1 +nanosleep: 1 +clone: 1 +setsockopt: 1 +getsockopt: 1 +madvise: 1 + +getitimer: 1 +setitimer: 1 +getpid: 1 +bind: 1 +listen: 1 +getpeername: 1 +socketpair: 1 +wait4: 1 +chown: 1 +fchown: 1 +lchown: 1 +umask: 1 +mmap2: 1 +fstat64: 1 +fstatat64: 1 +_llseek: 1 +geteuid: 1 diff --git a/gps/etc/seccomp_policy/gnss@2.0-xtwifi-client.policy b/gps/etc/seccomp_policy/gnss@2.0-xtwifi-client.policy index 17df31a..38a41f9 100644 --- a/gps/etc/seccomp_policy/gnss@2.0-xtwifi-client.policy +++ b/gps/etc/seccomp_policy/gnss@2.0-xtwifi-client.policy @@ -32,7 +32,7 @@ fdatasync: 1 getdents64: 1 gettimeofday: 1 -#ioctl: arg1 == _IOC(_IOC_NONE || arg1 == _IOC(_IOC_READ || arg1 == VSOC_MAYBE_SEND_INTERRUPT_TO_HOST +ioctl: 1 lseek: 1 madvise: 1 mkdirat: 1 @@ -43,3 +43,31 @@ timerfd_settime: 1 epoll_create1: 1 epoll_pwait: 1 epoll_ctl: 1 + +sched_getaffinity: 1 +gettid: 1 +fchown: 1 +fchmod: 1 +fchmodat: 1 +getsockopt: 1 +fchownat: 1 +fstat: 1 +fstatfs: 1 +newfstatat: 1 +sendmsg: 1 +recvmsg: 1 +gettimeofday: 1 +setsockopt: 1 +rt_tgsigqueueinfo: 1 +ioctl: 1 +mmap: 1 +getuid32: 1 +getuid: 1 +fstat64: 1 +fstatat64: 1 +mkdir: 1 +rmdir: 1 +creat: 1 +chmod: 1 +lseek: 1 +geteuid32: 1 diff --git a/gps/etc/seccomp_policy/gnss@2.0-xtwifi-inet-agent.policy b/gps/etc/seccomp_policy/gnss@2.0-xtwifi-inet-agent.policy index 00df6c7..024600a 100644 --- a/gps/etc/seccomp_policy/gnss@2.0-xtwifi-inet-agent.policy +++ b/gps/etc/seccomp_policy/gnss@2.0-xtwifi-inet-agent.policy @@ -31,3 +31,13 @@ unlinkat: 1 sched_getaffinity: 1 +newfstatat: 1 +fchmodat: 1 +madvise: 1 +mmap: 1 +getuid: 1 +getuid32: 1 +fstat64: 1 +fstatat64: 1 +gettimeofday: 1 +getdents64: 1 diff --git a/gps/geofence/GeofenceAdapter.cpp b/gps/geofence/GeofenceAdapter.cpp index e299589..1aeea0a 100644 --- a/gps/geofence/GeofenceAdapter.cpp +++ b/gps/geofence/GeofenceAdapter.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2021, 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 @@ -37,14 +37,14 @@ using namespace loc_core; GeofenceAdapter::GeofenceAdapter() : LocAdapterBase(0, - LocContext::getLocContext( - NULL, - NULL, - LocContext::mLocationHalName, - false), - true /*isMaster*/) + LocContext::getLocContext(LocContext::mLocationHalName), + true /*isMaster*/, nullptr, true) { LOC_LOGD("%s]: Constructor", __func__); + + // at last step, let us inform adapater base that we are done + // with initialization, e.g.: ready to process handleEngineUpEvent + doneInit(); } void diff --git a/gps/gnss/Agps.cpp b/gps/gnss/Agps.cpp index 9255f88..4344a6f 100644 --- a/gps/gnss/Agps.cpp +++ b/gps/gnss/Agps.cpp @@ -448,7 +448,7 @@ void AgpsStateMachine::setAPN(char* apn, unsigned int len){ mAPN = NULL; } - if (NULL == apn || len <= 0 || len > MAX_APN_LEN || strlen(apn) != len) { + if (NULL == apn || len > MAX_APN_LEN || strlen(apn) != len) { LOC_LOGD("Invalid apn len (%d) or null apn", len); mAPN = NULL; mAPNLen = 0; diff --git a/gps/gnss/Agps.h b/gps/gnss/Agps.h index d559377..8a27cd9 100644 --- a/gps/gnss/Agps.h +++ b/gps/gnss/Agps.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, 2020 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 @@ -37,6 +37,8 @@ #include #include +using namespace loc_util; + /* ATL callback function pointers * Passed in by Adapter to AgpsManager */ typedef std::function #define RAD2DEG (180.0 / M_PI) +#define DEG2RAD (M_PI / 180.0) #define PROCESS_NAME_ENGINE_SERVICE "engine-service" #define MIN_TRACKING_INTERVAL (100) // 100 msec @@ -61,6 +62,11 @@ using namespace loc_core; +static int loadEngHubForExternalEngine = 0; +static loc_param_s_type izatConfParamTable[] = { + {"LOAD_ENGHUB_FOR_EXTERNAL_ENGINE", &loadEngHubForExternalEngine, nullptr,'n'} +}; + /* Method to fetch status cb from loc_net_iface library */ typedef AgpsCbInfo& (*LocAgpsGetAgpsCbInfo)(LocAgpsOpenResultCb openResultCb, LocAgpsCloseResultCb closeResultCb, void* userDataPtr); @@ -71,13 +77,19 @@ static void agpsCloseResultCb (bool isSuccess, AGpsExtType agpsType, void* userD typedef const CdfwInterface* (*getCdfwInterface)(); +inline bool GnssReportLoggerUtil::isLogEnabled() { + return (mLogLatency != nullptr); +} + +inline void GnssReportLoggerUtil::log(const GnssLatencyInfo& gnssLatencyMeasInfo) { + if (mLogLatency != nullptr) { + mLogLatency(gnssLatencyMeasInfo); + } +} GnssAdapter::GnssAdapter() : LocAdapterBase(0, - LocContext::getLocContext(NULL, - NULL, - LocContext::mLocationHalName, - false), + LocContext::getLocContext(LocContext::mLocationHalName), true, nullptr, true), mEngHubProxy(new EngineHubProxyBase()), mQDgnssListenerHDL(nullptr), @@ -107,8 +119,9 @@ GnssAdapter::GnssAdapter() : mSystemStatus(SystemStatus::getInstance(mMsgTask)), mServerUrl(":"), mXtraObserver(mSystemStatus->getOsObserver(), mMsgTask), - mLocSystemInfo{}, mBlockCPIInfo{}, + mDreIntEnabled(false), + mLocSystemInfo{}, mNfwCb(NULL), mPowerOn(false), mAllowFlpNetworkFixes(0), @@ -124,7 +137,8 @@ GnssAdapter::GnssAdapter() : mLastDeleteAidingDataTime(0), mDgnssState(0), mSendNmeaConsent(false), - mDgnssLastNmeaBootTimeMilli(0) + mDgnssLastNmeaBootTimeMilli(0), + mNativeAgpsHandler(mSystemStatus->getOsObserver(), *this) { LOC_LOGD("%s]: Constructor %p", __func__, this); mLocPositionMode.mode = LOC_POSITION_MODE_INVALID; @@ -226,8 +240,7 @@ GnssAdapter::checkAndSetSPEToRunforNHz(TrackingOptions & out) { void GnssAdapter::convertLocation(Location& out, const UlpLocation& ulpLocation, - const GpsLocationExtended& locationExtended, - const LocPosTechMask techMask) + const GpsLocationExtended& locationExtended) { memset(&out, 0, sizeof(Location)); out.size = sizeof(Location); @@ -269,33 +282,42 @@ GnssAdapter::convertLocation(Location& out, const UlpLocation& ulpLocation, out.conformityIndex = locationExtended.conformityIndex; } out.timestamp = ulpLocation.gpsLocation.timestamp; - if (LOC_POS_TECH_MASK_SATELLITE & techMask) { + if (LOC_POS_TECH_MASK_SATELLITE & locationExtended.tech_mask) { out.techMask |= LOCATION_TECHNOLOGY_GNSS_BIT; } - if (LOC_POS_TECH_MASK_CELLID & techMask) { + if (LOC_POS_TECH_MASK_CELLID & locationExtended.tech_mask) { out.techMask |= LOCATION_TECHNOLOGY_CELL_BIT; } - if (LOC_POS_TECH_MASK_WIFI & techMask) { + if (LOC_POS_TECH_MASK_WIFI & locationExtended.tech_mask) { out.techMask |= LOCATION_TECHNOLOGY_WIFI_BIT; } - if (LOC_POS_TECH_MASK_SENSORS & techMask) { + if (LOC_POS_TECH_MASK_SENSORS & locationExtended.tech_mask) { out.techMask |= LOCATION_TECHNOLOGY_SENSORS_BIT; } - if (LOC_POS_TECH_MASK_REFERENCE_LOCATION & techMask) { + if (LOC_POS_TECH_MASK_REFERENCE_LOCATION & locationExtended.tech_mask) { out.techMask |= LOCATION_TECHNOLOGY_REFERENCE_LOCATION_BIT; } - if (LOC_POS_TECH_MASK_INJECTED_COARSE_POSITION & techMask) { + if (LOC_POS_TECH_MASK_INJECTED_COARSE_POSITION & locationExtended.tech_mask) { out.techMask |= LOCATION_TECHNOLOGY_INJECTED_COARSE_POSITION_BIT; } - if (LOC_POS_TECH_MASK_AFLT & techMask) { + if (LOC_POS_TECH_MASK_AFLT & locationExtended.tech_mask) { out.techMask |= LOCATION_TECHNOLOGY_AFLT_BIT; } - if (LOC_POS_TECH_MASK_HYBRID & techMask) { + if (LOC_POS_TECH_MASK_HYBRID & locationExtended.tech_mask) { out.techMask |= LOCATION_TECHNOLOGY_HYBRID_BIT; } - if (LOC_POS_TECH_MASK_PPE & techMask) { + if (LOC_POS_TECH_MASK_PPE & locationExtended.tech_mask) { out.techMask |= LOCATION_TECHNOLOGY_PPE_BIT; } + if (LOC_POS_TECH_MASK_VEH & locationExtended.tech_mask) { + out.techMask |= LOCATION_TECHNOLOGY_VEH_BIT; + } + if (LOC_POS_TECH_MASK_VIS & locationExtended.tech_mask) { + out.techMask |= LOCATION_TECHNOLOGY_VIS_BIT; + } + if (LOC_NAV_MASK_DGNSS_CORRECTION & locationExtended.navSolutionMask) { + out.techMask |= LOCATION_TECHNOLOGY_DGNSS_BIT; + } if (LOC_GPS_LOCATION_HAS_SPOOF_MASK & ulpLocation.gpsLocation.flags) { out.flags |= LOCATION_HAS_SPOOF_MASK; @@ -335,7 +357,8 @@ uint16_t GnssAdapter::getNumSvUsed(uint64_t svUsedIdsMask, void GnssAdapter::convertLocationInfo(GnssLocationInfoNotification& out, - const GpsLocationExtended& locationExtended) + const GpsLocationExtended& locationExtended, + enum loc_sess_status status) { out.size = sizeof(GnssLocationInfoNotification); if (GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL & locationExtended.flags) { @@ -583,35 +606,6 @@ GnssAdapter::convertLocationInfo(GnssLocationInfoNotification& out, out.bodyFrameDataExt.yaw = locationExtended.bodyFrameDataExt.yaw; out.bodyFrameDataExt.yawUnc = locationExtended.bodyFrameDataExt.yawUnc; } - if (GPS_LOCATION_EXTENDED_HAS_GPS_TIME & locationExtended.flags) { - out.flags |= GPS_LOCATION_EXTENDED_HAS_GPS_TIME; - out.gnssSystemTime.gnssSystemTimeSrc = locationExtended.gnssSystemTime.gnssSystemTimeSrc; - out.gnssSystemTime.u = locationExtended.gnssSystemTime.u; - } - if (GPS_LOCATION_EXTENDED_HAS_NORTH_VEL & locationExtended.flags) { - out.flags |= GPS_LOCATION_EXTENDED_HAS_NORTH_VEL; - out.northVelocity = locationExtended.northVelocity; - } - if (GPS_LOCATION_EXTENDED_HAS_EAST_VEL & locationExtended.flags) { - out.flags |= GPS_LOCATION_EXTENDED_HAS_EAST_VEL; - out.eastVelocity = locationExtended.eastVelocity; - } - if (GPS_LOCATION_EXTENDED_HAS_UP_VEL & locationExtended.flags) { - out.flags |= GPS_LOCATION_EXTENDED_HAS_UP_VEL; - out.upVelocity = locationExtended.upVelocity; - } - if (GPS_LOCATION_EXTENDED_HAS_NORTH_VEL_UNC & locationExtended.flags) { - out.flags |= GPS_LOCATION_EXTENDED_HAS_NORTH_VEL_UNC; - out.northVelocityStdDeviation = locationExtended.northVelocityStdDeviation; - } - if (GPS_LOCATION_EXTENDED_HAS_EAST_VEL_UNC & locationExtended.flags) { - out.flags |= GPS_LOCATION_EXTENDED_HAS_EAST_VEL_UNC; - out.eastVelocityStdDeviation = locationExtended.eastVelocityStdDeviation; - } - if (GPS_LOCATION_EXTENDED_HAS_UP_VEL_UNC & locationExtended.flags) { - out.flags |= GPS_LOCATION_EXTENDED_HAS_UP_VEL_UNC; - out.upVelocityStdDeviation = locationExtended.upVelocityStdDeviation; - } // Validity of this structure is established from the timeSrc of the GnssSystemTime structure. out.gnssSystemTime = locationExtended.gnssSystemTime; @@ -668,10 +662,16 @@ GnssAdapter::convertLocationInfo(GnssLocationInfoNotification& out, out.flags |= GNSS_LOCATION_INFO_DR_SOLUTION_STATUS_MASK_BIT; out.drSolutionStatusMask = locationExtended.drSolutionStatusMask; } + + if (GPS_LOCATION_EXTENDED_HAS_ALTITUDE_ASSUMED & locationExtended.flags) { + out.flags |= GNSS_LOCATION_INFO_ALTITUDE_ASSUMED_BIT; + out.altitudeAssumed = locationExtended.altitudeAssumed; + } + + out.flags |= GNSS_LOCATION_INFO_SESSION_STATUS_BIT; + out.sessionStatus = status; } - - inline uint32_t GnssAdapter::convertSuplVersion(const GnssConfigSuplVersion suplVersion) { @@ -861,6 +861,9 @@ GnssAdapter::setConfig() uint32_t mask = 0; if (NMEA_PROVIDER_MP == ContextBase::mGps_conf.NMEA_PROVIDER) { mask |= LOC_NMEA_ALL_GENERAL_SUPPORTED_MASK; + if (ContextBase::mGps_conf.NMEA_TAG_BLOCK_GROUPING_ENABLED) { + mask |= LOC_NMEA_MASK_TAGBLOCK_V02; + } } if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02)) { mask |= LOC_NMEA_MASK_DEBUG_V02; @@ -886,6 +889,8 @@ GnssAdapter::setConfig() ContextBase::mGps_conf.MO_SUPL_PORT, LOC_AGPS_MO_SUPL_SERVER); + std::string moServerUrl = getMoServerUrl(); + std::string serverUrl = getServerUrl(); // inject the configurations into modem loc_gps_cfg_s gpsConf = ContextBase::mGps_conf; loc_sap_cfg_s_type sapConf = ContextBase::mSap_conf; @@ -933,13 +938,18 @@ GnssAdapter::setConfig() gnssConfigRequested.blacklistedSvIds.assign(mBlacklistedSvIds.begin(), mBlacklistedSvIds.end()); mLocApi->sendMsg(new LocApiMsg( - [this, gpsConf, sapConf, oldMoServerUrl, gnssConfigRequested] () mutable { - gnssUpdateConfig(oldMoServerUrl, gnssConfigRequested, gnssConfigRequested); + [this, gpsConf, sapConf, oldMoServerUrl, moServerUrl, + serverUrl, gnssConfigRequested] () mutable { + gnssUpdateConfig(oldMoServerUrl, moServerUrl, serverUrl, + gnssConfigRequested, gnssConfigRequested); // set nmea mask type uint32_t mask = 0; if (NMEA_PROVIDER_MP == gpsConf.NMEA_PROVIDER) { mask |= LOC_NMEA_ALL_GENERAL_SUPPORTED_MASK; + if (gpsConf.NMEA_TAG_BLOCK_GROUPING_ENABLED) { + mask |= LOC_NMEA_MASK_TAGBLOCK_V02; + } } if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02)) { mask |= LOC_NMEA_MASK_DEBUG_V02; @@ -1019,6 +1029,7 @@ GnssAdapter::setConfig() } std::vector GnssAdapter::gnssUpdateConfig(const std::string& oldMoServerUrl, + const std::string& moServerUrl, const std::string& serverUrl, GnssConfig& gnssConfigRequested, GnssConfig& gnssConfigNeedEngineUpdate, size_t count) { loc_gps_cfg_s gpsConf = ContextBase::mGps_conf; size_t index = 0; @@ -1028,9 +1039,6 @@ std::vector GnssAdapter::gnssUpdateConfig(const std::string& oldM errsList.insert(errsList.begin(), count, LOCATION_ERROR_SUCCESS); } - std::string serverUrl = getServerUrl(); - std::string moServerUrl = getMoServerUrl(); - int serverUrlLen = serverUrl.length(); int moServerUrlLen = moServerUrl.length(); @@ -1266,19 +1274,26 @@ GnssAdapter::gnssUpdateConfigCommand(const GnssConfig& config) mApi(api), mConfig(config), mCount(count), - mIds(ids) {} + mIds(nullptr) { + if (mCount > 0) { + mIds = new uint32_t[count]; + if (mIds) { + for (uint32_t index = 0; index < count; index++) { + mIds[index] = ids[index]; + } + } else { + LOC_LOGe("memory allocation for mIds failed"); + } + } + } + inline MsgGnssUpdateConfig(const MsgGnssUpdateConfig& obj) : MsgGnssUpdateConfig(obj.mAdapter, obj.mApi, obj.mConfig, - new uint32_t[obj.mCount], obj.mCount) { - if (mIds != nullptr) { - for (int i = 0; i < mCount; ++i) { - mIds[i] = obj.mIds[i]; - } - } - } + obj.mIds, obj.mCount) {} + inline virtual ~MsgGnssUpdateConfig() { - delete[] mIds; + if (nullptr != mIds) delete[] mIds; } inline virtual void proc() const { @@ -1411,10 +1426,14 @@ GnssAdapter::gnssUpdateConfigCommand(const GnssConfig& config) adapter.reportResponse(countOfConfigs, errs.data(), ids.data()); }); + std::string moServerUrl = adapter.getMoServerUrl(); + std::string serverUrl = adapter.getServerUrl(); mApi.sendMsg(new LocApiMsg( [&adapter, gnssConfigRequested, gnssConfigNeedEngineUpdate, - countOfConfigs, configCollectiveResponse, errs] () mutable { + moServerUrl, serverUrl, countOfConfigs, configCollectiveResponse, + errs] () mutable { std::vector errsList = adapter.gnssUpdateConfig("", + moServerUrl, serverUrl, gnssConfigRequested, gnssConfigNeedEngineUpdate, countOfConfigs); configCollectiveResponse->returnToSender(errsList); @@ -1549,21 +1568,27 @@ GnssAdapter::gnssGetConfigCommand(GnssConfigFlagsMask configMask) { mAdapter(adapter), mApi(api), mConfigMask(configMask), - mIds(ids), - mCount(count) {} + mCount(count), + mIds(nullptr) { + if (mCount > 0) { + mIds = new uint32_t[count]; + if (mIds) { + for (uint32_t index = 0; index < count; index++) { + mIds[index] = ids[index]; + } + } else { + LOC_LOGe("memory allocation for mIds failed"); + } + } + } inline MsgGnssGetConfig(const MsgGnssGetConfig& obj) : MsgGnssGetConfig(obj.mAdapter, obj.mApi, obj.mConfigMask, - new uint32_t[obj.mCount], obj.mCount) { - if (mIds != nullptr) { - for (int i = 0; i < mCount; ++i) { - mIds[i] = obj.mIds[i]; - } - } - } + obj.mIds, obj.mCount) {} + inline virtual ~MsgGnssGetConfig() { - delete[] mIds; + if (nullptr != mIds) delete[] mIds; } inline virtual void proc() const { if (!mAdapter.isEngineCapabilitiesKnown()) { @@ -2193,7 +2218,17 @@ GnssAdapter::gnssDeleteAidingDataCommand(GnssAidingData& data) } } - mAdapter.mEngHubProxy->gnssDeleteAidingData(mData); + bool retVal = mAdapter.mEngHubProxy->gnssDeleteAidingData(mData); + // When SPE engine is invoked, responseCb will be invoked + // from QMI Loc API call. + // When SPE engine is not invoked, we also need to deliver responseCb + if ((mData.posEngineMask & STANDARD_POSITIONING_ENGINE) == 0) { + LocationError err = LOCATION_ERROR_NOT_SUPPORTED; + if (retVal == true) { + err = LOCATION_ERROR_SUCCESS; + } + mAdapter.reportResponse(err, mSessionId); + } } }; @@ -2455,7 +2490,10 @@ GnssAdapter::stopClientSessions(LocationAPI* client) void GnssAdapter::updateClientsEventMask() { - LOC_API_ADAPTER_EVENT_MASK_T mask = 0; + // need to register for leap second info + // for proper nmea generation + LOC_API_ADAPTER_EVENT_MASK_T mask = LOC_API_ADAPTER_BIT_LOC_SYSTEM_INFO | + LOC_API_ADAPTER_BIT_EVENT_REPORT_INFO; for (auto it=mClientData.begin(); it != mClientData.end(); ++it) { if (it->second.trackingCb != nullptr || it->second.gnssLocationInfoCb != nullptr || @@ -2490,8 +2528,6 @@ GnssAdapter::updateClientsEventMask() 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; // Nhz measurement bit is set based on callback from loc eng hub // for Nhz engines. @@ -2516,6 +2552,13 @@ GnssAdapter::updateClientsEventMask() // always register for NI NOTIFY VERIFY to handle internally in HAL mask |= LOC_API_ADAPTER_BIT_NI_NOTIFY_VERIFY_REQUEST; + // Enable the latency report + if (mask & LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT) { + if (mLogger.isLogEnabled()) { + mask |= LOC_API_ADAPTER_BIT_LATENCY_INFORMATION; + } + } + updateEvtMask(mask, LOC_REGISTRATION_MASK_SET); } @@ -2570,6 +2613,7 @@ GnssAdapter::restartSessions(bool modemSSR) // inform engine hub that GNSS session is about to start mEngHubProxy->gnssSetFixMode(mLocPositionMode); mEngHubProxy->gnssStartFix(); + checkUpdateDgnssNtrip(false); } checkAndRestartSPESession(); @@ -2602,6 +2646,10 @@ GnssAdapter::suspendSessions() // inform engine hub that GNSS session has stopped mEngHubProxy->gnssStopFix(); mLocApi->stopFix(nullptr); + if (isDgnssNmeaRequired()) { + mDgnssState &= ~DGNSS_STATE_NO_NMEA_PENDING; + } + stopDgnssNtrip(); mSPEAlreadyRunningAtHighestInterval = false; } } @@ -2640,6 +2688,48 @@ void GnssAdapter::checkAndRestartTimeBasedSession() } } +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; + } + //Get QWES feature status mask + mask |= ContextBase::getQwesFeatureStatus(); + return mask; +} + void GnssAdapter::notifyClientOfCachedLocationSystemInfo( LocationAPI* client, const LocationCallbacks& callbacks) { @@ -2756,7 +2846,6 @@ GnssAdapter::saveTrackingSession(LocationAPI* client, uint32_t sessionId, mTimeBasedTrackingSessions[key] = options; } reportPowerStateIfChanged(); - checkUpdateDgnssNtrip(false); } void @@ -2773,16 +2862,8 @@ GnssAdapter::eraseTrackingSession(LocationAPI* client, uint32_t sessionId) } } reportPowerStateIfChanged(); - - if (mSendNmeaConsent && mStartDgnssNtripParams.ntripParams.requiresNmeaLocation) { - LOC_LOGd("requiresNmeaLocation"); - mDgnssState &= ~DGNSS_STATE_NO_NMEA_PENDING; - mStartDgnssNtripParams.nmea.clear(); - } - stopDgnssNtrip(); } - bool GnssAdapter::setLocPositionMode(const LocPosMode& mode) { if (!mLocPositionMode.equals(mode)) { mLocPositionMode = mode; @@ -3000,6 +3081,8 @@ GnssAdapter::startTimeBasedTracking(LocationAPI* client, uint32_t sessionId, [this, client, sessionId] (LocationError err) { if (LOCATION_ERROR_SUCCESS != err) { eraseTrackingSession(client, sessionId); + } else { + checkUpdateDgnssNtrip(false); } reportResponse(client, err, sessionId); @@ -3341,6 +3424,11 @@ GnssAdapter::stopTracking(LocationAPI* client, uint32_t id) reportResponse(client, err, id); })); + if (isDgnssNmeaRequired()) { + mDgnssState &= ~DGNSS_STATE_NO_NMEA_PENDING; + } + stopDgnssNtrip(); + mSPEAlreadyRunningAtHighestInterval = false; } @@ -3553,6 +3641,63 @@ GnssAdapter::disableCommand(uint32_t id) } +// This function computes the VRP based latitude, longitude and alittude, and +// north, east and up velocity and save the result into EHubTechReport. +void +GnssAdapter::computeVRPBasedLla(const UlpLocation& loc, GpsLocationExtended& locExt, + const LeverArmConfigInfo& leverArmConfigInfo) { + + float leverArm[3]; + float rollPitchYaw[3]; + double lla[3]; + + uint16_t locFlags = loc.gpsLocation.flags; + uint64_t locExtFlags = locExt.flags; + + // check for SPE fix + if (!((locExtFlags & GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_TYPE) && + (locExt.locOutputEngType == LOC_OUTPUT_ENGINE_SPE))){ + LOC_LOGv("not SPE fix, return"); + return; + } + + // we can only do translation if we have VRP based lever ARM info + LeverArmTypeMask leverArmFlags = leverArmConfigInfo.leverArmValidMask; + if (!(leverArmFlags & LEVER_ARM_TYPE_GNSS_TO_VRP_BIT)) { + LOC_LOGd("no VRP based lever ARM info"); + return; + } + + leverArm[0] = leverArmConfigInfo.gnssToVRP.forwardOffsetMeters; + leverArm[1] = leverArmConfigInfo.gnssToVRP.sidewaysOffsetMeters; + leverArm[2] = leverArmConfigInfo.gnssToVRP.upOffsetMeters; + + if ((locFlags & LOC_GPS_LOCATION_HAS_LAT_LONG) && + (locFlags & LOC_GPS_LOCATION_HAS_ALTITUDE) && + (locFlags & LOCATION_HAS_BEARING_BIT)) { + + lla[0] = loc.gpsLocation.latitude * DEG2RAD; + lla[1] = loc.gpsLocation.longitude * DEG2RAD; + lla[2] = loc.gpsLocation.altitude; + + rollPitchYaw[0] = 0.0f; + rollPitchYaw[1] = 0.0f; + rollPitchYaw[2] = loc.gpsLocation.bearing * DEG2RAD; + + loc_convert_lla_gnss_to_vrp(lla, rollPitchYaw, leverArm); + + // assign the converted value into position report and + // set up valid mask + locExt.llaVRPBased.latitude = lla[0] * RAD2DEG; + locExt.llaVRPBased.longitude = lla[1] * RAD2DEG; + locExt.llaVRPBased.altitude = lla[2]; + locExt.flags |= GPS_LOCATION_EXTENDED_HAS_LLA_VRP_BASED; + } else { + LOC_LOGd("SPE fix missing latitude/longitude/alitutde"); + return; + } +} + void GnssAdapter::reportPositionEvent(const UlpLocation& ulpLocation, const GpsLocationExtended& locationExtended, @@ -3568,63 +3713,90 @@ GnssAdapter::reportPositionEvent(const UlpLocation& ulpLocation, locationExtended.locOutputEngType, ulpLocation.unpropagatedPosition, status, msInWeek); - if (false == ulpLocation.unpropagatedPosition && pDataNotify != nullptr) { - reportDataEvent((GnssDataNotification&)(*pDataNotify), msInWeek); - } - - if (true == initEngHubProxy()){ - // send the SPE fix to engine hub - mEngHubProxy->gnssReportPosition(ulpLocation, locationExtended, status); - // report out all SPE fix if it is not propagated, even for failed fix - if (false == ulpLocation.unpropagatedPosition) { - EngineLocationInfo engLocationInfo = {}; - engLocationInfo.location = ulpLocation; - engLocationInfo.locationExtended = locationExtended; - engLocationInfo.sessionStatus = status; - reportEnginePositionsEvent(1, &engLocationInfo); - } - return; - } - - // unpropagated report: is only for engine hub to consume and no need - // to send out to the clients - if (true == ulpLocation.unpropagatedPosition) { - return; - } - - // Fix is from QMI, and it is not an unpropagated position and engine hub - // is not loaded, queue the message when message is processed, the position - // can be dispatched to requesting client that registers for SPE report - struct MsgReportPosition : public LocMsg { + struct MsgReportSPEPosition : public LocMsg { GnssAdapter& mAdapter; - const UlpLocation mUlpLocation; - const GpsLocationExtended mLocationExtended; - loc_sess_status mStatus; + mutable UlpLocation mUlpLocation; + mutable GpsLocationExtended mLocationExtended; + enum loc_sess_status mStatus; LocPosTechMask mTechMask; - inline MsgReportPosition(GnssAdapter& adapter, - const UlpLocation& ulpLocation, - const GpsLocationExtended& locationExtended, - loc_sess_status status, - LocPosTechMask techMask) : + mutable GnssDataNotification mDataNotify; + int mMsInWeek; + + inline MsgReportSPEPosition(GnssAdapter& adapter, + const UlpLocation& ulpLocation, + const GpsLocationExtended& locationExtended, + enum loc_sess_status status, + LocPosTechMask techMask, + GnssDataNotification dataNotify, + int msInWeek) : LocMsg(), mAdapter(adapter), mUlpLocation(ulpLocation), mLocationExtended(locationExtended), mStatus(status), - mTechMask(techMask) {} + mTechMask(techMask), + mDataNotify(dataNotify), + mMsInWeek(msInWeek) {} inline virtual void proc() const { + if (mAdapter.mTimeBasedTrackingSessions.empty() && + mAdapter.mDistanceBasedTrackingSessions.empty()) { + LOC_LOGd("reportPositionEvent, no session on-going, throw away the SPE reports"); + return; + } + + if (false == mUlpLocation.unpropagatedPosition && mDataNotify.size != 0) { + if (mMsInWeek >= 0) { + mAdapter.getDataInformation((GnssDataNotification&)mDataNotify, + mMsInWeek); + } + mAdapter.reportData(mDataNotify); + } + + if (true == mAdapter.initEngHubProxy()){ + // send the SPE fix to engine hub + mAdapter.mEngHubProxy->gnssReportPosition(mUlpLocation, mLocationExtended, mStatus); + // report out all SPE fix if it is not propagated, even for failed fix + if (false == mUlpLocation.unpropagatedPosition) { + EngineLocationInfo engLocationInfo = {}; + engLocationInfo.location = mUlpLocation; + engLocationInfo.locationExtended = mLocationExtended; + engLocationInfo.sessionStatus = mStatus; + + // obtain the VRP based latitude/longitude/altitude for SPE fix + computeVRPBasedLla(engLocationInfo.location, + engLocationInfo.locationExtended, + mAdapter.mLocConfigInfo.leverArmConfigInfo); + mAdapter.reportEnginePositions(1, &engLocationInfo); + } + return; + } + + // unpropagated report: is only for engine hub to consume and no need + // to send out to the clients + if (true == mUlpLocation.unpropagatedPosition) { + return; + } + // extract bug report info - this returns true if consumed by systemstatus SystemStatus* s = mAdapter.getSystemStatus(); if ((nullptr != s) && ((LOC_SESS_SUCCESS == mStatus) || (LOC_SESS_INTERMEDIATE == mStatus))){ s->eventPosition(mUlpLocation, mLocationExtended); } + mAdapter.reportPosition(mUlpLocation, mLocationExtended, mStatus, mTechMask); } }; - sendMsg(new MsgReportPosition(*this, ulpLocation, locationExtended, - status, techMask)); + if (mContext != NULL) { + GnssDataNotification dataNotifyCopy = {}; + if (pDataNotify) { + dataNotifyCopy = *pDataNotify; + dataNotifyCopy.size = sizeof(dataNotifyCopy); + } + sendMsg(new MsgReportSPEPosition(*this, ulpLocation, locationExtended, + status, techMask, dataNotifyCopy, msInWeek)); + } } void @@ -3675,9 +3847,9 @@ GnssAdapter::needReportForGnssClient(const UlpLocation& ulpLocation, bool GnssAdapter::needReportForFlpClient(enum loc_sess_status status, LocPosTechMask techMask) { - if ((status == LOC_SESS_INTERMEDIATE) && - !(techMask & LOC_POS_TECH_MASK_SENSORS) && - (!getAllowFlpNetworkFixes())) { + if (((LOC_SESS_INTERMEDIATE == status) && !(techMask & LOC_POS_TECH_MASK_SENSORS) && + (!getAllowFlpNetworkFixes())) || + (LOC_SESS_FAILURE == status)) { return false; } else { return true; @@ -3727,6 +3899,62 @@ bool GnssAdapter::needToGenerateNmeaReport(const uint32_t &gpsTimeOfWeekMs, return retVal; } +void +GnssAdapter::logLatencyInfo() +{ + if (0 == mGnssLatencyInfoQueue.size()) { + LOC_LOGv("mGnssLatencyInfoQueue.size is 0"); + return; + } + mGnssLatencyInfoQueue.front().hlosQtimer5 = getQTimerTickCount(); + if (0 == mGnssLatencyInfoQueue.front().hlosQtimer3) { + /* if SPE from engine hub is not reported then hlosQtimer3 = 0, set it + equal to hlosQtimer2 to make sense */ + LOC_LOGv("hlosQtimer3 is 0, setting it to hlosQtimer2"); + mGnssLatencyInfoQueue.front().hlosQtimer3 = mGnssLatencyInfoQueue.front().hlosQtimer2; + } + if (0 == mGnssLatencyInfoQueue.front().hlosQtimer4) { + /* if PPE from engine hub is not reported then hlosQtimer4 = 0, set it + equal to hlosQtimer3 to make sense */ + LOC_LOGv("hlosQtimer4 is 0, setting it to hlosQtimer3"); + mGnssLatencyInfoQueue.front().hlosQtimer4 = mGnssLatencyInfoQueue.front().hlosQtimer3; + } + if (mGnssLatencyInfoQueue.front().hlosQtimer4 < mGnssLatencyInfoQueue.front().hlosQtimer3) { + /* hlosQtimer3 is timestamped when SPE from engine hub is reported, + and hlosQtimer4 is timestamped when PPE from engine hub is reported. + The order is random though, hence making sure the timestamps are sorted */ + LOC_LOGv("hlosQtimer4 is < hlosQtimer3, swapping them"); + std::swap(mGnssLatencyInfoQueue.front().hlosQtimer3, + mGnssLatencyInfoQueue.front().hlosQtimer4); + } + LOC_LOGv("meQtimer1=%" PRIi64 " " + "meQtimer2=%" PRIi64 " " + "meQtimer3=%" PRIi64 " " + "peQtimer1=%" PRIi64 " " + "peQtimer2=%" PRIi64 " " + "peQtimer3=%" PRIi64 " " + "smQtimer1=%" PRIi64 " " + "smQtimer2=%" PRIi64 " " + "smQtimer3=%" PRIi64 " " + "locMwQtimer=%" PRIi64 " " + "hlosQtimer1=%" PRIi64 " " + "hlosQtimer2=%" PRIi64 " " + "hlosQtimer3=%" PRIi64 " " + "hlosQtimer4=%" PRIi64 " " + "hlosQtimer5=%" PRIi64 " ", + mGnssLatencyInfoQueue.front().meQtimer1, mGnssLatencyInfoQueue.front().meQtimer2, + mGnssLatencyInfoQueue.front().meQtimer3, mGnssLatencyInfoQueue.front().peQtimer1, + mGnssLatencyInfoQueue.front().peQtimer2, mGnssLatencyInfoQueue.front().peQtimer3, + mGnssLatencyInfoQueue.front().smQtimer1, mGnssLatencyInfoQueue.front().smQtimer2, + mGnssLatencyInfoQueue.front().smQtimer3, mGnssLatencyInfoQueue.front().locMwQtimer, + mGnssLatencyInfoQueue.front().hlosQtimer1, mGnssLatencyInfoQueue.front().hlosQtimer2, + mGnssLatencyInfoQueue.front().hlosQtimer3, mGnssLatencyInfoQueue.front().hlosQtimer4, + mGnssLatencyInfoQueue.front().hlosQtimer5); + mLogger.log(mGnssLatencyInfoQueue.front()); + mGnssLatencyInfoQueue.pop(); + LOC_LOGv("mGnssLatencyInfoQueue.size after pop=%zu", mGnssLatencyInfoQueue.size()); +} + // only fused report (when engine hub is enabled) or // SPE report (when engine hub is disabled) will reach this function void @@ -3740,16 +3968,16 @@ GnssAdapter::reportPosition(const UlpLocation& ulpLocation, if (reportToGnssClient || reportToFlpClient) { GnssLocationInfoNotification locationInfo = {}; - convertLocationInfo(locationInfo, locationExtended); - convertLocation(locationInfo.location, ulpLocation, locationExtended, techMask); - + convertLocationInfo(locationInfo, locationExtended, status); + convertLocation(locationInfo.location, ulpLocation, locationExtended); + logLatencyInfo(); for (auto it=mClientData.begin(); it != mClientData.end(); ++it) { if ((reportToFlpClient && isFlpClient(it->second)) || (reportToGnssClient && !isFlpClient(it->second))) { if (nullptr != it->second.gnssLocationInfoCb) { it->second.gnssLocationInfoCb(locationInfo); } else if ((nullptr != it->second.engineLocationsInfoCb) && - (false == initEngHubProxy())) { + (false == initEngHubProxy())) { // if engine hub is disabled, this is SPE fix from modem // we need to mark one copy marked as fused and one copy marked as PPE // and dispatch it to the engineLocationsInfoCb @@ -3802,10 +4030,12 @@ GnssAdapter::reportPosition(const UlpLocation& ulpLocation, (LOC_RELIABILITY_NOT_SET == locationExtended.horizontal_reliability)); uint8_t generate_nmea = (reportToGnssClient && status != LOC_SESS_FAILURE && !blank_fix); bool custom_nmea_gga = (1 == ContextBase::mGps_conf.CUSTOM_NMEA_GGA_FIX_QUALITY_ENABLED); + bool isTagBlockGroupingEnabled = + (1 == ContextBase::mGps_conf.NMEA_TAG_BLOCK_GROUPING_ENABLED); std::vector nmeaArraystr; int indexOfGGA = -1; - loc_nmea_generate_pos(ulpLocation, locationExtended, mLocSystemInfo, - generate_nmea, custom_nmea_gga, nmeaArraystr, indexOfGGA); + loc_nmea_generate_pos(ulpLocation, locationExtended, mLocSystemInfo, generate_nmea, + custom_nmea_gga, nmeaArraystr, indexOfGGA, isTagBlockGroupingEnabled); stringstream ss; for (auto itor = nmeaArraystr.begin(); itor != nmeaArraystr.end(); ++itor) { ss << *itor; @@ -3824,6 +4054,25 @@ GnssAdapter::reportPosition(const UlpLocation& ulpLocation, } } +void +GnssAdapter::reportLatencyInfoEvent(const GnssLatencyInfo& gnssLatencyInfo) +{ + struct MsgReportLatencyInfo : public LocMsg { + GnssAdapter& mAdapter; + GnssLatencyInfo mGnssLatencyInfo; + inline MsgReportLatencyInfo(GnssAdapter& adapter, + const GnssLatencyInfo& gnssLatencyInfo) : + mGnssLatencyInfo(gnssLatencyInfo), + mAdapter(adapter) {} + inline virtual void proc() const { + mAdapter.mGnssLatencyInfoQueue.push(mGnssLatencyInfo); + LOC_LOGv("mGnssLatencyInfoQueue.size after push=%zu", + mAdapter.mGnssLatencyInfoQueue.size()); + } + }; + sendMsg(new MsgReportLatencyInfo(*this, gnssLatencyInfo)); +} + void GnssAdapter::reportEnginePositions(unsigned int count, const EngineLocationInfo* locationArr) @@ -3849,14 +4098,30 @@ GnssAdapter::reportEnginePositions(unsigned int count, } if (needReportEnginePositions) { - convertLocationInfo(locationInfo[i], engLocation->locationExtended); + convertLocationInfo(locationInfo[i], engLocation->locationExtended, + engLocation->sessionStatus); convertLocation(locationInfo[i].location, engLocation->location, - engLocation->locationExtended, - engLocation->location.tech_mask); + engLocation->locationExtended); } } + const EngineLocationInfo* engLocation = locationArr; + LOC_LOGv("engLocation->locationExtended.locOutputEngType=%d", + engLocation->locationExtended.locOutputEngType); + + if (0 != mGnssLatencyInfoQueue.size()) { + if ((GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_TYPE & engLocation->locationExtended.flags) && + (LOC_OUTPUT_ENGINE_SPE == engLocation->locationExtended.locOutputEngType)) { + mGnssLatencyInfoQueue.front().hlosQtimer3 = getQTimerTickCount(); + LOC_LOGv("SPE hlosQtimer3=%" PRIi64 " ", mGnssLatencyInfoQueue.front().hlosQtimer3); + } + if ((GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_TYPE & engLocation->locationExtended.flags) && + (LOC_OUTPUT_ENGINE_PPE == engLocation->locationExtended.locOutputEngType)) { + mGnssLatencyInfoQueue.front().hlosQtimer4 = getQTimerTickCount(); + LOC_LOGv("PPE hlosQtimer4=%" PRIi64 " ", mGnssLatencyInfoQueue.front().hlosQtimer4); + } + } if (needReportEnginePositions) { for (auto it=mClientData.begin(); it != mClientData.end(); ++it) { if (nullptr != it->second.engineLocationsInfoCb) { @@ -4051,6 +4316,7 @@ GnssAdapter::reportSv(GnssSvNotification& svNotify) } mGnssSvIdUsedInPosAvail = false; + mGnssMbSvIdUsedInPosAvail = false; } void @@ -4134,8 +4400,8 @@ GnssAdapter::reportDataEvent(const GnssDataNotification& dataNotify, GnssDataNotification mDataNotify; int mMsInWeek; inline MsgReportData(GnssAdapter& adapter, - const GnssDataNotification& dataNotify, - int msInWeek) : + const GnssDataNotification& dataNotify, + int msInWeek) : LocMsg(), mAdapter(adapter), mDataNotify(dataNotify), @@ -4622,8 +4888,33 @@ bool GnssAdapter::reportGnssAdditionalSystemInfoEvent( return true; } +bool GnssAdapter::reportQwesCapabilities( + const std::unordered_map &featureMap) +{ + struct MsgReportQwesFeatureStatus : public LocMsg { + GnssAdapter& mAdapter; + const std::unordered_map mFeatureMap; + inline MsgReportQwesFeatureStatus(GnssAdapter& adapter, + const std::unordered_map &featureMap) : + LocMsg(), + mAdapter(adapter), + mFeatureMap(std::move(featureMap)) {} + inline virtual void proc() const { + LOC_LOGi("ReportQwesFeatureStatus before caps %" PRIx64 " ", + mAdapter.getCapabilities()); + ContextBase::setQwesFeatureStatus(mFeatureMap); + LOC_LOGi("ReportQwesFeatureStatus After caps %" PRIx64 " ", + mAdapter.getCapabilities()); + mAdapter.broadcastCapabilities(mAdapter.getCapabilities()); + } + }; + + sendMsg(new MsgReportQwesFeatureStatus(*this, featureMap)); + return true; +} + void GnssAdapter::initOdcpiCommand(const OdcpiRequestCallback& callback, - OdcpiPrioritytype priority) + OdcpiPrioritytype priority) { struct MsgInitOdcpi : public LocMsg { GnssAdapter& mAdapter; @@ -4751,23 +5042,20 @@ GnssAdapter::reportGnssEngEnergyConsumedEvent(uint64_t energyConsumedSinceFirstB void GnssAdapter::initDefaultAgps() { LOC_LOGD("%s]: ", __func__); - void *handle = nullptr; - if ((handle = dlopen("libloc_net_iface.so", RTLD_NOW)) == nullptr) { - LOC_LOGD("%s]: libloc_net_iface.so not found !", __func__); - return; - } - LocAgpsGetAgpsCbInfo getAgpsCbInfo = (LocAgpsGetAgpsCbInfo) - dlsym(handle, "LocNetIfaceAgps_getAgpsCbInfo"); - if (getAgpsCbInfo == nullptr) { - LOC_LOGE("%s]: Failed to get method LocNetIfaceAgps_getStatusCb", __func__); - dlclose(handle); - return; + LocAgpsGetAgpsCbInfo getAgpsCbInfo = + (LocAgpsGetAgpsCbInfo)dlGetSymFromLib(handle, "libloc_net_iface.so", + "LocNetIfaceAgps_getAgpsCbInfo"); + // Below step is to make sure we init nativeAgpsHandler + // for Android platforms only + AgpsCbInfo cbInfo = {}; + if (nullptr != getAgpsCbInfo) { + cbInfo = getAgpsCbInfo(agpsOpenResultCb, agpsCloseResultCb, this); + } else { + cbInfo = mNativeAgpsHandler.getAgpsCbInfo(); } - AgpsCbInfo& cbInfo = getAgpsCbInfo(agpsOpenResultCb, agpsCloseResultCb, this); - if (cbInfo.statusV4Cb == nullptr) { LOC_LOGE("%s]: statusV4Cb is nullptr!", __func__); dlclose(handle); @@ -4974,8 +5262,7 @@ void GnssAdapter::dataConnOpenCommand( }; // 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) != (unsigned)apnLen)) { + if (NULL == apnName || apnLen > MAX_APN_LEN || (strlen(apnName) != apnLen)) { LOC_LOGe("%s]: incorrect apnlen length or incorrect apnName", __func__); mAgpsManager.reportAtlClosed(agpsType); } else { @@ -5839,6 +6126,13 @@ GnssAdapter::configLeverArmCommand(const LeverArmConfigInfo& configInfo) { mSessionId(sessionId), mConfigInfo(configInfo) {} inline virtual void proc() const { + // save the lever ARM config info for translating position from GNSS antenna based + // to VRP based + if (mConfigInfo.leverArmValidMask & LEVER_ARM_TYPE_GNSS_TO_VRP_BIT) { + mAdapter.mLocConfigInfo.leverArmConfigInfo.leverArmValidMask |= + LEVER_ARM_TYPE_GNSS_TO_VRP_BIT; + mAdapter.mLocConfigInfo.leverArmConfigInfo.gnssToVRP = mConfigInfo.gnssToVRP; + } mAdapter.configLeverArm(mSessionId, mConfigInfo); } }; @@ -6087,6 +6381,47 @@ uint32_t GnssAdapter::configDeadReckoningEngineParamsCommand( return sessionId; } +uint32_t GnssAdapter::configEngineRunStateCommand( + PositioningEngineMask engType, LocEngineRunState engState) { + + // generated session id will be none-zero + uint32_t sessionId = generateSessionId(); + LOC_LOGe("session id %u, eng type 0x%x, eng state %d, dre enabled %d", + sessionId, engType, engState, mDreIntEnabled); + + struct MsgConfigEngineRunState : public LocMsg { + GnssAdapter& mAdapter; + uint32_t mSessionId; + PositioningEngineMask mEngType; + LocEngineRunState mEngState; + + inline MsgConfigEngineRunState(GnssAdapter& adapter, + uint32_t sessionId, + PositioningEngineMask engType, + LocEngineRunState engState) : + LocMsg(), + mAdapter(adapter), + mSessionId(sessionId), + mEngType(engType), + mEngState(engState) {} + inline virtual void proc() const { + LocationError err = LOCATION_ERROR_NOT_SUPPORTED; + // Currently, only DR engine supports pause/resume request + if ((mEngType == DEAD_RECKONING_ENGINE) && + (mAdapter.mDreIntEnabled == true)) { + if (true == mAdapter.mEngHubProxy->configEngineRunState(mEngType, mEngState)) { + err = LOCATION_ERROR_SUCCESS; + } + } + mAdapter.reportResponse(err, mSessionId); + } + }; + + sendMsg(new MsgConfigEngineRunState(*this, sessionId, engType, engState)); + + return sessionId; +} + void GnssAdapter::reportGnssConfigEvent(uint32_t sessionId, const GnssConfig& gnssConfig) { struct MsgReportGnssConfig : public LocMsg { @@ -6161,13 +6496,23 @@ GnssAdapter::initEngHubProxy() { strlen(PROCESS_NAME_ENGINE_SERVICE)) == 0) && (processInfoList[i].proc_status == ENABLED)) { pluginDaemonEnabled = true; - break; + // check if this is DRE-INT engine + if ((processInfoList[i].args[1]!= nullptr) && + (strncmp(processInfoList[i].args[1], "DRE-INT", sizeof("DRE-INT")) == 0)) { + mDreIntEnabled = true; + break; + } } } - // no plugin daemon is enabled for this platform, no need to load eng hub .so + // no plugin daemon is enabled for this platform, + // check if external engine is present for which we need + // libloc_eng_hub.so to be loaded if (pluginDaemonEnabled == false) { - break; + UTIL_READ_CONF(LOC_PATH_IZAT_CONF, izatConfParamTable); + if (!loadEngHubForExternalEngine) { + break; + } } // load the engine hub .so, if the .so is not present @@ -6216,14 +6561,20 @@ GnssAdapter::initEngHubProxy() { mNHzNeeded = nHzNeeded; checkAndRestartSPESession(); } - }; + }; + + GnssAdapterUpdateQwesFeatureStatusCb updateQwesFeatureStatusCb = + [this] (const std::unordered_map &featureMap) { + reportQwesCapabilities(featureMap); + }; getEngHubProxyFn* getter = (getEngHubProxyFn*) dlsym(handle, "getEngHubProxy"); if(getter != nullptr) { EngineHubProxyBase* hubProxy = (*getter) (mMsgTask, mSystemStatus->getOsObserver(), - reportPositionEventCb, - reportSvEventCb, reqAidingDataCb, - updateNHzRequirementCb); + reportPositionEventCb, + reportSvEventCb, reqAidingDataCb, + updateNHzRequirementCb, + updateQwesFeatureStatusCb); if (hubProxy != nullptr) { mEngHubProxy = hubProxy; engHubLoadSuccessful = true; @@ -6265,6 +6616,9 @@ GnssAdapter::parseDoublesString(char* dString) { void GnssAdapter::reportGnssAntennaInformation(const antennaInfoCb antennaInfoCallback) { +#define MAX_TEXT_WIDTH 50 +#define MAX_COLUMN_WIDTH 20 + /* parse antenna_corrections file and fill in a vector of GnssAntennaInformation data structure */ @@ -6336,9 +6690,11 @@ GnssAdapter::reportGnssAntennaInformation(const antennaInfoCb antennaInfoCallbac gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.z = pcOffset[4]; gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.zUncertainty = pcOffset[5]; + uint16_t array_size = MAX_TEXT_WIDTH + MAX_COLUMN_WIDTH*numberOfColumns; + uint16_t array_size_SGC = MAX_TEXT_WIDTH + MAX_COLUMN_WIDTH*numberOfColumnsSGC; for (uint32_t j = 0; j < numberOfRows; j++) { - char pcVarCorrStr[LOC_MAX_PARAM_STRING]; - char pcVarCorrUncStr[LOC_MAX_PARAM_STRING]; + char pcVarCorrStr[array_size]; + char pcVarCorrUncStr[array_size]; string s1 = "PC_VARIATION_CORRECTION_" + to_string(i) + "_ROW_"; s1 += to_string(j); @@ -6350,7 +6706,7 @@ GnssAdapter::reportGnssAntennaInformation(const antennaInfoCb antennaInfoCallbac { s1.c_str(), &pcVarCorrStr, NULL, 's' }, { s2.c_str(), &pcVarCorrUncStr, NULL, 's' }, }; - UTIL_READ_CONF(LOC_PATH_ANT_CORR, ant_row_table); + UTIL_READ_CONF_LONG(LOC_PATH_ANT_CORR, ant_row_table, array_size); gnssAntennaInfo.phaseCenterVariationCorrectionMillimeters.push_back( parseDoublesString(pcVarCorrStr)); @@ -6358,8 +6714,8 @@ GnssAdapter::reportGnssAntennaInformation(const antennaInfoCb antennaInfoCallbac parseDoublesString(pcVarCorrUncStr)); } for (uint32_t j = 0; j < numberOfRowsSGC; j++) { - char sigGainCorrStr[LOC_MAX_PARAM_STRING]; - char sigGainCorrUncStr[LOC_MAX_PARAM_STRING]; + char sigGainCorrStr[array_size_SGC]; + char sigGainCorrUncStr[array_size_SGC]; string s3 = "SIGNAL_GAIN_CORRECTION_" + to_string(i) + "_ROW_"; s3 += to_string(j); @@ -6371,7 +6727,7 @@ GnssAdapter::reportGnssAntennaInformation(const antennaInfoCb antennaInfoCallbac { s3.c_str(), &sigGainCorrStr, NULL, 's' }, { s4.c_str(), &sigGainCorrUncStr, NULL, 's' }, }; - UTIL_READ_CONF(LOC_PATH_ANT_CORR, ant_row_table); + UTIL_READ_CONF_LONG(LOC_PATH_ANT_CORR, ant_row_table, array_size_SGC); gnssAntennaInfo.signalGainCorrectionDbi.push_back( parseDoublesString(sigGainCorrStr)); @@ -6380,7 +6736,9 @@ GnssAdapter::reportGnssAntennaInformation(const antennaInfoCb antennaInfoCallbac } gnssAntennaInformations.push_back(std::move(gnssAntennaInfo)); } - antennaInfoCallback(gnssAntennaInformations); + if (antennaInfoVectorSize > 0) { + antennaInfoCallback(gnssAntennaInformations); + } } /* ==== DGnss Usable Reporter ========================================================= */ @@ -6406,7 +6764,7 @@ void GnssAdapter::initCDFWService() QDgnssSessionActiveCb qDgnssSessionActiveCb = [this] (bool sessionActive) { mDGnssNeedReport = sessionActive; }; - mCdfwInterface->startDgnssApiService(); + mCdfwInterface->startDgnssApiService(*mMsgTask); mQDgnssListenerHDL = mCdfwInterface->createUsableReporter(qDgnssSessionActiveCb); } } @@ -6417,10 +6775,15 @@ void GnssAdapter::enablePPENtripStreamCommand(const GnssNtripConnectionParams& p bool enableRTKEngine) { (void)enableRTKEngine; //future parameter, not used + if (0 == params.size || params.hostNameOrIp.empty() || params.mountPoint.empty() || + params.username.empty() || params.password.empty()) { + LOC_LOGe("Ntrip parameters are invalid!"); + return; + } struct enableNtripMsg : public LocMsg { GnssAdapter& mAdapter; - const GnssNtripConnectionParams& mParams; + const GnssNtripConnectionParams mParams; inline enableNtripMsg(GnssAdapter& adapter, const GnssNtripConnectionParams& params) : @@ -6435,9 +6798,6 @@ void GnssAdapter::enablePPENtripStreamCommand(const GnssNtripConnectionParams& p } void GnssAdapter::handleEnablePPENtrip(const GnssNtripConnectionParams& params) { - - LOC_LOGd("isInSession %d mDgnssState 0x%x", isInSession(), mDgnssState); - LOC_LOGd("%d %s %d %s %s %s %d mSendNmeaConsent %d", params.useSSL, params.hostNameOrIp.data(), params.port, params.mountPoint.data(), params.username.data(), params.password.data(), @@ -6451,7 +6811,8 @@ void GnssAdapter::handleEnablePPENtrip(const GnssNtripConnectionParams& params) 0 == pNtripParams->mountPoint.compare(params.mountPoint) && 0 == pNtripParams->username.compare(params.username) && 0 == pNtripParams->password.compare(params.password) && - params.requiresNmeaLocation == params.requiresNmeaLocation) { + pNtripParams->requiresNmeaLocation == params.requiresNmeaLocation && + mDgnssState & DGNSS_STATE_ENABLE_NTRIP_COMMAND) { LOC_LOGd("received same Ntrip param"); return; } @@ -6486,13 +6847,14 @@ void GnssAdapter::disablePPENtripStreamCommand() { } void GnssAdapter::handleDisablePPENtrip() { - mStartDgnssNtripParams.clear(); mDgnssState &= ~DGNSS_STATE_ENABLE_NTRIP_COMMAND; mDgnssState |= DGNSS_STATE_NO_NMEA_PENDING; stopDgnssNtrip(); } void GnssAdapter::checkUpdateDgnssNtrip(bool isLocationValid) { + LOC_LOGd("isInSession %d mDgnssState 0x%x isLocationValid %d", + isInSession(), mDgnssState, isLocationValid); if (isInSession()) { uint64_t curBootTime = getBootTimeMilliSec(); if (mDgnssState == (DGNSS_STATE_ENABLE_NTRIP_COMMAND | DGNSS_STATE_NO_NMEA_PENDING)) { @@ -6511,12 +6873,11 @@ void GnssAdapter::checkUpdateDgnssNtrip(bool isLocationValid) { } void GnssAdapter::stopDgnssNtrip() { + LOC_LOGd("isInSession %d mDgnssState 0x%x", isInSession(), mDgnssState); + mStartDgnssNtripParams.nmea.clear(); if (mDgnssState & DGNSS_STATE_NTRIP_SESSION_STARTED) { mDgnssState &= ~DGNSS_STATE_NTRIP_SESSION_STARTED; mXtraObserver.stopDgnssSource(); - } else { - LOC_LOGd("isInSession %d mDgnssState 0x%x", - isInSession(), mDgnssState); } } diff --git a/gps/gnss/GnssAdapter.h b/gps/gnss/GnssAdapter.h index 358aaed..2cd4a5c 100644 --- a/gps/gnss/GnssAdapter.h +++ b/gps/gnss/GnssAdapter.h @@ -39,6 +39,9 @@ #include #include #include +#include +#include +#include #define MAX_URL_LEN 256 #define NMEA_SENTENCE_MAX_LENGTH 200 @@ -146,6 +149,7 @@ typedef struct { TuncConfigInfo tuncConfigInfo; PaceConfigInfo paceConfigInfo; RobustLocationConfigInfo robustLocationConfigInfo; + LeverArmConfigInfo leverArmConfigInfo; } LocIntegrationConfigInfo; using namespace loc_core; @@ -164,13 +168,10 @@ typedef std::function QDgnssSessionActiveCb; struct CdfwInterface { - void (*startDgnssApiService)(); - + void (*startDgnssApiService)(const MsgTask& msgTask); QDgnssListenerHDL (*createUsableReporter)( QDgnssSessionActiveCb sessionActiveCb); - void (*destroyUsableReporter)(QDgnssListenerHDL handle); - void (*reportUsable)(QDgnssListenerHDL handle, bool usable); }; @@ -179,6 +180,23 @@ typedef uint16_t DGnssStateBitMask; #define DGNSS_STATE_NO_NMEA_PENDING 0X02 #define DGNSS_STATE_NTRIP_SESSION_STARTED 0X04 +class GnssReportLoggerUtil { +public: + typedef void (*LogGnssLatency)(const GnssLatencyInfo& gnssLatencyMeasInfo); + + GnssReportLoggerUtil() : mLogLatency(nullptr) { + const char* libname = "liblocdiagiface.so"; + void* libHandle = nullptr; + mLogLatency = (LogGnssLatency)dlGetSymFromLib(libHandle, libname, "LogGnssLatency"); + } + + bool isLogEnabled(); + void log(const GnssLatencyInfo& gnssLatencyMeasInfo); + +private: + LogGnssLatency mLogLatency; +}; + class GnssAdapter : public LocAdapterBase { /* ==== Engine Hub ===================================================================== */ @@ -260,6 +278,12 @@ class GnssAdapter : public LocAdapterBase { BlockCPIInfo mBlockCPIInfo; bool mPowerOn; uint32_t mAllowFlpNetworkFixes; + std::queue mGnssLatencyInfoQueue; + GnssReportLoggerUtil mLogger; + bool mDreIntEnabled; + + /* === NativeAgpsHandler ======================================================== */ + NativeAgpsHandler mNativeAgpsHandler; /* === Misc callback from QMI LOC API ============================================== */ GnssEnergyConsumedCallback mGnssEnergyConsumedCb; @@ -268,10 +292,10 @@ class GnssAdapter : public LocAdapterBase { /*==== CONVERSION ===================================================================*/ static void convertOptions(LocPosMode& out, const TrackingOptions& trackingOptions); static void convertLocation(Location& out, const UlpLocation& ulpLocation, - const GpsLocationExtended& locationExtended, - const LocPosTechMask techMask); + const GpsLocationExtended& locationExtended); static void convertLocationInfo(GnssLocationInfoNotification& out, - const GpsLocationExtended& locationExtended); + const GpsLocationExtended& locationExtended, + loc_sess_status status); static uint16_t getNumSvUsed(uint64_t svUsedIdsMask, int totalSvCntInThisConstellation); @@ -293,6 +317,8 @@ protected: /* ==== CLIENT ========================================================================= */ virtual void updateClientsEventMask(); virtual void stopClientSessions(LocationAPI* client); + inline void setNmeaReportRateConfig(); + void logLatencyInfo(); public: @@ -383,6 +409,8 @@ public: void deleteAidingData(const GnssAidingData &data, uint32_t sessionId); void gnssUpdateXtraThrottleCommand(const bool enabled); std::vector gnssUpdateConfig(const std::string& oldMoServerUrl, + const std::string& moServerUrl, + const std::string& serverUrl, GnssConfig& gnssConfigRequested, GnssConfig& gnssConfigNeedEngineUpdate, size_t count = 0); @@ -437,6 +465,8 @@ public: inline void antennaInfoCloseCommand() { mIsAntennaInfoInterfaceOpened = false; } uint32_t configMinGpsWeekCommand(uint16_t minGpsWeek); uint32_t configDeadReckoningEngineParamsCommand(const DeadReckoningEngineConfig& dreConfig); + uint32_t configEngineRunStateCommand(PositioningEngineMask engType, + LocEngineRunState engState); /* ========= ODCPI ===================================================================== */ /* ======== COMMANDS ====(Called from Client Thread)==================================== */ @@ -492,6 +522,11 @@ public: virtual bool reportGnssAdditionalSystemInfoEvent( GnssAdditionalSystemInfo& additionalSystemInfo); virtual void reportNfwNotificationEvent(GnssNfwNotification& notification); + virtual void reportLatencyInfoEvent(const GnssLatencyInfo& gnssLatencyInfo); + virtual bool reportQwesCapabilities + ( + const std::unordered_map &featureMap + ); /* ======== UTILITIES ================================================================= */ bool needReportForGnssClient(const UlpLocation& ulpLocation, @@ -567,6 +602,8 @@ public: static void convertGnssSvIdMaskToList( uint64_t svIdMask, std::vector& svIds, GnssSvId initialSvId, GnssSvType svType); + static void computeVRPBasedLla(const UlpLocation& loc, GpsLocationExtended& locExt, + const LeverArmConfigInfo& leverArmConfigInfo); void injectLocationCommand(double latitude, double longitude, float accuracy); void injectLocationExtCommand(const GnssLocationInfoNotification &locationInfo); @@ -590,6 +627,7 @@ public: void setSuplHostServer(const char* server, int port, LocServerType type); void notifyClientOfCachedLocationSystemInfo(LocationAPI* client, const LocationCallbacks& callbacks); + LocationCapabilitiesMask getCapabilities(); void updateSystemPowerStateCommand(PowerStateType systemPowerState); /*==== DGnss Usable Report Flag ====================================================*/ diff --git a/gps/gnss/Makefile.am b/gps/gnss/Makefile.am index db20c15..dd313a1 100644 --- a/gps/gnss/Makefile.am +++ b/gps/gnss/Makefile.am @@ -13,7 +13,8 @@ libgnss_la_SOURCES = \ location_gnss.cpp \ GnssAdapter.cpp \ XtraSystemStatusObserver.cpp \ - Agps.cpp + Agps.cpp \ + NativeAgpsHandler.cpp if USE_GLIB libgnss_la_CFLAGS = -DUSE_GLIB $(AM_CFLAGS) @GLIB_CFLAGS@ diff --git a/gps/gnss/NativeAgpsHandler.cpp b/gps/gnss/NativeAgpsHandler.cpp new file mode 100644 index 0000000..ce4c03a --- /dev/null +++ b/gps/gnss/NativeAgpsHandler.cpp @@ -0,0 +1,127 @@ +/* Copyright (c) 2020, 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_NativeAgpsHandler" + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace loc_core; + +// IDataItemObserver overrides +void NativeAgpsHandler::getName(string& name) { + name = "NativeAgpsHandler"; +} + +void NativeAgpsHandler::notify(const list& dlist) { + for (auto each : dlist) { + switch (each->getId()) { + case NETWORKINFO_DATA_ITEM_ID: { + NetworkInfoDataItemBase* networkInfo = + static_cast(each); + uint64_t mobileBit = (uint64_t )1 << loc_core::TYPE_MOBILE; + uint64_t allTypes = networkInfo->mAllTypes; + mConnected = ((networkInfo->mAllTypes & mobileBit) == mobileBit); + /** + * mApn Telephony preferred Access Point Name to use for + * carrier data connection when connected to a cellular network. + * Empty string, otherwise. + */ + mApn = networkInfo->mApn; + LOC_LOGd("updated mConnected:%d, mApn: %s", mConnected, mApn.c_str()); + break; + } + default: + break; + } + } +} + +NativeAgpsHandler* NativeAgpsHandler::sLocalHandle = nullptr; +NativeAgpsHandler::NativeAgpsHandler(IOsObserver* sysStatObs, GnssAdapter& adapter) : + mSystemStatusObsrvr(sysStatObs), mConnected(false), mAdapter(adapter) { + sLocalHandle = this; + list subItemIdList = {NETWORKINFO_DATA_ITEM_ID}; + mSystemStatusObsrvr->subscribe(subItemIdList, this); +} + +NativeAgpsHandler::~NativeAgpsHandler() { + if (nullptr != mSystemStatusObsrvr) { + LOC_LOGd("Unsubscribe for network info."); + list subItemIdList = {NETWORKINFO_DATA_ITEM_ID}; + mSystemStatusObsrvr->unsubscribe(subItemIdList, this); + } + sLocalHandle = nullptr; + mSystemStatusObsrvr = nullptr; +} + + +AgpsCbInfo NativeAgpsHandler::getAgpsCbInfo() { + AgpsCbInfo nativeCbInfo = {}; + nativeCbInfo.statusV4Cb = (void*)agnssStatusIpV4Cb; + nativeCbInfo.atlType = AGPS_ATL_TYPE_WWAN; + return nativeCbInfo; +} + +void NativeAgpsHandler::agnssStatusIpV4Cb(AGnssExtStatusIpV4 statusInfo) { + if (nullptr != sLocalHandle) { + sLocalHandle->processATLRequestRelease(statusInfo); + } else { + LOC_LOGe("sLocalHandle is null"); + } +} + +void NativeAgpsHandler::processATLRequestRelease(AGnssExtStatusIpV4 statusInfo) { + if (LOC_AGPS_TYPE_WWAN_ANY == statusInfo.type) { + LOC_LOGd("status.type = %d status.apnTypeMask = 0x%X", statusInfo.type, + statusInfo.apnTypeMask); + switch (statusInfo.status) { + case LOC_GPS_REQUEST_AGPS_DATA_CONN: + if (mConnected) { + mAdapter.dataConnOpenCommand(LOC_AGPS_TYPE_WWAN_ANY, mApn.c_str(), mApn.size(), + AGPS_APN_BEARER_IPV4); + } else { + mAdapter.dataConnFailedCommand(LOC_AGPS_TYPE_WWAN_ANY); + } + break; + case LOC_GPS_RELEASE_AGPS_DATA_CONN: + mAdapter.dataConnClosedCommand(LOC_AGPS_TYPE_WWAN_ANY); + break; + default: + LOC_LOGe("Invalid Request: %d", statusInfo.status); + } + } else { + LOC_LOGe("mAgpsManger is null or invalid request type!"); + } +} diff --git a/gps/gnss/NativeAgpsHandler.h b/gps/gnss/NativeAgpsHandler.h new file mode 100644 index 0000000..fb0b46c --- /dev/null +++ b/gps/gnss/NativeAgpsHandler.h @@ -0,0 +1,64 @@ +/* Copyright (c) 2020, 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 NATIVEAGPSHANDLER_H +#define NATIVEAGPSHANDLER_H + +#include +#include +#include +#include +#include +#include + +using namespace std; +using loc_core::IOsObserver; +using loc_core::IDataItemObserver; +using loc_core::IDataItemCore; + +class GnssAdapter; + +class NativeAgpsHandler : public IDataItemObserver { +public: + NativeAgpsHandler(IOsObserver* sysStatObs, GnssAdapter& adapter); + ~NativeAgpsHandler(); + AgpsCbInfo getAgpsCbInfo(); + // IDataItemObserver overrides + virtual void notify(const list& dlist); + inline virtual void getName(string& name); +private: + static NativeAgpsHandler* sLocalHandle; + static void agnssStatusIpV4Cb(AGnssExtStatusIpV4 statusInfo); + void processATLRequestRelease(AGnssExtStatusIpV4 statusInfo); + IOsObserver* mSystemStatusObsrvr; + bool mConnected; + string mApn; + GnssAdapter& mAdapter; +}; + +#endif // NATIVEAGPSHANDLER_H diff --git a/gps/gnss/location_gnss.cpp b/gps/gnss/location_gnss.cpp index 3bfb930..8f67369 100644 --- a/gps/gnss/location_gnss.cpp +++ b/gps/gnss/location_gnss.cpp @@ -66,8 +66,8 @@ 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, bool roaming = false, - NetworkHandle networkHandle = NETWORK_HANDLE_UNKNOWN); +static void updateConnectionStatus(bool connected, int8_t type, bool roaming, + NetworkHandle networkHandle, string& apn); static void getGnssEnergyConsumed(GnssEnergyConsumedCallback energyConsumedCb); static void enableNfwLocationAccess(bool enable); static void nfwInit(const NfwCbInfo& cbInfo); @@ -92,6 +92,7 @@ static uint32_t configMinGpsWeek(uint16_t minGpsWeek); static uint32_t configDeadReckoningEngineParams(const DeadReckoningEngineConfig& dreConfig); static uint32_t gnssUpdateSecondaryBandConfig(const GnssSvTypeConfig& secondaryBandConfig); static uint32_t gnssGetSecondaryBandConfig(); +static void resetNetworkInfo(); static void updateNTRIPGGAConsent(bool consentAccepted); static void enablePPENtripStream(const GnssNtripConnectionParams& params, bool enableRTKEngine); @@ -102,6 +103,7 @@ static bool measCorrSetCorrections(const GnssMeasurementCorrections gnssMeasCorr static void measCorrClose(); static uint32_t antennaInfoInit(const antennaInfoCb antennaInfoCallback); static void antennaInfoClose(); +static uint32_t configEngineRunState(PositioningEngineMask engType, LocEngineRunState engState); static const GnssInterface gGnssInterface = { sizeof(GnssInterface), @@ -159,6 +161,8 @@ static const GnssInterface gGnssInterface = { disablePPENtripStream, gnssUpdateSecondaryBandConfig, gnssGetSecondaryBandConfig, + resetNetworkInfo, + configEngineRunState }; #ifndef DEBUG_X86 @@ -367,10 +371,11 @@ static void getDebugReport(GnssDebugReport& report) { } static void updateConnectionStatus(bool connected, int8_t type, - bool roaming, NetworkHandle networkHandle) { + bool roaming, NetworkHandle networkHandle, + string& apn) { if (NULL != gGnssAdapter) { gGnssAdapter->getSystemStatus()->eventConnectionStatus( - connected, type, roaming, networkHandle); + connected, type, roaming, networkHandle, apn); } } @@ -434,6 +439,12 @@ static void updateBatteryStatus(bool charging) { } } +static void resetNetworkInfo() { + if (NULL != gGnssAdapter) { + gGnssAdapter->getSystemStatus()->resetNetworkInfo(); + } +} + static void updateSystemPowerState(PowerStateType systemPowerState) { if (NULL != gGnssAdapter) { gGnssAdapter->updateSystemPowerStateCommand(systemPowerState); @@ -508,7 +519,7 @@ static uint32_t antennaInfoInit(const antennaInfoCb antennaInfoCallback) { static void antennaInfoClose() { if (NULL != gGnssAdapter) { return gGnssAdapter->antennaInfoCloseCommand(); - } + } } static uint32_t configRobustLocation(bool enable, bool enableForE911){ @@ -572,3 +583,11 @@ static void disablePPENtripStream(){ gGnssAdapter->disablePPENtripStreamCommand(); } } + +static uint32_t configEngineRunState(PositioningEngineMask engType, LocEngineRunState engState) { + if (NULL != gGnssAdapter) { + return gGnssAdapter->configEngineRunStateCommand(engType, engState); + } else { + return 0; + } +} diff --git a/gps/location/ILocationAPI.h b/gps/location/ILocationAPI.h index 96076e9..29846ac 100644 --- a/gps/location/ILocationAPI.h +++ b/gps/location/ILocationAPI.h @@ -363,6 +363,44 @@ public: LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid */ virtual uint32_t configDeadReckoningEngineParams(const DeadReckoningEngineConfig& dreConfig)=0; + + /** @brief + This API is used to instruct the specified engine to be in + the pause/resume state.
+ + When the engine is placed in paused state, the engine will + stop. If there is an on-going session, engine will no longer + produce fixes. In the paused state, calling API to delete + aiding data from the paused engine may not have effect. + Request to delete Aiding data shall be issued after + engine resume.
+ + Currently, only DRE engine will support pause/resume + request. responseCb() will return not supported when request + is made to pause/resume none-DRE engine.
+ + Request to pause/resume DRE engine can be made with or + without an on-going session. With QDR engine, on resume, + GNSS position & heading re-acquisition is needed for DR + engine to engage. If DR engine is already in the requested + state, the request will be no-op.
+ + @param + engType: the engine that is instructed to change its run + state.
+ + engState: the new engine run state that the engine is + instructed to be in.
+ + @return + A session id that will be returned in responseCallback to + match command with response. This effect is global for all + clients of LocationAPI responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid + */ + virtual uint32_t configEngineRunState(PositioningEngineMask engType, + LocEngineRunState engState) = 0; }; #endif /* ILOCATIONAPI_H */ diff --git a/gps/location/LocationAPI.cpp b/gps/location/LocationAPI.cpp index 5c4be47..3a50c46 100644 --- a/gps/location/LocationAPI.cpp +++ b/gps/location/LocationAPI.cpp @@ -39,6 +39,15 @@ typedef const GnssInterface* (getGnssInterface)(); typedef const GeofenceInterface* (getGeofenceInterface)(); typedef const BatchingInterface* (getBatchingInterface)(); +typedef void (createOSFramework)(); +typedef void (destroyOSFramework)(); + +// GTP services +typedef uint32_t (setOptInStatusGetter)(bool userConsent, responseCallback* callback); +typedef void (enableProviderGetter)(); +typedef void (disableProviderGetter)(); +typedef void (getSingleNetworkLocationGetter)(trackingCallback* callback); +typedef void (stopNetworkLocationGetter)(trackingCallback* callback); typedef struct { // bit mask of the adpaters that we need to wait for the removeClientCompleteCallback @@ -68,6 +77,7 @@ static pthread_mutex_t gDataMutex = PTHREAD_MUTEX_INITIALIZER; static bool gGnssLoadFailed = false; static bool gBatchingLoadFailed = false; static bool gGeofenceLoadFailed = false; +static uint32_t gOSFrameworkRefCount = 0; template static const T1* loadLocationInterface(const char* library, const char* name) { @@ -80,6 +90,28 @@ static const T1* loadLocationInterface(const char* library, const char* name) { } } +static void createOSFrameworkInstance() { + void* libHandle = nullptr; + createOSFramework* getter = (createOSFramework*)dlGetSymFromLib(libHandle, + "liblocationservice_glue.so", "createOSFramework"); + if (getter != nullptr) { + (*getter)(); + } else { + LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so"); + } +} + +static void destroyOSFrameworkInstance() { + void* libHandle = nullptr; + destroyOSFramework* getter = (destroyOSFramework*)dlGetSymFromLib(libHandle, + "liblocationservice_glue.so", "destroyOSFramework"); + if (getter != nullptr) { + (*getter)(); + } else { + LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so"); + } +} + static bool needsGnssTrackingInfo(LocationCallbacks& locationCallbacks) { return (locationCallbacks.gnssLocationInfoCb != nullptr || @@ -132,9 +164,11 @@ void LocationAPI::onRemoveClientCompleteCb (LocationAdapterTypeMask adapterType) } pthread_mutex_unlock(&gDataMutex); - if ((true == invokeCallback) && (nullptr != destroyCompleteCb)) { + if (invokeCallback) { LOC_LOGd("invoke client destroy cb"); - (destroyCompleteCb) (); + if (!destroyCompleteCb) { + (destroyCompleteCb) (); + } delete this; } @@ -161,6 +195,7 @@ LocationAPI::createInstance (LocationCallbacks& locationCallbacks) if (nullptr == locationCallbacks.capabilitiesCb || nullptr == locationCallbacks.responseCb || nullptr == locationCallbacks.collectiveResponseCb) { + LOC_LOGe("missing mandatory callback, return null"); return NULL; } @@ -169,6 +204,11 @@ LocationAPI::createInstance (LocationCallbacks& locationCallbacks) pthread_mutex_lock(&gDataMutex); + gOSFrameworkRefCount++; + if (1 == gOSFrameworkRefCount) { + createOSFrameworkInstance(); + } + if (isGnssClient(locationCallbacks)) { if (NULL == gData.gnssInterface && !gGnssLoadFailed) { gData.gnssInterface = @@ -286,7 +326,7 @@ LocationAPI::destroy(locationApiDestroyCompleteCallback destroyCompleteCb) gData.clientData.erase(it); - if ((NULL != destroyCompleteCb) && (false == needToWait)) { + if (!needToWait) { invokeDestroyCb = true; } } else { @@ -294,9 +334,16 @@ LocationAPI::destroy(locationApiDestroyCompleteCallback destroyCompleteCb) __func__, __LINE__, this); } + if (1 == gOSFrameworkRefCount) { + destroyOSFrameworkInstance(); + } + gOSFrameworkRefCount--; + pthread_mutex_unlock(&gDataMutex); - if (invokeDestroyCb == true) { - (destroyCompleteCb) (); + if (invokeDestroyCb) { + if (!destroyCompleteCb) { + (destroyCompleteCb) (); + } delete this; } } @@ -602,6 +649,52 @@ LocationAPI::gnssNiResponse(uint32_t id, GnssNiResponse response) pthread_mutex_unlock(&gDataMutex); } +void LocationAPI::enableNetworkProvider() { + void* libHandle = nullptr; + enableProviderGetter* setter = (enableProviderGetter*)dlGetSymFromLib(libHandle, + "liblocationservice_glue.so", "enableNetworkProvider"); + if (setter != nullptr) { + (*setter)(); + } else { + LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so"); + } +} + +void LocationAPI::disableNetworkProvider() { + void* libHandle = nullptr; + disableProviderGetter* setter = (disableProviderGetter*)dlGetSymFromLib(libHandle, + "liblocationservice_glue.so", "disableNetworkProvider"); + if (setter != nullptr) { + (*setter)(); + } else { + LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so"); + } +} + +void LocationAPI::startNetworkLocation(trackingCallback* callback) { + void* libHandle = nullptr; + getSingleNetworkLocationGetter* setter = + (getSingleNetworkLocationGetter*)dlGetSymFromLib(libHandle, + "liblocationservice_glue.so", "startNetworkLocation"); + if (setter != nullptr) { + (*setter)(callback); + } else { + LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so"); + } +} + +void LocationAPI::stopNetworkLocation(trackingCallback* callback) { + void* libHandle = nullptr; + stopNetworkLocationGetter* setter = (stopNetworkLocationGetter*)dlGetSymFromLib(libHandle, + "liblocationservice_glue.so", "stopNetworkLocation"); + if (setter != nullptr) { + LOC_LOGe("called"); + (*setter)(callback); + } else { + LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so"); + } +} + LocationControlAPI* LocationControlAPI::createInstance(LocationControlCallbacks& locationControlCallbacks) { @@ -853,3 +946,31 @@ uint32_t LocationControlAPI::configDeadReckoningEngineParams( pthread_mutex_unlock(&gDataMutex); return id; } + +uint32_t LocationControlAPI::configEngineRunState( + PositioningEngineMask engType, LocEngineRunState engState) { + uint32_t id = 0; + pthread_mutex_lock(&gDataMutex); + + if (gData.gnssInterface != NULL) { + id = gData.gnssInterface->configEngineRunState(engType, engState); + } else { + LOC_LOGe("No gnss interface available for Location Control API"); + } + + pthread_mutex_unlock(&gDataMutex); + return id; +} + +uint32_t LocationControlAPI::setOptInStatus(bool userConsent) { + void* libHandle = nullptr; + uint32_t sessionId = 0; + setOptInStatusGetter* setter = (setOptInStatusGetter*)dlGetSymFromLib(libHandle, + "liblocationservice_glue.so", "setOptInStatus"); + if (setter != nullptr) { + sessionId = (*setter)(userConsent, &gData.controlCallbacks.responseCb); + } else { + LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so"); + } + return sessionId; +} diff --git a/gps/location/LocationAPI.h b/gps/location/LocationAPI.h index 5646ec8..7c70506 100644 --- a/gps/location/LocationAPI.h +++ b/gps/location/LocationAPI.h @@ -178,6 +178,20 @@ public: LOCATION_ERROR_INVALID_PARAMETER if any parameters in GnssNiResponse are invalid LOCATION_ERROR_ID_UNKNOWN if id does not match a gnssNiCallback */ virtual void gnssNiResponse(uint32_t id, GnssNiResponse response) override; + + /* ================================== NETWORK PROVIDER =========================== */ + + /* enableNetworkProvider enables Network Provider */ + virtual void enableNetworkProvider(); + + /* disableNetworkProvider disables Network Provider */ + virtual void disableNetworkProvider(); + + /* startNetworkLocation start a single shot network location request */ + virtual void startNetworkLocation(trackingCallback* callback); + + /* stopNetworkLocation stop any ongoing network location request */ + virtual void stopNetworkLocation(trackingCallback* callback); }; typedef struct { @@ -235,7 +249,10 @@ public: collectiveResponseCallback returns: LOCATION_ERROR_SUCCESS if session was successful LOCATION_ERROR_INVALID_PARAMETER if any other parameters are invalid - LOCATION_ERROR_GENERAL_FAILURE if failure for any other reason */ + LOCATION_ERROR_GENERAL_FAILURE if failure for any other reason + + PLEASE NOTE: It is caller's resposibility to FREE the memory of the return value. + The memory must be freed by delete [].*/ virtual uint32_t* gnssUpdateConfig(const GnssConfig& config) override; /* gnssGetConfig fetches the current constellation and SV configuration @@ -250,7 +267,10 @@ public: LOCATION_ERROR_CALLBACK_MISSING If no gnssConfigCallback was passed in createInstance LOCATION_ERROR_NOT_SUPPORTED If read of requested configuration - is not supported */ + is not supported + + PLEASE NOTE: It is caller's resposibility to FREE the memory of the return value. + The memory must be freed by delete [].*/ uint32_t* gnssGetConfig(GnssConfigFlagsMask mask); /* delete specific gnss aiding data for testing, which returns a session id @@ -436,6 +456,57 @@ public: */ virtual uint32_t configDeadReckoningEngineParams( const DeadReckoningEngineConfig& dreConfig) override; + + /** @brief + This API is used to instruct the specified engine to be in + the pause/resume state.
+ + When the engine is placed in paused state, the engine will + stop. If there is an on-going session, engine will no longer + produce fixes. In the paused state, calling API to delete + aiding data from the paused engine may not have effect. + Request to delete Aiding data shall be issued after + engine resume.
+ + Currently, only DRE engine will support pause/resume + request. responseCb() will return not supported when request + is made to pause/resume none-DRE engine.
+ + Request to pause/resume DRE engine can be made with or + without an on-going session. With QDR engine, on resume, GNSS + position & heading re-acquisition is needed for DR engine to + engage. If DR engine is already in the requested state, the + request will be no-op.
+ + @param + engType: the engine that is instructed to change its run + state.
+ + engState: the new engine run state that the engine is + instructed to be in.
+ + @return + A session id that will be returned in responseCallback to + match command with response. This effect is global for all + clients of LocationAPI responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid + */ + virtual uint32_t configEngineRunState(PositioningEngineMask engType, + LocEngineRunState engState) override; + + /** @brief + Set the EULA opt-in status from system user. This is used as consent to + use network-based positioning. + + @param + userConsnt: user agrees to use GTP service or not. + + @return + A session id that will be returned in responseCallback to + match command with response. + */ + virtual uint32_t setOptInStatus(bool userConsent); }; #endif /* LOCATIONAPI_H */ diff --git a/gps/location/LocationAPIClientBase.cpp b/gps/location/LocationAPIClientBase.cpp index de0fb6f..ea15a76 100644 --- a/gps/location/LocationAPIClientBase.cpp +++ b/gps/location/LocationAPIClientBase.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, 2020 The Linux Foundation. All rights reserved. +/* Copyright (c) 2017, 2020-2021 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 @@ -158,6 +158,7 @@ uint32_t LocationAPIControlClient::locAPIGnssUpdateConfig(GnssConfig config) } mRequestQueues[CTRL_REQUEST_CONFIG_UPDATE].push(new GnssUpdateConfigRequest(*this)); retVal = LOCATION_ERROR_SUCCESS; + delete [] idArray; } } } @@ -180,6 +181,7 @@ uint32_t LocationAPIControlClient::locAPIGnssGetConfig(GnssConfigFlagsMask mask) } mRequestQueues[CTRL_REQUEST_CONFIG_GET].push(new GnssGetConfigRequest(*this)); retVal = LOCATION_ERROR_SUCCESS; + delete [] idArray; } } pthread_mutex_unlock(&mMutex); @@ -318,16 +320,24 @@ void LocationAPIClientBase::destroy() mGeofenceBreachCallback = nullptr; - if (mLocationAPI) { - mLocationAPI->destroy([this]() {onLocationApiDestroyCompleteCb();}); - mLocationAPI = nullptr; - } - for (int i = 0; i < REQUEST_MAX; i++) { mRequestQueues[i].reset((uint32_t)0); } + LocationAPI* localHandle = nullptr; + if (nullptr != mLocationAPI) { + localHandle = mLocationAPI; + mLocationAPI = nullptr; + } + pthread_mutex_unlock(&mMutex); + + // Invoking destroy has the possibility of destroy complete callback + // being invoked right away in the same context, hence no instance + // member must be accessed after the destroy call. + if (nullptr != localHandle) { + localHandle->destroy([this]() {onLocationApiDestroyCompleteCb();}); + } } LocationAPIClientBase::~LocationAPIClientBase() @@ -624,7 +634,7 @@ uint32_t LocationAPIClientBase::locAPIGetBatchedLocations(uint32_t id, size_t co } } else { retVal = LOCATION_ERROR_ID_UNKNOWN; - LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__, id); + LOC_LOGd("unknown session id: %d, might flush() a stopped session", id); } } pthread_mutex_unlock(&mMutex); diff --git a/gps/location/LocationDataTypes.h b/gps/location/LocationDataTypes.h index a7f3a6c..b85464a 100644 --- a/gps/location/LocationDataTypes.h +++ b/gps/location/LocationDataTypes.h @@ -61,7 +61,8 @@ typedef enum { LOCATION_ERROR_ID_UNKNOWN, LOCATION_ERROR_ALREADY_STARTED, LOCATION_ERROR_GEOFENCES_AT_MAX, - LOCATION_ERROR_NOT_SUPPORTED + LOCATION_ERROR_NOT_SUPPORTED, + LOCATION_ERROR_TIMEOUT, } LocationError; // Flags to indicate which values are valid in a Location @@ -91,7 +92,10 @@ typedef enum { LOCATION_TECHNOLOGY_INJECTED_COARSE_POSITION_BIT = (1<<5), // using CPI LOCATION_TECHNOLOGY_AFLT_BIT = (1<<6), // AFLT LOCATION_TECHNOLOGY_HYBRID_BIT = (1<<7), // HYBRID - LOCATION_TECHNOLOGY_PPE_BIT = (1<<8) // PPE + LOCATION_TECHNOLOGY_PPE_BIT = (1<<8), // PPE + LOCATION_TECHNOLOGY_VEH_BIT = (1<<9), // using vehicular data + LOCATION_TECHNOLOGY_VIS_BIT = (1<<10), // using visual data + LOCATION_TECHNOLOGY_DGNSS_BIT = (1<<11), // DGNSS } LocationTechnologyBits; typedef uint32_t LocationSpoofMask; @@ -206,7 +210,9 @@ typedef enum { GNSS_LOCATION_INFO_CONFORMITY_INDEX_BIT = (1<<28), // conformity index GNSS_LOCATION_INFO_LLA_VRP_BASED_BIT = (1<<29), // VRP-based lat/long/alt GNSS_LOCATION_INFO_ENU_VELOCITY_VRP_BASED_BIT = (1<<30), // VRP-based east/north/up vel - GNSS_LOCATION_INFO_DR_SOLUTION_STATUS_MASK_BIT = (1ULL<<31), // DR solution status + GNSS_LOCATION_INFO_DR_SOLUTION_STATUS_MASK_BIT = (1ULL<<31), // Valid DR solution status + GNSS_LOCATION_INFO_ALTITUDE_ASSUMED_BIT = (1ULL<<32), // Valid altitude assumed + GNSS_LOCATION_INFO_SESSION_STATUS_BIT = (1ULL<<33), // session status } GnssLocationInfoFlagBits; typedef enum { @@ -230,7 +236,8 @@ typedef enum { GEOFENCE_STATUS_AVAILABILE_YES, } GeofenceStatusAvailable; -typedef uint32_t LocationCapabilitiesMask; +// Set of masks for Modem and QWES capabilities. +typedef uint64_t LocationCapabilitiesMask; typedef enum { // supports startTracking API with minInterval param LOCATION_CAPABILITIES_TIME_BASED_TRACKING_BIT = (1<<0), @@ -264,8 +271,86 @@ typedef enum { LOCATION_CAPABILITIES_CONFORMITY_INDEX_BIT = (1<<14), // support precise location edgnss LOCATION_CAPABILITIES_EDGNSS_BIT = (1<<15), + // Modem supports Carrier Phase for Precise Positioning + // Measurement Engine (PPME). + LOCATION_CAPABILITIES_QWES_CARRIER_PHASE_BIT = (1<<16), + // Modem supports SV Polynomial for tightly coupled external + // DR support. This is a Standalone Feature. + LOCATION_CAPABILITIES_QWES_SV_POLYNOMIAL_BIT = (1<<17), + // Modem supports SV Ephemeris for tightly coupled external + // PPE engines. This is a Standalone Feature. + LOCATION_CAPABILITIES_QWES_SV_EPHEMERIS_BIT = (1<<18), + // Modem supports GNSS Single Frequency feature. This is a + // Standalone Feature. + LOCATION_CAPABILITIES_QWES_GNSS_SINGLE_FREQUENCY = (1<<19), + // Modem supports GNSS Multi Frequency feature. Multi Frequency + // enables Single frequency also. + LOCATION_CAPABILITIES_QWES_GNSS_MULTI_FREQUENCY = (1<<20), + // This mask indicates VPe license bundle is enabled. VEPP + // bundle include Carrier Phase and SV Polynomial features. + LOCATION_CAPABILITIES_QWES_VPE = (1<<21), + // This mask indicates support for CV2X Location basic features. + // This bundle includes features for GTS Time & Freq, C-TUNC + // (Constrained Time uncertainity. + LOCATION_CAPABILITIES_QWES_CV2X_LOCATION_BASIC = (1<<22), + // This mask indicates support for CV2X Location premium features. + // This bundle includes features for CV2X Location Basic features, + // QDR3 feature, and PACE. (Position Assisted Clock Estimator. + LOCATION_CAPABILITIES_QWES_CV2X_LOCATION_PREMIUM = (1<<23), + // This mask indicates that PPE (Precise Positioning Engine) + // library is enabled or Precise Positioning Framework (PPF) + // is available. This bundle includes features for Carrier + // Phase and SV Ephermeris. + LOCATION_CAPABILITIES_QWES_PPE = (1<<24), + // This mask indicates QDR2_C license bundle is enabled. This + // bundle includes features for SV Polynomial. + LOCATION_CAPABILITIES_QWES_QDR2 = (1<<25), + // This mask indicates QDR3_C license bundle is enabled. This + // bundle includes features for SV Polynomial. + LOCATION_CAPABILITIES_QWES_QDR3 = (1<<26), } LocationCapabilitiesBits; +typedef uint8_t LocationQwesFeatureType; +typedef enum { + // Modem supports Carrier Phase for Precise Positioning + // Measurement Engine (PPME). + LOCATION_QWES_FEATURE_TYPE_CARRIER_PHASE = 1, + // Modem supports SV Polynomial for tightly coupled external + // DR support. This is a Standalone Feature. + LOCATION_QWES_FEATURE_TYPE_SV_POLYNOMIAL, + // Modem supports SV Ephemeris for tightly coupled external + // PPE support. This is a Standalone Feature. + LOCATION_QWES_FEATURE_TYPE_SV_EPH, + // Modem supports GNSS Single Frequency feature. This is a + // Standalone Feature. + LOCATION_QWES_FEATURE_TYPE_GNSS_SINGLE_FREQUENCY, + // Modem supports GNSS Multi Frequency feature. Multi Frequency + // enables Single frequency also. + LOCATION_QWES_FEATURE_TYPE_GNSS_MULTI_FREQUENCY, + // This indicates Time and Frequency status. + LOCATION_QWES_FEATURE_TYPE_TIME_FREQUENCY, + // This indicates Time Uncertainty status. + LOCATION_QWES_FEATURE_TYPE_TIME_UNCERTAINTY, + // This indicates Clock Estimate status. + LOCATION_QWES_FEATURE_TYPE_CLOCK_ESTIMATE, + // This mask indicates that PPE (Precise Positioning Engine) + // library is enabled or Precise Positioning Framework (PPF) + // is available. This bundle includes features for Carrier + // Phase and SV Ephermeris. + LOCATION_QWES_FEATURE_TYPE_PPE, + // This indicates QDR2_C license bundle is enabled. This + // bundle includes features for SV Polynomial. + LOCATION_QWES_FEATURE_TYPE_QDR2, + // This indicates QDR3_C license bundle is enabled. This + // bundle includes features for SV Polynomial. + LOCATION_QWES_FEATURE_TYPE_QDR3, + // This indicates VEPP license bundle is enabled. VEPP + // bundle include Carrier Phase and SV Polynomial features. + LOCATION_QWES_FEATURE_TYPE_VPE, + // Max value + LOCATION_QWES_FEATURE_TYPE_MAX +} LocationQwesFeatureTypes; + typedef enum { LOCATION_TECHNOLOGY_TYPE_GNSS = 0, } LocationTechnologyType; @@ -717,10 +802,22 @@ typedef uint32_t PositioningEngineMask; typedef enum { STANDARD_POSITIONING_ENGINE = (1 << 0), DEAD_RECKONING_ENGINE = (1 << 1), - PRECISE_POSITIONING_ENGINE = (1 << 2) + PRECISE_POSITIONING_ENGINE = (1 << 2), + VP_POSITIONING_ENGINE = (1 << 3) } PositioningEngineBits; #define POSITION_ENGINE_MASK_ALL \ - (STANDARD_POSITIONING_ENGINE|DEAD_RECKONING_ENGINE|PRECISE_POSITIONING_ENGINE) + (STANDARD_POSITIONING_ENGINE|DEAD_RECKONING_ENGINE| \ + PRECISE_POSITIONING_ENGINE|VP_POSITIONING_ENGINE) + +/** Specify the position engine running state.
*/ +enum LocEngineRunState { + /** Request the position engine to be put into resume state. + *
*/ + LOC_ENGINE_RUN_STATE_PAUSE = 1, + /** Request the position engine to be put into resume state. + *
*/ + LOC_ENGINE_RUN_STATE_RESUME = 2, +}; typedef uint64_t GnssDataMask; typedef enum { @@ -821,6 +918,7 @@ typedef enum { LOC_REQ_ENGINE_FUSED_BIT = (1<<0), LOC_REQ_ENGINE_SPE_BIT = (1<<1), LOC_REQ_ENGINE_PPE_BIT = (1<<2), + LOC_REQ_ENGINE_VPE_BIT = (1<<3) } LocReqEngineTypeMask; typedef enum { @@ -829,6 +927,7 @@ typedef enum { LOC_OUTPUT_ENGINE_SPE = 1, /** This is the GNSS fix with correction PPP/RTK correction */ LOC_OUTPUT_ENGINE_PPE = 2, + LOC_OUTPUT_ENGINE_VPE = 3, LOC_OUTPUT_ENGINE_COUNT, } LocOutputEngineType; @@ -1087,6 +1186,12 @@ typedef struct { float altitude; // altitude wrt to ellipsoid } LLAInfo; +enum loc_sess_status { + LOC_SESS_SUCCESS, + LOC_SESS_INTERMEDIATE, + LOC_SESS_FAILURE +}; + typedef struct { uint32_t size; // set to sizeof(GnssLocationInfo) Location location; // basic locaiton info, latitude, longitude, and etc @@ -1127,7 +1232,7 @@ typedef struct { // location engine type. When the fix. when the type is set to // LOC_ENGINE_SRC_FUSED, the fix is the propagated/aggregated // reports from all engines running on the system (e.g.: - // DR/SPE/PPE). To check which location engine contributes to + // DR/SPE/PPE/VPE). To check which location engine contributes to // the fused output, check for locOutputEngMask. LocOutputEngineType locOutputEngType; // when loc output eng type is set to fused, this field @@ -1144,6 +1249,10 @@ typedef struct { // VRR-based east, north, and up velocity float enuVelocityVRPBased[3]; DrSolutionStatusMask drSolutionStatusMask; + // true: altitude is assumed, false: altitude is calculated + bool altitudeAssumed; + // location session status + loc_sess_status sessionStatus; } GnssLocationInfoNotification; typedef struct { @@ -1201,6 +1310,7 @@ typedef struct { float carrierFrequencyHz; // carrier frequency of the signal tracked GnssSignalTypeMask gnssSignalTypeMask; // Specifies GNSS signal type double basebandCarrierToNoiseDbHz; // baseband signal strength + uint16_t gloFrequency; // GLONASS Frequency channel number } GnssSv; struct GnssConfigSetAssistanceServer { @@ -1612,6 +1722,11 @@ struct LocationSystemInfo { LeapSecondSystemInfo leapSecondSysInfo; }; +// Specify the set of terrestrial technologies +enum TerrestrialTechMask { + TERRESTRIAL_TECH_GTP_WWAN = 1 << 0, +}; + // Specify parameters related to lever arm struct LeverArmParams { // Offset along the vehicle forward axis @@ -1933,4 +2048,23 @@ typedef struct { uint32_t port; bool useSSL; } GnssNtripConnectionParams; + +typedef struct { + uint64_t meQtimer1; + uint64_t meQtimer2; + uint64_t meQtimer3; + uint64_t peQtimer1; + uint64_t peQtimer2; + uint64_t peQtimer3; + uint64_t smQtimer1; + uint64_t smQtimer2; + uint64_t smQtimer3; + uint64_t locMwQtimer; + uint64_t hlosQtimer1; + uint64_t hlosQtimer2; + uint64_t hlosQtimer3; + uint64_t hlosQtimer4; + uint64_t hlosQtimer5; +} GnssLatencyInfo; + #endif /* LOCATIONDATATYPES_H */ diff --git a/gps/location/location_interface.h b/gps/location/location_interface.h index e399a5b..69d4f0c 100644 --- a/gps/location/location_interface.h +++ b/gps/location/location_interface.h @@ -78,7 +78,7 @@ struct GnssInterface { void (*agpsDataConnFailed)(AGpsExtType agpsType); void (*getDebugReport)(GnssDebugReport& report); void (*updateConnectionStatus)(bool connected, int8_t type, bool roaming, - NetworkHandle networkHandle); + NetworkHandle networkHandle, std::string& apn); void (*odcpiInit)(const OdcpiRequestCallback& callback, OdcpiPrioritytype priority); void (*odcpiInject)(const Location& location); void (*blockCPI)(double latitude, double longitude, float accuracy, @@ -108,6 +108,9 @@ struct GnssInterface { void (*disablePPENtripStream)(); uint32_t (*gnssUpdateSecondaryBandConfig)(const GnssSvTypeConfig& secondaryBandConfig); uint32_t (*gnssGetSecondaryBandConfig)(); + void (*resetNetworkInfo)(); + uint32_t (*configEngineRunState)(PositioningEngineMask engType, + LocEngineRunState engState); }; struct BatchingInterface { diff --git a/gps/utils/LocHeap.cpp b/gps/utils/LocHeap.cpp index d667f14..4d047e4 100644 --- a/gps/utils/LocHeap.cpp +++ b/gps/utils/LocHeap.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015, 2020 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 @@ -28,6 +28,8 @@ */ #include +namespace loc_util { + class LocHeapNode { friend class LocHeap; @@ -266,6 +268,8 @@ LocRankable* LocHeap::remove(LocRankable& rankable) { return locNode; } +} // namespace loc_util + #ifdef __LOC_UNIT_TEST__ bool LocHeap::checkTree() { return ((NULL == mTree) || mTree->checkNodes()); @@ -274,81 +278,3 @@ uint32_t LocHeap::getTreeSize() { return (NULL == mTree) ? 0 : mTree->getSize(); } #endif - -#ifdef __LOC_DEBUG__ - -#include -#include -#include - -class LocHeapDebug : public LocHeap { -public: - bool checkTree() { - return ((NULL == mTree) || mTree->checkNodes()); - } - - uint32_t getTreeSize() { - return (NULL == mTree) ? 0 : (mTree->getSize()); - } -}; - -class LocHeapDebugData : public LocRankable { - const int mID; -public: - LocHeapDebugData(int id) : mID(id) {} - inline virtual int ranks(LocRankable& rankable) { - LocHeapDebugData* testData = dynamic_cast(&rankable); - return testData->mID - mID; - } -}; - -// For Linux command line testing: -// compilation: g++ -D__LOC_HOST_DEBUG__ -D__LOC_DEBUG__ -g -I. -I../../../../vendor/qcom/proprietary/gps-internal/unit-tests/fakes_for_host -I../../../../system/core/include LocHeap.cpp -// test: valgrind --leak-check=full ./a.out 100 -int main(int argc, char** argv) { - srand(time(NULL)); - int tries = atoi(argv[1]); - int checks = tries >> 3; - LocHeapDebug heap; - int treeSize = 0; - - for (int i = 0; i < tries; i++) { - if (i % checks == 0 && !heap.checkTree()) { - printf("tree check failed before %dth op\n", i); - } - int r = rand(); - - if (r & 1) { - LocHeapDebugData* data = new LocHeapDebugData(r >> 1); - heap.push(dynamic_cast(*data)); - treeSize++; - } else { - LocRankable* rankable = heap.pop(); - if (rankable) { - delete rankable; - } - treeSize ? treeSize-- : 0; - } - - printf("%s: %d == %d\n", (r&1)?"push":"pop", treeSize, heap.getTreeSize()); - if (treeSize != heap.getTreeSize()) { - printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); - tries = i+1; - break; - } - } - - if (!heap.checkTree()) { - printf("!!!!!!!!!!tree check failed at the end after %d ops!!!!!!!\n", tries); - } else { - printf("success!\n"); - } - - for (LocRankable* data = heap.pop(); NULL != data; data = heap.pop()) { - delete data; - } - - return 0; -} - -#endif diff --git a/gps/utils/LocHeap.h b/gps/utils/LocHeap.h index b491948..bb62d6b 100644 --- a/gps/utils/LocHeap.h +++ b/gps/utils/LocHeap.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015, 2020 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 #include +namespace loc_util { + // abstract class to be implemented by client to provide a rankable class class LocRankable { public: @@ -93,4 +95,6 @@ public: #endif }; +} // namespace loc_util + #endif //__LOC_HEAP__ diff --git a/gps/utils/LocIpc.cpp b/gps/utils/LocIpc.cpp index bfe541d..746ca87 100644 --- a/gps/utils/LocIpc.cpp +++ b/gps/utils/LocIpc.cpp @@ -313,7 +313,7 @@ public: mAbortCalled(false), mLocIpc(locIpc), mIpcRecver(move(ipcRecver)) {} - inline bool run() override { + inline virtual bool run() override { if (mIpcRecver != nullptr) { mLocIpc.startBlockingListening(*(mIpcRecver.get())); if (!mAbortCalled) { @@ -323,7 +323,7 @@ public: // return false so the calling thread exits while loop return false; } - inline void abort() { + inline virtual void interrupt() override { mAbortCalled = true; if (mIpcRecver != nullptr) { mIpcRecver->abort(); @@ -335,8 +335,7 @@ bool LocIpc::startNonBlockingListening(unique_ptr& ipcRecver) { if (ipcRecver != nullptr && ipcRecver->isRecvable()) { std::string threadName("LocIpc-"); threadName.append(ipcRecver->getName()); - mRunnable = new LocIpcRunnable(*this, ipcRecver); - return mThread.start(threadName.c_str(), mRunnable); + return mThread.start(threadName.c_str(), make_shared(*this, ipcRecver)); } else { LOC_LOGe("ipcRecver is null OR ipcRecver->recvable() is fasle"); return false; @@ -356,10 +355,6 @@ bool LocIpc::startBlockingListening(LocIpcRecver& ipcRecver) { } void LocIpc::stopNonBlockingListening() { - if (mRunnable) { - mRunnable->abort(); - mRunnable = nullptr; - } mThread.stop(); } diff --git a/gps/utils/LocIpc.h b/gps/utils/LocIpc.h index 1cad2c3..b2586e6 100644 --- a/gps/utils/LocIpc.h +++ b/gps/utils/LocIpc.h @@ -45,7 +45,6 @@ namespace loc_util { class LocIpcRecver; class LocIpcSender; -class LocIpcRunnable; class ILocIpcListener { protected: @@ -89,7 +88,7 @@ public: class LocIpc { public: - inline LocIpc() : mRunnable(nullptr) {} + inline LocIpc() = default; inline virtual ~LocIpc() { stopNonBlockingListening(); } @@ -151,7 +150,6 @@ public: private: LocThread mThread; - LocIpcRunnable *mRunnable; }; /* this is only when client needs to implement Sender / Recver that are not already provided by diff --git a/gps/utils/LocSharedLock.h b/gps/utils/LocSharedLock.h index a7af35e..1ef2c57 100644 --- a/gps/utils/LocSharedLock.h +++ b/gps/utils/LocSharedLock.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015, 2020 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 @@ -49,9 +49,11 @@ 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 + +namespace loc_util { + +// 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, @@ -74,4 +76,6 @@ public: inline void unlock() { pthread_mutex_unlock(&mMutex); } }; +} //namespace loc_util + #endif //__LOC_SHARED_LOCK__ diff --git a/gps/utils/LocThread.cpp b/gps/utils/LocThread.cpp index 568a6bb..3cac1f9 100644 --- a/gps/utils/LocThread.cpp +++ b/gps/utils/LocThread.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015, 2020 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,194 +26,75 @@ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ +#include #include #include -#include +#include +#include #include +using std::weak_ptr; +using std::shared_ptr; +using std::thread; +using std::string; + +namespace loc_util { + class LocThreadDelegate { - LocRunnable* mRunnable; - bool mJoinable; - pthread_t mThandle; - pthread_mutex_t mMutex; - int mRefCount; - ~LocThreadDelegate(); - LocThreadDelegate(LocThread::tCreate creator, const char* threadName, - LocRunnable* runnable, bool joinable); - void destroy(); + static const char defaultThreadName[]; + weak_ptr mRunnable; + thread mThread; + LocThreadDelegate(const string tName, shared_ptr r); public: - static LocThreadDelegate* create(LocThread::tCreate creator, - const char* threadName, LocRunnable* runnable, bool joinable); - void stop(); - // bye() is for the parent thread to go away. if joinable, - // parent must stop the spawned thread, join, and then - // destroy(); if detached, the parent can go straight - // ahead to destroy() - inline void bye() { mJoinable ? stop() : destroy(); } - inline bool isRunning() { return (NULL != mRunnable); } - static void* threadMain(void* arg); + ~LocThreadDelegate() { + shared_ptr runnable = mRunnable.lock(); + if (nullptr != runnable) { + runnable->interrupt(); + } + } + inline static LocThreadDelegate* create(const char* tName, shared_ptr runnable); }; -// it is important to note that internal members must be -// initialized to values as if pthread_create succeeds. -// This is to avoid the race condition between the threads, -// once the thread is created, some of these values will -// be check in the spawned thread, and must set correctly -// then and there. -// However, upon pthread_create failure, the data members -// must be set to indicate failure, e.g. mRunnable, and -// threashold approprietly for destroy(), e.g. mRefCount. -LocThreadDelegate::LocThreadDelegate(LocThread::tCreate creator, - const char* threadName, LocRunnable* runnable, bool joinable) : - mRunnable(runnable), mJoinable(joinable), mThandle((pthread_t)NULL), - mMutex(PTHREAD_MUTEX_INITIALIZER), mRefCount(2) { +const char LocThreadDelegate::defaultThreadName[] = "LocThread"; - // set up thread name, if nothing is passed in - if (!threadName) { - threadName = "LocThread"; - } +LocThreadDelegate* LocThreadDelegate::create(const char* tName, shared_ptr runnable) { + LocThreadDelegate* threadDelegate = nullptr; - // create the thread here, then if successful - // and a name is given, we set the thread name - if (creator) { - mThandle = creator(threadName, threadMain, this); - } else if (pthread_create(&mThandle, NULL, threadMain, this)) { - // pthread_create() failed - mThandle = (pthread_t)NULL; - } + if (nullptr != runnable) { + if (!tName) { + tName = defaultThreadName; + } - if (mThandle) { - // set thread name char lname[16]; - int len = (sizeof(lname) > (strlen(threadName) + 1)) ? - (strlen(threadName)):(sizeof(lname) - 1); - memcpy(lname, threadName, len); + auto nameSize = strlen(tName) + 1; + int len = std::min(sizeof(lname), nameSize) - 1; + memcpy(lname, tName, len); lname[len] = 0; - // set the thread name here - pthread_setname_np(mThandle, lname); - // detach, if not joinable - if (!joinable) { - pthread_detach(mThandle); - } - } else { - // must set these values upon failure - mRunnable = NULL; - mJoinable = false; - mRefCount = 1; - } -} - -inline -LocThreadDelegate::~LocThreadDelegate() { - // at this point nothing should need done any more -} - -// factory method so that we could return NULL upon failure -LocThreadDelegate* LocThreadDelegate::create(LocThread::tCreate creator, - const char* threadName, LocRunnable* runnable, bool joinable) { - LocThreadDelegate* thread = NULL; - if (runnable) { - thread = new LocThreadDelegate(creator, threadName, runnable, joinable); - if (thread && !thread->isRunning()) { - thread->destroy(); - thread = NULL; - } + threadDelegate = new LocThreadDelegate(lname, runnable); } - return thread; + return threadDelegate; } -// The order is importang -// NULLing mRunnalbe stops the while loop in threadMain() -// join() if mJoinble must come before destroy() call, as -// the obj must remain alive at this time so that mThandle -// remains valud. -void LocThreadDelegate::stop() { - // mRunnable and mJoinable are reset on different triggers. - // mRunnable may get nulled on the spawned thread's way out; - // or here. - // mJouinable (if ever been true) gets falsed when client - // thread triggers stop, with either a stop() - // call or the client releases thread obj handle. - if (mRunnable) { - mRunnable = NULL; - } - if (mJoinable) { - mJoinable = false; - pthread_join(mThandle, NULL); - } - // call destroy() to possibly delete the obj - destroy(); -} - -// method for clients to call to release the obj -// when it is a detached thread, the client thread -// and the spawned thread can both try to destroy() -// asynchronously. And we delete this obj when -// mRefCount becomes 0. -void LocThreadDelegate::destroy() { - // else case shouldn't happen, unless there is a - // leaking obj. But only our code here has such - // obj, so if we test our code well, else case - // will never happen - if (mRefCount > 0) { - // we need a flag on the stack - bool callDelete = false; - - // critical section between threads - pthread_mutex_lock(&mMutex); - // last destroy() call - callDelete = (1 == mRefCount--); - pthread_mutex_unlock(&mMutex); - - // upon last destroy() call we delete this obj - if (callDelete) { - delete this; - } - } -} - -void* LocThreadDelegate::threadMain(void* arg) { - LocThreadDelegate* locThread = (LocThreadDelegate*)(arg); - - if (locThread) { - LocRunnable* runnable = locThread->mRunnable; - - if (runnable) { - if (locThread->isRunning()) { +LocThreadDelegate::LocThreadDelegate(const string tName, shared_ptr runnable) : + mRunnable(runnable), + mThread([tName, runnable] { + prctl(PR_SET_NAME, tName.c_str(), 0, 0, 0); runnable->prerun(); - } - - while (locThread->isRunning() && runnable->run()); - - if (locThread->isRunning()) { + while (runnable->run()); runnable->postrun(); - } + }) { - // at this time, locThread->mRunnable may or may not be NULL - // NULL it just to be safe and clean, as we want the field - // in the released memory slot to be NULL. - locThread->mRunnable = NULL; - delete runnable; - } - locThread->destroy(); - } - - return NULL; + mThread.detach(); } -LocThread::~LocThread() { - if (mThread) { - mThread->bye(); - mThread = NULL; - } -} -bool LocThread::start(tCreate creator, const char* threadName, LocRunnable* runnable, bool joinable) { + +bool LocThread::start(const char* tName, shared_ptr runnable) { bool success = false; if (!mThread) { - mThread = LocThreadDelegate::create(creator, threadName, runnable, joinable); + mThread = LocThreadDelegate::create(tName, runnable); // true only if thread is created successfully success = (NULL != mThread); } @@ -221,46 +102,10 @@ bool LocThread::start(tCreate creator, const char* threadName, LocRunnable* runn } void LocThread::stop() { - if (mThread) { - mThread->stop(); - mThread = NULL; + if (nullptr != mThread) { + delete mThread; + mThread = nullptr; } } -#ifdef __LOC_DEBUG__ - -#include -#include -#include - -class LocRunnableTest1 : public LocRunnable { - int mID; -public: - LocRunnableTest1(int id) : LocRunnable(), mID(id) {} - virtual bool run() { - printf("LocRunnableTest1: %d\n", mID++); - sleep(1); - return true; - } -}; - -// on linux command line: -// compile: g++ -D__LOC_HOST_DEBUG__ -D__LOC_DEBUG__ -g -std=c++0x -I. -I../../../../vendor/qcom/proprietary/gps-internal/unit-tests/fakes_for_host -I../../../../system/core/include -lpthread LocThread.cpp -// test detached thread: valgrind ./a.out 0 -// test joinable thread: valgrind ./a.out 1 -int main(int argc, char** argv) { - LocRunnableTest1 test(10); - - LocThread thread; - thread.start("LocThreadTest", test, atoi(argv[1])); - - sleep(10); - - thread.stop(); - - sleep(5); - - return 0; -} - -#endif +} // loc_util diff --git a/gps/utils/LocThread.h b/gps/utils/LocThread.h index 2a65d8f..c7ece87 100644 --- a/gps/utils/LocThread.h +++ b/gps/utils/LocThread.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015, 2020 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,14 +30,18 @@ #define __LOC_THREAD__ #include -#include +#include + +using std::shared_ptr; + +namespace loc_util { // abstract class to be implemented by client to provide a runnable class // which gets scheduled by LocThread class LocRunnable { public: - inline LocRunnable() {} - inline virtual ~LocRunnable() {} + inline LocRunnable() = default; + inline virtual ~LocRunnable() = default; // The method to be implemented by thread clients // and be scheduled by LocThread @@ -52,6 +56,10 @@ public: // The method to be run after thread loop (conditionally repeatedly) // calls run() inline virtual void postrun() {} + + // The method to wake up the potential blocking thread + // no op if not applicable + inline virtual void interrupt() = 0; }; // opaque class to provide service implementation. @@ -63,12 +71,11 @@ class LocThread { LocThreadDelegate* mThread; public: inline LocThread() : mThread(NULL) {} - virtual ~LocThread(); + inline virtual ~LocThread() { stop(); } - typedef pthread_t (*tCreate)(const char* name, void* (*start)(void*), void* arg); // client starts thread with a runnable, which implements // the logics to fun in the created thread context. - // The thread could be either joinable or detached. + // The thread is always detached. // runnable is an obj managed by client. Client creates and // frees it (but must be after stop() is called, or // this LocThread obj is deleted). @@ -76,17 +83,13 @@ public: // returns true. Else it is client's responsibility // to delete the object // Returns 0 if success; false if failure. - bool start(tCreate creator, const char* threadName, LocRunnable* runnable, bool joinable = true); - inline bool start(const char* threadName, LocRunnable* runnable, bool joinable = true) { - return start(NULL, threadName, runnable, joinable); - } + bool start(const char* threadName, shared_ptr runnable); - // NOTE: if this is a joinable thread, this stop may block - // for a while until the thread is joined. void stop(); // thread status check inline bool isRunning() { return NULL != mThread; } }; +} // loc_util #endif //__LOC_THREAD__ diff --git a/gps/utils/LocTimer.cpp b/gps/utils/LocTimer.cpp index dfec810..915cf54 100644 --- a/gps/utils/LocTimer.cpp +++ b/gps/utils/LocTimer.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015, 2020 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 @@ -48,6 +48,8 @@ #define CLOCK_BOOTTIME_ALARM CLOCK_MONOTONIC #endif +namespace loc_util { + /* There are implementations of 5 classes in this file: LocTimer, LocTimerDelegate, LocTimerContainer, LocTimerPollTask, LocTimerWrapper @@ -129,6 +131,21 @@ public: void expire(); }; +class TimerRunnable : public LocRunnable { + const int mFd; +public: + inline TimerRunnable(const int fd) : mFd(fd) {} + // The method to be implemented by thread clients + // and be scheduled by LocThread + // This method will be repeated called until it returns false; or + // until thread is stopped. + virtual bool run() override; + + // The method to wake up the potential blocking thread + // no op if not applicable + inline virtual void interrupt() { close(mFd); } +}; + // This class implements the polling thread that epolls imer / alarm fds. // The LocRunnable::run() contains the actual polling. The other methods // will be run in the caller's thread context to add / remove timer / alarm @@ -140,19 +157,17 @@ public: // having 1 fd per container of timer / alarm is such that, we may not need // to make a system call each time a timer / alarm is added / removed, unless // that changes the "soonest" time out of that of all the timers / alarms. -class LocTimerPollTask : public LocRunnable { +class LocTimerPollTask { // the epoll fd const int mFd; - // the thread that calls run() method - LocThread* mThread; - friend class LocThreadDelegate; - // dtor - ~LocTimerPollTask(); + // the thread that calls TimerRunnable::run() method, where + // epoll_wait() is blocking and waiting for events.. + LocThread mThread; public: // ctor LocTimerPollTask(); - // this obj will be deleted once thread is deleted - void destroy(); + // dtor + ~LocTimerPollTask() = default; // add a container of timers. Each contain has a unique device fd, i.e. // either timer or alarm fd, and a heap of timers / alarms. It is expected // that container would have written to the device fd with the soonest @@ -164,9 +179,6 @@ public: // remove a fd that is assciated with a container. The expectation is that // the atual timer would have been removed from the container. void removePoll(LocTimerContainer& timerContainer); - // The polling thread context will call this method. This is where - // epoll_wait() is blocking and waiting for events.. - virtual bool run(); }; // Internal class of timer obj. It gets born when client calls LocTimer::start(); @@ -257,7 +269,7 @@ LocTimerContainer* LocTimerContainer::get(bool wakeOnExpire) { MsgTask* LocTimerContainer::getMsgTaskLocked() { // it is cheap to check pointer first than locking mutext unconditionally if (!mMsgTask) { - mMsgTask = new MsgTask("LocTimerMsgTask", false); + mMsgTask = new MsgTask("LocTimerMsgTask"); } return mMsgTask; } @@ -313,7 +325,6 @@ inline void LocTimerContainer::add(LocTimerDelegate& timer) { struct MsgTimerPush : public LocMsg { LocTimerContainer* mTimerContainer; - LocHeapNode* mTree; LocTimerDelegate* mTimer; inline MsgTimerPush(LocTimerContainer& container, LocTimerDelegate& timer) : LocMsg(), mTimerContainer(&container), mTimer(&timer) {} @@ -398,32 +409,12 @@ LocTimerDelegate* LocTimerContainer::popIfOutRanks(LocTimerDelegate& timer) { inline LocTimerPollTask::LocTimerPollTask() - : mFd(epoll_create(2)), mThread(new LocThread()) { + : mFd(epoll_create(2)), mThread() { // before a next call returens, a thread will be created. The run() method // could already be running in parallel. Also, since each of the objs // creates a thread, the container will make sure that there will be only // one of such obj for our timer implementation. - if (!mThread->start("LocTimerPollTask", this)) { - delete mThread; - mThread = NULL; - } -} - -inline -LocTimerPollTask::~LocTimerPollTask() { - // when fs is closed, epoll_wait() should fail run() should return false - // and the spawned thread should exit. - close(mFd); -} - -void LocTimerPollTask::destroy() { - if (mThread) { - LocThread* thread = mThread; - mThread = NULL; - delete thread; - } else { - delete this; - } + mThread.start("LocTimerPollTask", std::make_shared(mFd)); } void LocTimerPollTask::addPoll(LocTimerContainer& timerContainer) { @@ -447,7 +438,7 @@ void LocTimerPollTask::removePoll(LocTimerContainer& timerContainer) { // The polling thread context will call this method. If run() method needs to // be repetitvely called, it must return true from the previous call. -bool LocTimerPollTask::run() { +bool TimerRunnable::run() { struct epoll_event ev[2]; // we have max 2 descriptors to poll from @@ -621,6 +612,14 @@ public: } }; +} // namespace loc_util + +////////////////////////////////////////////////////////////////////////// +// This section below wraps for the C style APIs +////////////////////////////////////////////////////////////////////////// + +using loc_util::LocTimerWrapper; + pthread_mutex_t LocTimerWrapper::mMutex = PTHREAD_MUTEX_INITIALIZER; void* loc_timer_start(uint64_t msec, loc_timer_callback cb_func, @@ -647,107 +646,3 @@ void loc_timer_stop(void*& handle) handle = NULL; } } - -////////////////////////////////////////////////////////////////////////// -// This section above wraps for the C style APIs -////////////////////////////////////////////////////////////////////////// - -#ifdef __LOC_DEBUG__ - -double getDeltaSeconds(struct timespec from, struct timespec to) { - return (double)to.tv_sec + (double)to.tv_nsec / 1000000000 - - from.tv_sec - (double)from.tv_nsec / 1000000000; -} - -struct timespec getNow() { - struct timespec now; - clock_gettime(CLOCK_BOOTTIME, &now); - return now; -} - -class LocTimerTest : public LocTimer, public LocRankable { - int mTimeOut; - const struct timespec mTimeOfBirth; - inline struct timespec getTimerWrapper(int timeout) { - struct timespec now; - clock_gettime(CLOCK_BOOTTIME, &now); - now.tv_sec += timeout; - return now; - } -public: - inline LocTimerTest(int timeout) : LocTimer(), LocRankable(), - mTimeOut(timeout), mTimeOfBirth(getTimerWrapper(0)) {} - inline virtual int ranks(LocRankable& rankable) { - LocTimerTest* timer = dynamic_cast(&rankable); - return timer->mTimeOut - mTimeOut; - } - inline virtual void timeOutCallback() { - printf("timeOutCallback() - "); - deviation(); - } - double deviation() { - struct timespec now = getTimerWrapper(0); - double delta = getDeltaSeconds(mTimeOfBirth, now); - printf("%lf: %lf\n", delta, delta * 100 / mTimeOut); - return delta / mTimeOut; - } -}; - -// For Linux command line testing: -// compilation: -// g++ -D__LOC_HOST_DEBUG__ -D__LOC_DEBUG__ -g -I. -I../../../../system/core/include -o LocHeap.o LocHeap.cpp -// g++ -D__LOC_HOST_DEBUG__ -D__LOC_DEBUG__ -g -std=c++0x -I. -I../../../../system/core/include -lpthread -o LocThread.o LocThread.cpp -// g++ -D__LOC_HOST_DEBUG__ -D__LOC_DEBUG__ -g -I. -I../../../../system/core/include -o LocTimer.o LocTimer.cpp -int main(int argc, char** argv) { - struct timespec timeOfStart=getNow(); - srand(time(NULL)); - int tries = atoi(argv[1]); - int checks = tries >> 3; - LocTimerTest** timerArray = new LocTimerTest*[tries]; - memset(timerArray, NULL, tries); - - for (int i = 0; i < tries; i++) { - int r = rand() % tries; - LocTimerTest* timer = new LocTimerTest(r); - if (timerArray[r]) { - if (!timer->stop()) { - printf("%lf:\n", getDeltaSeconds(timeOfStart, getNow())); - printf("ERRER: %dth timer, id %d, not running when it should be\n", i, r); - exit(0); - } else { - printf("stop() - %d\n", r); - delete timer; - timerArray[r] = NULL; - } - } else { - if (!timer->start(r, false)) { - printf("%lf:\n", getDeltaSeconds(timeOfStart, getNow())); - printf("ERRER: %dth timer, id %d, running when it should not be\n", i, r); - exit(0); - } else { - printf("stop() - %d\n", r); - timerArray[r] = timer; - } - } - } - - for (int i = 0; i < tries; i++) { - if (timerArray[i]) { - if (!timerArray[i]->stop()) { - printf("%lf:\n", getDeltaSeconds(timeOfStart, getNow())); - printf("ERRER: %dth timer, not running when it should be\n", i); - exit(0); - } else { - printf("stop() - %d\n", i); - delete timerArray[i]; - timerArray[i] = NULL; - } - } - } - - delete[] timerArray; - - return 0; -} - -#endif diff --git a/gps/utils/LocTimer.h b/gps/utils/LocTimer.h index abc7f64..c883de2 100644 --- a/gps/utils/LocTimer.h +++ b/gps/utils/LocTimer.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015, 2020 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 @@ -33,6 +33,8 @@ #include #include +namespace loc_util { + // opaque class to provide service implementation. class LocTimerDelegate; class LocSharedLock; @@ -71,4 +73,6 @@ public: virtual void timeOutCallback() = 0; }; +} // namespace loc_util + #endif //__LOC_DELAY_H__ diff --git a/gps/utils/MsgTask.cpp b/gps/utils/MsgTask.cpp index 0a978ed..6ef689a 100644 --- a/gps/utils/MsgTask.cpp +++ b/gps/utils/MsgTask.cpp @@ -36,41 +36,33 @@ #include #include +namespace loc_util { + +class MTRunnable : public LocRunnable { + const void* mQ; +public: + inline MTRunnable(const void* q) : mQ(q) {} + virtual ~MTRunnable(); + // Overrides of LocRunnable methods + // This method will be repeated called until it returns false; or + // until thread is stopped. + virtual bool run() override; + + // The method to be run before thread loop (conditionally repeatedly) + // calls run() + virtual void prerun() override; + + // to interrupt the run() method and come out of that + virtual void interrupt() override; +}; + static void LocMsgDestroy(void* msg) { delete (LocMsg*)msg; } -MsgTask::MsgTask(LocThread::tCreate tCreator, - const char* threadName, bool joinable) : - mQ(msg_q_init2()), mThread(new LocThread()) { - if (!mThread->start(tCreator, threadName, this, joinable)) { - delete mThread; - mThread = NULL; - } -} - -MsgTask::MsgTask(const char* threadName, bool joinable) : - mQ(msg_q_init2()), mThread(new LocThread()) { - if (!mThread->start(threadName, this, joinable)) { - delete mThread; - mThread = NULL; - } -} - -MsgTask::~MsgTask() { - msg_q_flush((void*)mQ); - msg_q_destroy((void**)&mQ); -} - -void MsgTask::destroy() { - LocThread* thread = mThread; - msg_q_unblock((void*)mQ); - if (thread) { - mThread = NULL; - delete thread; - } else { - delete this; - } +MsgTask::MsgTask(const char* threadName) : + mQ(msg_q_init2()), mThread() { + mThread.start(threadName, std::make_shared(mQ)); } void MsgTask::sendMsg(const LocMsg* msg) const { @@ -82,12 +74,27 @@ void MsgTask::sendMsg(const LocMsg* msg) const { } } -void MsgTask::prerun() { +void MsgTask::sendMsg(const std::function runnable) const { + struct RunMsg : public LocMsg { + const std::function mRunnable; + public: + inline RunMsg(const std::function runnable) : mRunnable(runnable) {} + ~RunMsg() = default; + inline virtual void proc() const override { mRunnable(); } + }; + sendMsg(new RunMsg(runnable)); +} + +void MTRunnable::interrupt() { + msg_q_unblock((void*)mQ); +} + +void MTRunnable::prerun() { // make sure we do not run in background scheduling group set_sched_policy(gettid(), SP_FOREGROUND); } -bool MsgTask::run() { +bool MTRunnable::run() { LocMsg* msg; msq_q_err_type result = msg_q_rcv((void*)mQ, (void **)&msg); if (eMSG_Q_SUCCESS != result) { @@ -104,3 +111,10 @@ bool MsgTask::run() { return true; } + +MTRunnable::~MTRunnable() { + msg_q_flush((void*)mQ); + msg_q_destroy((void**)&mQ); +} + +} // namespace loc_util diff --git a/gps/utils/MsgTask.h b/gps/utils/MsgTask.h index 9eb1f56..a8cce9e 100644 --- a/gps/utils/MsgTask.h +++ b/gps/utils/MsgTask.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2013,2015 The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2013, 2015, 2020 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 @@ -29,8 +29,11 @@ #ifndef __MSG_TASK__ #define __MSG_TASK__ +#include #include +namespace loc_util { + struct LocMsg { inline LocMsg() {} inline virtual ~LocMsg() {} @@ -38,30 +41,16 @@ struct LocMsg { inline virtual void log() const {} }; -class MsgTask : public LocRunnable { +class MsgTask { const void* mQ; - LocThread* mThread; - friend class LocThreadDelegate; -protected: - virtual ~MsgTask(); + LocThread mThread; public: - MsgTask(LocThread::tCreate tCreator, const char* threadName = NULL, bool joinable = true); - MsgTask(const char* threadName = NULL, bool joinable = true); - // this obj will be deleted once thread is deleted - void destroy(); + ~MsgTask() = default; + MsgTask(const char* threadName = NULL); void sendMsg(const LocMsg* msg) const; - // Overrides of LocRunnable methods - // This method will be repeated called until it returns false; or - // until thread is stopped. - virtual bool run(); - - // The method to be run before thread loop (conditionally repeatedly) - // calls run() - virtual void prerun(); - - // The method to be run after thread loop (conditionally repeatedly) - // calls run() - inline virtual void postrun() {} + void sendMsg(const std::function runnable) const; }; +} // + #endif //__MSG_TASK__ diff --git a/gps/utils/gps_extended_c.h b/gps/utils/gps_extended_c.h index eb27e39..f368975 100644 --- a/gps/utils/gps_extended_c.h +++ b/gps/utils/gps_extended_c.h @@ -115,6 +115,9 @@ typedef uint32_t LocPosTechMask; #define LOC_POS_TECH_MASK_AFLT ((LocPosTechMask)0x00000040) #define LOC_POS_TECH_MASK_HYBRID ((LocPosTechMask)0x00000080) #define LOC_POS_TECH_MASK_PPE ((LocPosTechMask)0x00000100) +#define LOC_POS_TECH_MASK_VEH ((LocPosTechMask)0x00000200) +#define LOC_POS_TECH_MASK_VIS ((LocPosTechMask)0x00000400) + enum loc_registration_mask_status { LOC_REGISTRATION_MASK_ENABLED, @@ -412,8 +415,12 @@ typedef uint64_t GpsLocationExtendedFlags; #define GPS_LOCATION_EXTENDED_HAS_LLA_VRP_BASED 0x200000000000 /** GpsLocationExtended has the velocityVRPased. */ #define GPS_LOCATION_EXTENDED_HAS_ENU_VELOCITY_LLA_VRP_BASED 0x400000000000 +/** GpsLocationExtended has upperTriangleFullCovMatrix. */ #define GPS_LOCATION_EXTENDED_HAS_UPPER_TRIANGLE_FULL_COV_MATRIX 0x800000000000 +/** GpsLocationExtended has drSolutionStatusMask. */ #define GPS_LOCATION_EXTENDED_HAS_DR_SOLUTION_STATUS_MASK 0x1000000000000 +/** GpsLocationExtended has altitudeAssumed. */ +#define GPS_LOCATION_EXTENDED_HAS_ALTITUDE_ASSUMED 0x2000000000000 typedef uint32_t LocNavSolutionMask; /* Bitmask to specify whether SBAS ionospheric correction is used */ @@ -479,6 +486,7 @@ typedef uint32_t GnssAdditionalSystemInfoMask; #define GAL_SV_PRN_MAX 336 #define NAVIC_SV_PRN_MIN 401 #define NAVIC_SV_PRN_MAX 414 +#define GLO_SV_PRN_SLOT_UNKNOWN 255 /* Checking svIdOneBase can be set to the corresponding bit in mask */ #define svFitsMask(mask, svIdOneBase) \ @@ -488,6 +496,7 @@ typedef uint32_t GnssAdditionalSystemInfoMask; if (svFitsMask(mask, svIdOneBase)) mask |= (1ULL << ((svIdOneBase) - 1)) #define isValInRangeInclusive(val, min, max) ((val) >= (min) && (val) <= (max)) +#define isGloSlotUnknown(val) ((val) == GLO_SV_PRN_SLOT_UNKNOWN) typedef enum { LOC_RELIABILITY_NOT_SET = 0, @@ -864,14 +873,14 @@ typedef struct { */ float upperTriangleFullCovMatrix[COV_MATRIX_SIZE]; DrSolutionStatusMask drSolutionStatusMask; + /** When this field is valid, it will indicates whether altitude + * is assumed or calculated. + * false: Altitude is calculated. + * true: Altitude is assumed; there may not be enough + * satellites to determine the precise altitude. */ + bool altitudeAssumed; } GpsLocationExtended; -enum loc_sess_status { - LOC_SESS_SUCCESS, - LOC_SESS_INTERMEDIATE, - LOC_SESS_FAILURE -}; - // struct that contains complete position info from engine typedef struct { UlpLocation location; @@ -912,6 +921,7 @@ typedef uint32_t NmeaSentenceTypesMask; #define LOC_NMEA_MASK_GQGSV_V02 ((NmeaSentenceTypesMask)0x10000000) /**< Enable GQGSV type */ #define LOC_NMEA_MASK_GIGSV_V02 ((NmeaSentenceTypesMask)0x20000000) /**< Enable GIGSV type */ #define LOC_NMEA_MASK_GNDTM_V02 ((NmeaSentenceTypesMask)0x40000000) /**< Enable GNDTM type */ +#define LOC_NMEA_MASK_TAGBLOCK_V02 ((NmeaSentenceTypesMask)0x80000000) /**< Enable TAGBLOCK type */ // all bitmasks of general supported NMEA sentenses - debug is not part of this @@ -1006,41 +1016,42 @@ enum loc_api_adapter_event_index { 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_LATENCY_INFORMATION_REPORT, // Latency information report LOC_API_ADAPTER_EVENT_MAX }; -#define LOC_API_ADAPTER_BIT_PARSED_POSITION_REPORT (1<param_ptr, config_value->param_str_value, - LOC_MAX_PARAM_STRING); + string_len); } /* Log INI values */ LOC_LOGD("%s: PARAM %s = %s", __FUNCTION__, @@ -233,7 +235,8 @@ SIDE EFFECTS N/A ===========================================================================*/ int loc_fill_conf_item(char* input_buf, - const loc_param_s_type* config_table, uint32_t table_length) + const loc_param_s_type* config_table, + uint32_t table_length, uint16_t string_len = LOC_MAX_PARAM_STRING) { int ret = 0; @@ -270,7 +273,7 @@ int loc_fill_conf_item(char* input_buf, for(uint32_t i = 0; NULL != config_table && i < table_length; i++) { - if(!loc_set_config_entry(&config_table[i], &config_value)) { + if(!loc_set_config_entry(&config_table[i], &config_value, string_len)) { ret += 1; } } @@ -282,7 +285,7 @@ int loc_fill_conf_item(char* input_buf, } /*=========================================================================== -FUNCTION loc_read_conf_r (repetitive) +FUNCTION loc_read_conf_r_long (repetitive) DESCRIPTION Reads the specified configuration file and sets defined values based on @@ -310,11 +313,13 @@ RETURN VALUE SIDE EFFECTS N/A ===========================================================================*/ -int loc_read_conf_r(FILE *conf_fp, const loc_param_s_type* config_table, uint32_t table_length) +int loc_read_conf_r_long(FILE *conf_fp, const loc_param_s_type* config_table, + uint32_t table_length, uint16_t string_len) { int ret=0; - + char input_buf[string_len]; /* declare a char array */ unsigned int num_params=table_length; + if(conf_fp == NULL) { LOC_LOGE("%s:%d]: ERROR: File pointer is NULL\n", __func__, __LINE__); ret = -1; @@ -330,17 +335,15 @@ int loc_read_conf_r(FILE *conf_fp, const loc_param_s_type* config_table, uint32_ } } - char input_buf[LOC_MAX_PARAM_LINE]; /* declare a char array */ - LOC_LOGD("%s:%d]: num_params: %d\n", __func__, __LINE__, num_params); while(num_params) { - if(!fgets(input_buf, LOC_MAX_PARAM_LINE, conf_fp)) { + if(!fgets(input_buf, string_len, conf_fp)) { LOC_LOGD("%s:%d]: fgets returned NULL\n", __func__, __LINE__); break; } - num_params -= loc_fill_conf_item(input_buf, config_table, table_length); + num_params -= loc_fill_conf_item(input_buf, config_table, table_length, string_len); } err: @@ -348,7 +351,7 @@ err: } /*=========================================================================== -FUNCTION loc_udpate_conf +FUNCTION loc_udpate_conf_long DESCRIPTION Parses the passed in buffer for configuration items, and update the table @@ -373,8 +376,9 @@ RETURN VALUE SIDE EFFECTS N/A ===========================================================================*/ -int loc_update_conf(const char* conf_data, int32_t length, - const loc_param_s_type* config_table, uint32_t table_length) +int loc_update_conf_long(const char* conf_data, int32_t length, + const loc_param_s_type* config_table, + uint32_t table_length, uint16_t string_len) { int ret = -1; @@ -397,7 +401,8 @@ int loc_update_conf(const char* conf_data, int32_t length, LOC_LOGD("%s:%d]: num_params: %d\n", __func__, __LINE__, num_params); while(num_params && input_buf) { ret++; - num_params -= loc_fill_conf_item(input_buf, config_table, table_length); + num_params -= + loc_fill_conf_item(input_buf, config_table, table_length, string_len); input_buf = strtok_r(NULL, "\n", &saveptr); } free(conf_copy); @@ -408,7 +413,7 @@ int loc_update_conf(const char* conf_data, int32_t length, } /*=========================================================================== -FUNCTION loc_read_conf +FUNCTION loc_read_conf_long DESCRIPTION Reads the specified configuration file and sets defined values based on @@ -429,8 +434,8 @@ RETURN VALUE SIDE EFFECTS N/A ===========================================================================*/ -void loc_read_conf(const char* conf_file_name, const loc_param_s_type* config_table, - uint32_t table_length) +void loc_read_conf_long(const char* conf_file_name, const loc_param_s_type* config_table, + uint32_t table_length, uint16_t string_len) { FILE *conf_fp = NULL; @@ -439,15 +444,16 @@ void loc_read_conf(const char* conf_file_name, const loc_param_s_type* config_ta { LOC_LOGD("%s: using %s", __FUNCTION__, conf_file_name); if(table_length && config_table) { - loc_read_conf_r(conf_fp, config_table, table_length); + loc_read_conf_r_long(conf_fp, config_table, table_length, string_len); rewind(conf_fp); } - loc_read_conf_r(conf_fp, loc_param_table, loc_param_num); + loc_read_conf_r_long(conf_fp, loc_param_table, loc_param_num, string_len); fclose(conf_fp); } /* Initialize logging mechanism with parsed data */ loc_logger_init(DEBUG_LEVEL, TIMESTAMP); log_buffer_init(sLogBufferEnabled); + log_tag_level_map_init(); } /*============================================================================= diff --git a/gps/utils/loc_cfg.h b/gps/utils/loc_cfg.h index ea5a97a..e87d632 100644 --- a/gps/utils/loc_cfg.h +++ b/gps/utils/loc_cfg.h @@ -65,6 +65,10 @@ #define UTIL_READ_CONF(filename, config_table) \ loc_read_conf((filename), (&config_table[0]), sizeof(config_table) / sizeof(config_table[0])) +#define UTIL_READ_CONF_LONG(filename, config_table, rec_len) \ + loc_read_conf_long((filename), (&config_table[0]), \ + sizeof(config_table) / sizeof(config_table[0]), (rec_len)) + /*============================================================================= * * MODULE TYPE DECLARATION @@ -115,13 +119,30 @@ extern "C" { *============================================================================*/ bool isVendorEnhanced(); void setVendorEnhanced(bool vendorEnhanced); -void loc_read_conf(const char* conf_file_name, - const loc_param_s_type* config_table, - uint32_t table_length); -int loc_read_conf_r(FILE *conf_fp, const loc_param_s_type* config_table, - uint32_t table_length); -int loc_update_conf(const char* conf_data, int32_t length, - const loc_param_s_type* config_table, uint32_t table_length); +void loc_read_conf_long(const char* conf_file_name, + const loc_param_s_type* config_table, + uint32_t table_length, uint16_t string_len); +int loc_read_conf_r_long(FILE *conf_fp, const loc_param_s_type* config_table, + uint32_t table_length, uint16_t string_len); +int loc_update_conf_long(const char* conf_data, int32_t length, + const loc_param_s_type* config_table, uint32_t table_length, + uint16_t string_len); + +inline void loc_read_conf(const char* conf_file_name, + const loc_param_s_type* config_table, uint32_t table_length) { + loc_read_conf_long(conf_file_name, config_table, table_length, LOC_MAX_PARAM_STRING); +} + +inline int loc_read_conf_r(FILE *conf_fp, const loc_param_s_type* config_table, + uint32_t table_length) { + return (loc_read_conf_r_long(conf_fp, config_table, table_length, LOC_MAX_PARAM_STRING)); +} + +inline int loc_update_conf(const char* conf_data, int32_t length, + const loc_param_s_type* config_table, uint32_t table_length) { + return (loc_update_conf_long( + conf_data, length, config_table, table_length, LOC_MAX_PARAM_STRING)); +} // Below are the location conf file paths extern const char LOC_PATH_GPS_CONF[]; diff --git a/gps/utils/loc_log.cpp b/gps/utils/loc_log.cpp index 56ae116..2110683 100644 --- a/gps/utils/loc_log.cpp +++ b/gps/utils/loc_log.cpp @@ -38,8 +38,13 @@ #include "msg_q.h" #include #include "LogBuffer.h" - +#include +#include +#include +#include +#include #define BUFFER_SIZE 120 +#define LOG_TAG_LEVEL_CONF_FILE_PATH "/data/vendor/location/gps.prop" // Logging Improvements const char *loc_logger_boolStr[]={"False","True"}; @@ -59,6 +64,10 @@ const string gUnknownStr = "UNKNOWN"; /* Logging Mechanism */ loc_logger_s_type loc_logger; +/* tag base logging control map*/ +static std::unordered_map tag_level_map; +static bool tag_map_inited = false; + /* returns the least signification bit that is set in the mask Param mask - bit mask. @@ -219,3 +228,55 @@ void log_buffer_insert(char *str, unsigned long buf_size, int level) string ss = str; loc_util::LogBuffer::getInstance()->append(ss, level, elapsedTime); } + +void log_tag_level_map_init() +{ + if (tag_map_inited) { + return; + } + + std::string filename = LOG_TAG_LEVEL_CONF_FILE_PATH; + + std::ifstream s(filename); + if (!s.is_open()) { + ALOGE("cannot open file:%s", LOG_TAG_LEVEL_CONF_FILE_PATH); + } else { + std::string line; + while (std::getline(s, line)) { + line.erase(std::remove(line.begin(), line.end(), ' '), line.end()); + int pos = line.find('='); + if (pos <= 0 || pos >= (line.size() - 1)) { + ALOGE("wrong format in gps.prop"); + continue; + } + std::string tag = line.substr(0, pos); + std::string level = line.substr(pos+1, 1); + if (!std::isdigit(*(level.begin()))) { + ALOGE("wrong format in gps.prop"); + continue; + } + tag_level_map[tag] = (uint8_t)std::stoul(level); + } + } + tag_map_inited = true; +} + +int get_tag_log_level(const char* tag) +{ + if (!tag_map_inited) { + return -1; + } + + // in case LOG_TAG isn't defined in a source file, use the global log level + if (tag == NULL) { + return loc_logger.DEBUG_LEVEL; + } + int log_level; + auto search = tag_level_map.find(std::string(tag)); + if (tag_level_map.end() != search) { + log_level = search->second; + } else { + log_level = loc_logger.DEBUG_LEVEL; + } + return log_level; +} diff --git a/gps/utils/loc_misc_utils.cpp b/gps/utils/loc_misc_utils.cpp index 7143466..fbcaef4 100644 --- a/gps/utils/loc_misc_utils.cpp +++ b/gps/utils/loc_misc_utils.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -232,3 +233,119 @@ uint64_t getBootTimeMilliSec() clock_gettime(CLOCK_BOOTTIME, &curTs); return (uint64_t)GET_MSEC_FROM_TS(curTs); } + +// Used for convert position/velocity from GSNS antenna based to VRP based +void Matrix_MxV(float a[3][3], float b[3], float c[3]) { + int i, j; + + for (i=0; i<3; i++) { + c[i] = 0.0f; + for (j=0; j<3; j++) + c[i] += a[i][j] * b[j]; + } +} + +// Used for convert position/velocity from GNSS antenna based to VRP based +void Matrix_Skew(float a[3], float c[3][3]) { + c[0][0] = 0.0f; + c[0][1] = -a[2]; + c[0][2] = a[1]; + c[1][0] = a[2]; + c[1][1] = 0.0f; + c[1][2] = -a[0]; + c[2][0] = -a[1]; + c[2][1] = a[0]; + c[2][2] = 0.0f; +} + +// Used for convert position/velocity from GNSS antenna based to VRP based +void Euler2Dcm(float euler[3], float dcm[3][3]) { + float cr = 0.0, sr = 0.0, cp = 0.0, sp = 0.0, ch = 0.0, sh = 0.0; + + cr = cosf(euler[0]); + sr = sinf(euler[0]); + cp = cosf(euler[1]); + sp = sinf(euler[1]); + ch = cosf(euler[2]); + sh = sinf(euler[2]); + + dcm[0][0] = cp * ch; + dcm[0][1] = (sp*sr*ch) - (cr*sh); + dcm[0][2] = (cr*sp*ch) + (sh*sr); + + dcm[1][0] = cp * sh; + dcm[1][1] = (sr*sp*sh) + (cr*ch); + dcm[1][2] = (cr*sp*sh) - (sr*ch); + + dcm[2][0] = -sp; + dcm[2][1] = sr * cp; + dcm[2][2] = cr * cp; +} + +// Used for convert position from GSNS based to VRP based +// The converted position will be stored in the llaInfo parameter. +#define A6DOF_WGS_A (6378137.0f) +#define A6DOF_WGS_B (6335439.0f) +#define A6DOF_WGS_E2 (0.00669437999014f) +void loc_convert_lla_gnss_to_vrp(double lla[3], float rollPitchYaw[3], + float leverArm[3]) { + LOC_LOGv("lla: %f, %f, %f, lever arm: %f %f %f, " + "rollpitchyaw: %f %f %f", + lla[0], lla[1], lla[2], + leverArm[0], leverArm[1], leverArm[2], + rollPitchYaw[0], rollPitchYaw[1], rollPitchYaw[2]); + + float cnb[3][3]; + memset(cnb, 0, sizeof(cnb)); + Euler2Dcm(rollPitchYaw, cnb); + + float sl = sin(lla[0]); + float cl = cos(lla[0]); + float sf = 1.0f / (1.0f - A6DOF_WGS_E2 * sl* sl); + float sfr = sqrtf(sf); + + float rn = A6DOF_WGS_B * sf * sfr + lla[2]; + float re = A6DOF_WGS_A * sfr + lla[2]; + + float deltaNEU[3]; + + // gps_pos_lla = imu_pos_lla + Cbn*la_b .* [1/geo.Rn; 1/(geo.Re*geo.cL); -1]; + Matrix_MxV(cnb, leverArm, deltaNEU); + + // NED to lla conversion + lla[0] = lla[0] + deltaNEU[0] / rn; + lla[1] = lla[1] + deltaNEU[1] / (re * cl); + lla[2] = lla[2] + deltaNEU[2]; +} + +// Used for convert velocity from GSNS based to VRP based +// The converted velocity will be stored in the enuVelocity parameter. +void loc_convert_velocity_gnss_to_vrp(float enuVelocity[3], float rollPitchYaw[3], + float rollPitchYawRate[3], float leverArm[3]) { + + LOC_LOGv("enu velocity: %f, %f, %f, lever arm: %f %f %f, roll pitch yaw: %f %f %f," + "rollpitchyawRate: %f %f %f", + enuVelocity[0], enuVelocity[1], enuVelocity[2], + leverArm[0], leverArm[1], leverArm[2], + rollPitchYaw[0], rollPitchYaw[1], rollPitchYaw[2], + rollPitchYawRate[0], rollPitchYawRate[1], rollPitchYawRate[2]); + + float cnb[3][3]; + memset(cnb, 0, sizeof(cnb)); + Euler2Dcm(rollPitchYaw, cnb); + + float skewLA[3][3]; + memset(skewLA, 0, sizeof(skewLA)); + Matrix_Skew(leverArm, skewLA); + + float tmp[3]; + float deltaEnuVelocity[3]; + memset(tmp, 0, sizeof(tmp)); + memset(deltaEnuVelocity, 0, sizeof(deltaEnuVelocity)); + Matrix_MxV(skewLA, rollPitchYawRate, tmp); + Matrix_MxV(cnb, tmp, deltaEnuVelocity); + + enuVelocity[0] = enuVelocity[0] - deltaEnuVelocity[0]; + enuVelocity[1] = enuVelocity[1] - deltaEnuVelocity[1]; + enuVelocity[2] = enuVelocity[2] - deltaEnuVelocity[2]; +} diff --git a/gps/utils/loc_misc_utils.h b/gps/utils/loc_misc_utils.h index 796beab..2335e57 100644 --- a/gps/utils/loc_misc_utils.h +++ b/gps/utils/loc_misc_utils.h @@ -279,4 +279,43 @@ inline uint64_t qTimerTicksToNanos(double qTimer) { return (uint64_t((qTimer * double(10000ull)) / (double)192ull)); } +/*=========================================================================== +FUNCTION loc_convert_lla_gnss_to_vrp + +DESCRIPTION + This function converts lat/long/altitude from GNSS antenna based + to vehicle reference point based. + +DEPENDENCIES + N/A + +RETURN VALUE + The converted lat/long/altitude will be stored in the parameter of llaInfo. + +SIDE EFFECTS + N/A +===========================================================================*/ +void loc_convert_lla_gnss_to_vrp(double lla[3], float rollPitchYaw[3], + float leverArm[3]); + +/*=========================================================================== +FUNCTION loc_convert_velocity_gnss_to_vrp + +DESCRIPTION + This function converts east/north/up velocity from GNSS antenna based + to vehicle reference point based. + +DEPENDENCIES + N/A + +RETURN VALUE + The converted east/north/up velocity will be stored in the parameter of + enuVelocity. + +SIDE EFFECTS + N/A +===========================================================================*/ +void loc_convert_velocity_gnss_to_vrp(float enuVelocity[3], float rollPitchYaw[3], + float rollPitchYawRate[3], float leverArm[3]); + #endif //_LOC_MISC_UTILS_H_ diff --git a/gps/utils/loc_nmea.cpp b/gps/utils/loc_nmea.cpp index 78007d5..6b5e60e 100644 --- a/gps/utils/loc_nmea.cpp +++ b/gps/utils/loc_nmea.cpp @@ -36,6 +36,7 @@ #include #define GLONASS_SV_ID_OFFSET 64 +#define SBAS_SV_ID_OFFSET (87) #define QZSS_SV_ID_OFFSET (192) #define BDS_SV_ID_OFFSET (200) #define GALILEO_SV_ID_OFFSET (300) @@ -44,6 +45,7 @@ #define MAX_SATELLITES_IN_USE 12 #define MSEC_IN_ONE_WEEK 604800000ULL #define UTC_GPS_OFFSET_MSECS 315964800000ULL +#define MAX_TAG_BLOCK_GROUP_CODE (99999) // GNSS system id according to NMEA spec #define SYSTEM_ID_GPS 1 @@ -113,7 +115,7 @@ typedef struct loc_nmea_sv_meta_s { char talker[3]; - LocGnssConstellationType svType; + uint32_t svTypeMask; uint64_t mask; uint32_t svCount; uint32_t totalSvUsedCount; @@ -139,6 +141,7 @@ typedef struct loc_sv_cache_info_s uint32_t gal_e5_count; uint32_t gal_e5b_count; uint32_t qzss_l1_count; + uint32_t qzss_l2_count; uint32_t qzss_l5_count; uint32_t bds_b1i_count; uint32_t bds_b1c_count; @@ -291,6 +294,7 @@ static uint32_t convert_signalType_to_signalId(GnssSignalTypeMask signalType) switch (signalType) { case GNSS_SIGNAL_GPS_L1CA: + case GNSS_SIGNAL_SBAS_L1: signalId = SIGNAL_ID_GPS_L1CA; break; case GNSS_SIGNAL_GPS_L2: @@ -403,7 +407,7 @@ static loc_nmea_sv_meta* loc_nmea_sv_meta_init(loc_nmea_sv_meta& sv_meta, bool needCombine) { memset(&sv_meta, 0, sizeof(sv_meta)); - sv_meta.svType = svType; + sv_meta.svTypeMask = (1 << svType); switch (svType) { @@ -412,12 +416,17 @@ static loc_nmea_sv_meta* loc_nmea_sv_meta_init(loc_nmea_sv_meta& sv_meta, sv_meta.talker[1] = 'P'; sv_meta.mask = sv_cache_info.gps_used_mask; sv_meta.systemId = SYSTEM_ID_GPS; - if (GNSS_SIGNAL_GPS_L1CA == signalType) { - sv_meta.svCount = sv_cache_info.gps_l1_count; - } else if (GNSS_SIGNAL_GPS_L5 == signalType) { - sv_meta.svCount = sv_cache_info.gps_l5_count; - } else if (GNSS_SIGNAL_GPS_L2 == signalType) { - sv_meta.svCount = sv_cache_info.gps_l2_count; + sv_meta.svTypeMask |= (1 << GNSS_SV_TYPE_SBAS); + switch (signalType) { + case GNSS_SIGNAL_GPS_L1CA: + sv_meta.svCount = sv_cache_info.gps_l1_count; + break; + case GNSS_SIGNAL_GPS_L5: + sv_meta.svCount = sv_cache_info.gps_l5_count; + break; + case GNSS_SIGNAL_GPS_L2: + sv_meta.svCount = sv_cache_info.gps_l2_count; + break; } break; case GNSS_SV_TYPE_GLONASS: @@ -427,10 +436,13 @@ static loc_nmea_sv_meta* loc_nmea_sv_meta_init(loc_nmea_sv_meta& sv_meta, // GLONASS SV ids are from 65-96 sv_meta.svIdOffset = GLONASS_SV_ID_OFFSET; sv_meta.systemId = SYSTEM_ID_GLONASS; - if (GNSS_SIGNAL_GLONASS_G1 == signalType) { - sv_meta.svCount = sv_cache_info.glo_g1_count; - } else if (GNSS_SIGNAL_GLONASS_G2 == signalType) { - sv_meta.svCount = sv_cache_info.glo_g2_count; + switch (signalType) { + case GNSS_SIGNAL_GLONASS_G1: + sv_meta.svCount = sv_cache_info.glo_g1_count; + break; + case GNSS_SIGNAL_GLONASS_G2: + sv_meta.svCount = sv_cache_info.glo_g2_count; + break; } break; case GNSS_SV_TYPE_GALILEO: @@ -440,12 +452,16 @@ static loc_nmea_sv_meta* loc_nmea_sv_meta_init(loc_nmea_sv_meta& sv_meta, // GALILEO SV ids are from 301-336, So keep svIdOffset 300 sv_meta.svIdOffset = GALILEO_SV_ID_OFFSET; sv_meta.systemId = SYSTEM_ID_GALILEO; - if (GNSS_SIGNAL_GALILEO_E1 == signalType) { - sv_meta.svCount = sv_cache_info.gal_e1_count; - } else if (GNSS_SIGNAL_GALILEO_E5A == signalType) { - sv_meta.svCount = sv_cache_info.gal_e5_count; - } else if (GNSS_SIGNAL_GALILEO_E5B == signalType) { - sv_meta.svCount == sv_cache_info.gal_e5b_count; + switch (signalType) { + case GNSS_SIGNAL_GALILEO_E1: + sv_meta.svCount = sv_cache_info.gal_e1_count; + break; + case GNSS_SIGNAL_GALILEO_E5A: + sv_meta.svCount = sv_cache_info.gal_e5_count; + break; + case GNSS_SIGNAL_GALILEO_E5B: + sv_meta.svCount = sv_cache_info.gal_e5b_count; + break; } break; case GNSS_SV_TYPE_QZSS: @@ -455,10 +471,16 @@ static loc_nmea_sv_meta* loc_nmea_sv_meta_init(loc_nmea_sv_meta& sv_meta, // QZSS SV ids are from 193-199. So keep svIdOffset 192 sv_meta.svIdOffset = QZSS_SV_ID_OFFSET; sv_meta.systemId = SYSTEM_ID_QZSS; - if (GNSS_SIGNAL_QZSS_L1CA == signalType) { - sv_meta.svCount = sv_cache_info.qzss_l1_count; - } else if (GNSS_SIGNAL_QZSS_L5 == signalType) { - sv_meta.svCount = sv_cache_info.qzss_l5_count; + switch (signalType) { + case GNSS_SIGNAL_QZSS_L1CA: + sv_meta.svCount = sv_cache_info.qzss_l1_count; + break; + case GNSS_SIGNAL_QZSS_L2: + sv_meta.svCount = sv_cache_info.qzss_l2_count; + break; + case GNSS_SIGNAL_QZSS_L5: + sv_meta.svCount = sv_cache_info.qzss_l5_count; + break; } break; case GNSS_SV_TYPE_BEIDOU: @@ -468,12 +490,16 @@ static loc_nmea_sv_meta* loc_nmea_sv_meta_init(loc_nmea_sv_meta& sv_meta, // BDS SV ids are from 201-237. So keep svIdOffset 200 sv_meta.svIdOffset = BDS_SV_ID_OFFSET; sv_meta.systemId = SYSTEM_ID_BDS; - if (GNSS_SIGNAL_BEIDOU_B1I == signalType) { - sv_meta.svCount = sv_cache_info.bds_b1i_count; - } else if (GNSS_SIGNAL_BEIDOU_B1C == signalType) { - sv_meta.svCount = sv_cache_info.bds_b1c_count; - } else if (GNSS_SIGNAL_BEIDOU_B2AI == signalType) { - sv_meta.svCount = sv_cache_info.bds_b2_count; + switch (signalType) { + case GNSS_SIGNAL_BEIDOU_B1I: + sv_meta.svCount = sv_cache_info.bds_b1i_count; + break; + case GNSS_SIGNAL_BEIDOU_B1C: + sv_meta.svCount = sv_cache_info.bds_b1c_count; + break; + case GNSS_SIGNAL_BEIDOU_B2AI: + sv_meta.svCount = sv_cache_info.bds_b2_count; + break; } break; case GNSS_SV_TYPE_NAVIC: @@ -483,8 +509,10 @@ static loc_nmea_sv_meta* loc_nmea_sv_meta_init(loc_nmea_sv_meta& sv_meta, // NAVIC SV ids are from 401-414. So keep svIdOffset 400 sv_meta.svIdOffset = NAVIC_SV_ID_OFFSET; sv_meta.systemId = SYSTEM_ID_NAVIC; - if (GNSS_SIGNAL_NAVIC_L5 == signalType) { - sv_meta.svCount = sv_cache_info.navic_l5_count; + switch (signalType) { + case GNSS_SIGNAL_NAVIC_L5: + sv_meta.svCount = sv_cache_info.navic_l5_count; + break; } break; default: @@ -539,23 +567,28 @@ SIDE EFFECTS N/A ===========================================================================*/ -static int loc_nmea_put_checksum(char *pNmea, int maxSize) +static int loc_nmea_put_checksum(char *pNmea, int maxSize, bool isTagBlock) { uint8_t checksum = 0; int length = 0; + int checksumLength = 0; if(NULL == pNmea) return 0; - pNmea++; //skip the $ + pNmea++; //skip the $ or / for Tag Block while (*pNmea != '\0') { checksum ^= *pNmea++; length++; } - // length now contains nmea sentence string length not including $ sign. - int checksumLength = snprintf(pNmea,(maxSize-length-1),"*%02X\r\n", checksum); - + if (isTagBlock) { + // length now contains tag block sentence string length not including / sign. + checksumLength = snprintf(pNmea, (maxSize-length-1), "*%02X\\", checksum); + } else { + // length now contains nmea sentence string length not including $ sign. + checksumLength = snprintf(pNmea, (maxSize-length-1), "*%02X\r\n", checksum); + } // total length of nmea sentence is length of nmea sentence inc $ sign plus // length of checksum (+1 is to cover the $ character in the length). return (length + checksumLength + 1); @@ -586,7 +619,8 @@ static uint32_t loc_nmea_generate_GSA(const GpsLocationExtended &locationExtende char* sentence, int bufSize, loc_nmea_sv_meta* sv_meta_p, - std::vector &nmeaArraystr) + std::vector &nmeaArraystr, + bool isTagBlockGroupingEnabled) { if (!sentence || bufSize <= 0 || !sv_meta_p) { @@ -597,9 +631,14 @@ static uint32_t loc_nmea_generate_GSA(const GpsLocationExtended &locationExtende char* pMarker = sentence; int lengthRemaining = bufSize; int length = 0; + int lengthTagBlock = 0; uint32_t svUsedCount = 0; uint32_t svUsedList[64] = {0}; + uint32_t sentenceCount = 0; + uint32_t sentenceNumber = 1; + size_t svNumber = 1; + static uint32_t code = 1; char fixType = '\0'; @@ -607,7 +646,7 @@ static uint32_t loc_nmea_generate_GSA(const GpsLocationExtended &locationExtende uint32_t svIdOffset = sv_meta_p->svIdOffset; uint64_t mask = sv_meta_p->mask; - if(sv_meta_p->svType != GNSS_SV_TYPE_GLONASS) { + if (!(sv_meta_p->svTypeMask & (1 << GNSS_SV_TYPE_GLONASS))) { svIdOffset = 0; } @@ -618,77 +657,98 @@ static uint32_t loc_nmea_generate_GSA(const GpsLocationExtended &locationExtende mask = mask >> 1; } - if (svUsedCount == 0) - return 0; - - if (sv_meta_p->totalSvUsedCount == 0) - fixType = '1'; // no fix - else if (sv_meta_p->totalSvUsedCount <= 3) - fixType = '2'; // 2D fix - else - fixType = '3'; // 3D fix - - // Start printing the sentence - // Format: $--GSA,a,x,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,p.p,h.h,v.v,s*cc - // a : Mode : A : Automatic, allowed to automatically switch 2D/3D - // x : Fixtype : 1 (no fix), 2 (2D fix), 3 (3D fix) - // xx : 12 SV ID - // p.p : Position DOP (Dilution of Precision) - // h.h : Horizontal DOP - // v.v : Vertical DOP - // s : GNSS System Id - // cc : Checksum value - length = snprintf(pMarker, lengthRemaining, "$%sGSA,A,%c,", talker, fixType); - - if (length < 0 || length >= lengthRemaining) - { - LOC_LOGE("NMEA Error in string formatting"); + if (svUsedCount == 0) { return 0; + } else { + sentenceNumber = 1; + sentenceCount = svUsedCount / 12 + (svUsedCount % 12 != 0); + svNumber = 1; } - pMarker += length; - lengthRemaining -= length; - - // Add first 12 satellite IDs - for (uint8_t i = 0; i < 12; i++) - { - if (i < svUsedCount) - length = snprintf(pMarker, lengthRemaining, "%02d,", svUsedList[i]); + while (sentenceNumber <= sentenceCount) { + pMarker = sentence; + lengthRemaining = bufSize; + if (svUsedCount > 12 && isTagBlockGroupingEnabled) { + lengthTagBlock = snprintf(pMarker, lengthRemaining, "\\g:%d-%d-%d", sentenceNumber, + sentenceCount, code); + if (MAX_TAG_BLOCK_GROUP_CODE == code) { + code = 1; + } + lengthTagBlock = loc_nmea_put_checksum(sentence, bufSize, true); + pMarker += lengthTagBlock; + lengthRemaining -= lengthTagBlock; + } + if (sv_meta_p->totalSvUsedCount == 0) + fixType = '1'; // no fix + else if (sv_meta_p->totalSvUsedCount <= 3) + fixType = '2'; // 2D fix else - length = snprintf(pMarker, lengthRemaining, ","); + fixType = '3'; // 3D fix - if (length < 0 || length >= lengthRemaining) - { + // Start printing the sentence + // Format: $--GSA,a,x,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,p.p,h.h,v.v,s*cc + // a : Mode : A : Automatic, allowed to automatically switch 2D/3D + // x : Fixtype : 1 (no fix), 2 (2D fix), 3 (3D fix) + // xx : 12 SV ID + // p.p : Position DOP (Dilution of Precision) + // h.h : Horizontal DOP + // v.v : Vertical DOP + // s : GNSS System Id + // cc : Checksum value + length = snprintf(pMarker, lengthRemaining, "$%sGSA,A,%c,", talker, fixType); + if (length < 0 || length >= lengthRemaining) { LOC_LOGE("NMEA Error in string formatting"); return 0; } pMarker += length; lengthRemaining -= length; + + // Add 12 satellite IDs + for (uint8_t i = 0; i < 12; i++, svNumber++) + { + if (svNumber <= svUsedCount) + length = snprintf(pMarker, lengthRemaining, "%02d,", svUsedList[svNumber - 1]); + else + length = snprintf(pMarker, lengthRemaining, ","); + + if (length < 0 || length >= lengthRemaining) { + LOC_LOGE("NMEA Error in string formatting"); + return 0; + } + pMarker += length; + lengthRemaining -= length; + } + + // Add the position/horizontal/vertical DOP values + if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_DOP) + { + length = snprintf(pMarker, lengthRemaining, "%.1f,%.1f,%.1f,", + locationExtended.pdop, + locationExtended.hdop, + locationExtended.vdop); + } + else + { // no dop + length = snprintf(pMarker, lengthRemaining, ",,,"); + } + pMarker += length; + lengthRemaining -= length; + + // system id + length = snprintf(pMarker, lengthRemaining, "%d", sv_meta_p->systemId); + pMarker += length; + lengthRemaining -= length; + + /* Sentence is ready, add checksum and broadcast */ + length = loc_nmea_put_checksum(sentence + lengthTagBlock, bufSize - lengthTagBlock, false); + nmeaArraystr.push_back(sentence); + sentenceNumber++; + if (!isTagBlockGroupingEnabled) { + break; + } } - - // Add the position/horizontal/vertical DOP values - if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_DOP) - { - length = snprintf(pMarker, lengthRemaining, "%.1f,%.1f,%.1f,", - locationExtended.pdop, - locationExtended.hdop, - locationExtended.vdop); + if (svUsedCount > 12 && isTagBlockGroupingEnabled) { + code++; } - else - { // no dop - length = snprintf(pMarker, lengthRemaining, ",,,"); - } - pMarker += length; - lengthRemaining -= length; - - // system id - length = snprintf(pMarker, lengthRemaining, "%d", sv_meta_p->systemId); - pMarker += length; - lengthRemaining -= length; - - /* Sentence is ready, add checksum and broadcast */ - length = loc_nmea_put_checksum(sentence, bufSize); - nmeaArraystr.push_back(sentence); - return svUsedCount; } @@ -740,7 +800,7 @@ static void loc_nmea_generate_GSV(const GnssSvNotification &svNotify, return; } - if (GNSS_SV_TYPE_GLONASS == sv_meta_p->svType) { + if ((1 << GNSS_SV_TYPE_GLONASS) & sv_meta_p->svTypeMask) { svIdOffset = 0; } svNumber = 1; @@ -798,14 +858,23 @@ static void loc_nmea_generate_GSV(const GnssSvNotification &svNotify, } } - if (sv_meta_p->svType == svNotify.gnssSvs[svNumber - 1].type && + if ((sv_meta_p->svTypeMask & (1 << svNotify.gnssSvs[svNumber - 1].type)) && sv_meta_p->signalId == convert_signalType_to_signalId(signalType)) { - length = snprintf(pMarker, lengthRemaining,",%02d,%02d,%03d,", + if (GNSS_SV_TYPE_SBAS == svNotify.gnssSvs[svNumber - 1].type) { + svIdOffset = SBAS_SV_ID_OFFSET; + } + if (GNSS_SV_TYPE_GLONASS == svNotify.gnssSvs[svNumber - 1].type && + GLO_SV_PRN_SLOT_UNKNOWN == svNotify.gnssSvs[svNumber - 1].svId) { + length = snprintf(pMarker, lengthRemaining, ",,%02d,%03d,", + (int)(0.5 + svNotify.gnssSvs[svNumber - 1].elevation), //float to int + (int)(0.5 + svNotify.gnssSvs[svNumber - 1].azimuth)); //float to int + } else { + length = snprintf(pMarker, lengthRemaining, ",%02d,%02d,%03d,", svNotify.gnssSvs[svNumber - 1].svId - svIdOffset, (int)(0.5 + svNotify.gnssSvs[svNumber - 1].elevation), //float to int (int)(0.5 + svNotify.gnssSvs[svNumber - 1].azimuth)); //float to int - + } if (length < 0 || length >= lengthRemaining) { LOC_LOGE("NMEA Error in string formatting"); @@ -838,7 +907,7 @@ static void loc_nmea_generate_GSV(const GnssSvNotification &svNotify, pMarker += length; lengthRemaining -= length; - length = loc_nmea_put_checksum(sentence, bufSize); + length = loc_nmea_put_checksum(sentence, bufSize, false); nmeaArraystr.push_back(sentence); sentenceNumber++; @@ -947,7 +1016,7 @@ static void loc_nmea_generate_DTM(const LocLla &ref_lla, pMarker += length; lengthRemaining -= length; - length = loc_nmea_put_checksum(sentence, bufSize); + length = loc_nmea_put_checksum(sentence, bufSize, false); } /*=========================================================================== @@ -1059,17 +1128,6 @@ static void loc_nmea_get_fix_quality(const UlpLocation & location, memset(gnsModeIndicator, 'N', 6); // N means no fix gnsModeIndicator[6] = '\0'; do { - // GGA fix quality is defined in NMEA spec as below: - // https://www.trimble.com/OEM_ReceiverHelp/V4.44/en/NMEA-0183messages_GGA.html - // Fix quality: 0 = invalid - // 1 = GPS fix (SPS) - // 2 = DGPS fix - // 3 = PPS fix - // 4 = Real Time Kinematic - // 5 = Float RTK - // 6 = estimated (dead reckoning) (2.3 feature) - // 7 = Manual input mode - // 8 = Simulation mode if (!(location.gpsLocation.flags & LOC_GPS_LOCATION_HAS_LAT_LONG)){ break; } @@ -1274,7 +1332,8 @@ void loc_nmea_generate_pos(const UlpLocation &location, unsigned char generate_nmea, bool custom_gga_fix_quality, std::vector &nmeaArraystr, - int& indexOfGGA) + int& indexOfGGA, + bool isTagBlockGroupingEnabled) { ENTRY_LOG(); @@ -1355,7 +1414,7 @@ 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_GPS, - GNSS_SIGNAL_GPS_L1CA, true), nmeaArraystr); + GNSS_SIGNAL_GPS_L1CA, true), nmeaArraystr, isTagBlockGroupingEnabled); if (count > 0) { svUsedCount += count; @@ -1369,7 +1428,7 @@ 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_GLONASS, - GNSS_SIGNAL_GLONASS_G1, true), nmeaArraystr); + GNSS_SIGNAL_GLONASS_G1, true), nmeaArraystr, isTagBlockGroupingEnabled); if (count > 0) { svUsedCount += count; @@ -1383,7 +1442,7 @@ 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_GALILEO, - GNSS_SIGNAL_GALILEO_E1, true), nmeaArraystr); + GNSS_SIGNAL_GALILEO_E1, true), nmeaArraystr, isTagBlockGroupingEnabled); if (count > 0) { svUsedCount += count; @@ -1396,7 +1455,7 @@ 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, true), nmeaArraystr); + GNSS_SIGNAL_BEIDOU_B1I, true), nmeaArraystr, isTagBlockGroupingEnabled); if (count > 0) { svUsedCount += count; @@ -1410,7 +1469,7 @@ 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, true), nmeaArraystr); + GNSS_SIGNAL_QZSS_L1CA, true), nmeaArraystr, isTagBlockGroupingEnabled); if (count > 0) { svUsedCount += count; @@ -1422,7 +1481,7 @@ void loc_nmea_generate_pos(const UlpLocation &location, // in this case, generate an empty GSA sentence if (svUsedCount == 0) { strlcpy(sentence, "$GPGSA,A,1,,,,,,,,,,,,,,,,", sizeof(sentence)); - length = loc_nmea_put_checksum(sentence, sizeof(sentence)); + length = loc_nmea_put_checksum(sentence, sizeof(sentence), false); nmeaArraystr.push_back(sentence); } @@ -1445,7 +1504,7 @@ void loc_nmea_generate_pos(const UlpLocation &location, float magTrack = location.gpsLocation.bearing; if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_MAG_DEV) { - float magTrack = location.gpsLocation.bearing - locationExtended.magneticDeviation; + magTrack = location.gpsLocation.bearing - locationExtended.magneticDeviation; if (magTrack < 0.0) magTrack += 360.0; else if (magTrack > 360.0) @@ -1489,7 +1548,7 @@ void loc_nmea_generate_pos(const UlpLocation &location, length = snprintf(pMarker, lengthRemaining, "%c", vtgModeIndicator); - length = loc_nmea_put_checksum(sentence, sizeof(sentence)); + length = loc_nmea_put_checksum(sentence, sizeof(sentence), false); nmeaArraystr.push_back(sentence); memset(&ecef_w84, 0, sizeof(ecef_w84)); @@ -1693,7 +1752,7 @@ void loc_nmea_generate_pos(const UlpLocation &location, // hardcode Navigation Status field to 'V' length = snprintf(pMarker, lengthRemaining, ",%c", 'V'); - length = loc_nmea_put_checksum(sentence_RMC, sizeof(sentence_RMC)); + length = loc_nmea_put_checksum(sentence_RMC, sizeof(sentence_RMC), false); // ------------------- // ------$--GNS------- @@ -1855,7 +1914,7 @@ void loc_nmea_generate_pos(const UlpLocation &location, pMarker += length; lengthRemaining -= length; - length = loc_nmea_put_checksum(sentence_GNS, sizeof(sentence_GNS)); + length = loc_nmea_put_checksum(sentence_GNS, sizeof(sentence_GNS), false); // ------------------- // ------$--GGA------- @@ -2012,7 +2071,7 @@ void loc_nmea_generate_pos(const UlpLocation &location, lengthRemaining -= length; } - length = loc_nmea_put_checksum(sentence_GGA, sizeof(sentence_GGA)); + length = loc_nmea_put_checksum(sentence_GGA, sizeof(sentence_GGA), false); // ------$--DTM------- nmeaArraystr.push_back(sentence_DTM); @@ -2035,27 +2094,27 @@ void loc_nmea_generate_pos(const UlpLocation &location, //Send blank NMEA reports for non-final fixes else { strlcpy(sentence, "$GPGSA,A,1,,,,,,,,,,,,,,,,", sizeof(sentence)); - length = loc_nmea_put_checksum(sentence, sizeof(sentence)); + length = loc_nmea_put_checksum(sentence, sizeof(sentence), false); nmeaArraystr.push_back(sentence); strlcpy(sentence, "$GPVTG,,T,,M,,N,,K,N", sizeof(sentence)); - length = loc_nmea_put_checksum(sentence, sizeof(sentence)); + length = loc_nmea_put_checksum(sentence, sizeof(sentence), false); nmeaArraystr.push_back(sentence); strlcpy(sentence, "$GPDTM,,,,,,,,", sizeof(sentence)); - length = loc_nmea_put_checksum(sentence, sizeof(sentence)); + length = loc_nmea_put_checksum(sentence, sizeof(sentence), false); nmeaArraystr.push_back(sentence); strlcpy(sentence, "$GPRMC,,V,,,,,,,,,,N,V", sizeof(sentence)); - length = loc_nmea_put_checksum(sentence, sizeof(sentence)); + length = loc_nmea_put_checksum(sentence, sizeof(sentence), false); nmeaArraystr.push_back(sentence); strlcpy(sentence, "$GPGNS,,,,,,N,,,,,,,V", sizeof(sentence)); - length = loc_nmea_put_checksum(sentence, sizeof(sentence)); + length = loc_nmea_put_checksum(sentence, sizeof(sentence), false); nmeaArraystr.push_back(sentence); strlcpy(sentence, "$GPGGA,,,,,,0,,,,,,,,", sizeof(sentence)); - length = loc_nmea_put_checksum(sentence, sizeof(sentence)); + length = loc_nmea_put_checksum(sentence, sizeof(sentence), false); nmeaArraystr.push_back(sentence); } @@ -2090,14 +2149,15 @@ void loc_nmea_generate_sv(const GnssSvNotification &svNotify, //Count GPS SVs for saparating GPS from GLONASS and throw others for (uint32_t svOffset = 0; svOffset < svNotify.count; svOffset++) { - if (GNSS_SV_TYPE_GPS == svNotify.gnssSvs[svOffset].type) + if ((GNSS_SV_TYPE_GPS == svNotify.gnssSvs[svOffset].type) || + (GNSS_SV_TYPE_SBAS == svNotify.gnssSvs[svOffset].type)) { if (GNSS_SIGNAL_GPS_L5 == svNotify.gnssSvs[svOffset].gnssSignalTypeMask) { sv_cache_info.gps_l5_count++; } else if (GNSS_SIGNAL_GPS_L2 == svNotify.gnssSvs[svOffset].gnssSignalTypeMask) { sv_cache_info.gps_l2_count++; } else { - // GNSS_SIGNAL_GPS_L1CA or default + // GNSS_SIGNAL_GPS_L1CA, GNSS_SIGNAL_SBAS_L1 or default // If no signal type in report, it means default L1 sv_cache_info.gps_l1_count++; } @@ -2128,6 +2188,8 @@ void loc_nmea_generate_sv(const GnssSvNotification &svNotify, { if (GNSS_SIGNAL_QZSS_L5 == svNotify.gnssSvs[svOffset].gnssSignalTypeMask) { sv_cache_info.qzss_l5_count++; + } else if (GNSS_SIGNAL_QZSS_L2 == svNotify.gnssSvs[svOffset].gnssSignalTypeMask) { + sv_cache_info.qzss_l2_count++; } else { // GNSS_SIGNAL_QZSS_L1CA or default // If no signal type in report, it means default L1 @@ -2136,6 +2198,14 @@ void loc_nmea_generate_sv(const GnssSvNotification &svNotify, } else if (GNSS_SV_TYPE_BEIDOU == svNotify.gnssSvs[svOffset].type) { + // cache the used in fix mask, as it will be needed to send $PQGSA + // during the position report + if (GNSS_SV_OPTIONS_USED_IN_FIX_BIT == + (svNotify.gnssSvs[svOffset].gnssSvOptionsMask & + GNSS_SV_OPTIONS_USED_IN_FIX_BIT)) + { + setSvMask(sv_cache_info.bds_used_mask, svNotify.gnssSvs[svOffset].svId); + } if ((GNSS_SIGNAL_BEIDOU_B2AI == svNotify.gnssSvs[svOffset].gnssSignalTypeMask) || (GNSS_SIGNAL_BEIDOU_B2AQ == svNotify.gnssSvs[svOffset].gnssSignalTypeMask)) { sv_cache_info.bds_b2_count++; @@ -2231,6 +2301,16 @@ void loc_nmea_generate_sv(const GnssSvNotification &svNotify, loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence), loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_QZSS, GNSS_SIGNAL_QZSS_L5, false), nmeaArraystr); + + // ----------------------------- + // ------$GQGSV (QZSS):L2------- + // ----------------------------- + + loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence), + loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_QZSS, + GNSS_SIGNAL_QZSS_L2, false), nmeaArraystr); + + // ----------------------------- // ------$GBGSV (BEIDOU:B1I)---- // ----------------------------- @@ -2242,6 +2322,7 @@ void loc_nmea_generate_sv(const GnssSvNotification &svNotify, // ----------------------------- // ------$GBGSV (BEIDOU:B1C)---- // ----------------------------- + loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence), loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_BEIDOU, GNSS_SIGNAL_BEIDOU_B1C, false), nmeaArraystr); diff --git a/gps/utils/loc_nmea.h b/gps/utils/loc_nmea.h index ef99e0f..2d98f42 100644 --- a/gps/utils/loc_nmea.h +++ b/gps/utils/loc_nmea.h @@ -81,7 +81,8 @@ void loc_nmea_generate_pos(const UlpLocation &location, unsigned char generate_nmea, bool custom_gga_fix_quality, std::vector &nmeaArraystr, - int& indexOfGGA); + int& indexOfGGA, + bool isTagBlockGroupingEnabled); #define DEBUG_NMEA_MINSIZE 6 #define DEBUG_NMEA_MAXSIZE 4096 diff --git a/gps/utils/log_util.h b/gps/utils/log_util.h index 5cdcf25..33aa6e2 100644 --- a/gps/utils/log_util.h +++ b/gps/utils/log_util.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2014, 2020 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,7 +32,6 @@ #include #include - #if defined (USE_ANDROID_LOGGING) || defined (ANDROID) // Android and LE targets with logcat support #include @@ -53,7 +52,7 @@ #endif /* LOG_TAG */ // LE targets with no logcat support -#ifdef FEATURE_EXTERNAL_AP +#if defined(FEATURE_EXTERNAL_AP) || defined(USE_SYSLOG_LOGGING) #include #define ALOGE(...) syslog(LOG_ERR, "LOC_LOGE: " __VA_ARGS__); #define ALOGW(...) syslog(LOG_WARNING, "LOC_LOGW: " __VA_ARGS__); @@ -160,10 +159,10 @@ inline void loc_logger_init(unsigned long debug, unsigned long timestamp) inline void log_buffer_init(bool enabled) { loc_logger.LOG_BUFFER_ENABLE = enabled; } - +extern void log_tag_level_map_init(); +extern int get_tag_log_level(const char* tag); extern char* get_timestamp(char* str, unsigned long buf_size); extern void log_buffer_insert(char *str, unsigned long buf_size, int level); - /*============================================================================= * * LOGGING BUFFER MACROS @@ -196,11 +195,28 @@ extern void log_buffer_insert(char *str, unsigned long buf_size, int level); if that value remains unchanged, it means gps.conf did not provide a value and we default to the initial value to use Android's logging levels*/ -#define IF_LOC_LOGE if((loc_logger.DEBUG_LEVEL >= 1) && (loc_logger.DEBUG_LEVEL <= 5)) -#define IF_LOC_LOGW if((loc_logger.DEBUG_LEVEL >= 2) && (loc_logger.DEBUG_LEVEL <= 5)) -#define IF_LOC_LOGI if((loc_logger.DEBUG_LEVEL >= 3) && (loc_logger.DEBUG_LEVEL <= 5)) -#define IF_LOC_LOGD if((loc_logger.DEBUG_LEVEL >= 4) && (loc_logger.DEBUG_LEVEL <= 5)) -#define IF_LOC_LOGV if((loc_logger.DEBUG_LEVEL >= 5) && (loc_logger.DEBUG_LEVEL <= 5)) + + +/* Tag based logging control MACROS */ +/* The logic is like this: + * 1, LOCAL_LOG_LEVEL is defined as a static variable in log_util.h, + * then all source files which includes log_util.h will have its own LOCAL_LOG_LEVEL variable; + * 2, For each source file, + * 2.1, First time when LOC_LOG* is invoked(its LOCAL_LOG_LEVEL == -1), + * Set the tag based log level according to the map; + * If this tag isn't found in map, set local debug level as global loc_logger.DEBUG_LEVEL; + * 2.2, If not the first time, use its LOCAL_LOG_LEVEL as the debug level of this tag. +*/ +static int LOCAL_LOG_LEVEL = -1; +#define IF_LOC_LOG(x) \ + if (((LOCAL_LOG_LEVEL == -1 && (LOCAL_LOG_LEVEL = get_tag_log_level(LOG_TAG)) >= x) ||\ + LOCAL_LOG_LEVEL >= x) && LOCAL_LOG_LEVEL <= 5) + +#define IF_LOC_LOGE IF_LOC_LOG(1) +#define IF_LOC_LOGW IF_LOC_LOG(2) +#define IF_LOC_LOGI IF_LOC_LOG(3) +#define IF_LOC_LOGD IF_LOC_LOG(4) +#define IF_LOC_LOGV IF_LOC_LOG(5) #define LOC_LOGE(...) IF_LOC_LOGE { ALOGE(__VA_ARGS__); INSERT_BUFFER(LOG_NDEBUG, 0, __VA_ARGS__);} #define LOC_LOGW(...) IF_LOC_LOGW { ALOGW(__VA_ARGS__); INSERT_BUFFER(LOG_NDEBUG, 1, __VA_ARGS__);}