Loading gnss/aidl/default/Gnss.cpp +6 −2 Original line number Diff line number Diff line Loading @@ -162,12 +162,13 @@ ScopedAStatus Gnss::close() { return ScopedAStatus::ok(); } void Gnss::reportLocation(const GnssLocation& location) const { void Gnss::reportLocation(const GnssLocation& location) { std::unique_lock<std::mutex> lock(mMutex); if (sGnssCallback == nullptr) { ALOGE("%s: GnssCallback is null.", __func__); return; } mLastLocation = std::make_shared<GnssLocation>(location); auto status = sGnssCallback->gnssLocationCb(location); if (!status.isOk()) { ALOGE("%s: Unable to invoke gnssLocationCb", __func__); Loading Loading @@ -359,7 +360,6 @@ ScopedAStatus Gnss::getExtensionGnssNavigationMessage( ndk::ScopedAStatus Gnss::getExtensionGnssDebug(std::shared_ptr<IGnssDebug>* iGnssDebug) { ALOGD("Gnss::getExtensionGnssDebug"); *iGnssDebug = SharedRefBase::make<GnssDebug>(); return ndk::ScopedAStatus::ok(); } Loading Loading @@ -398,4 +398,8 @@ void Gnss::setGnssMeasurementInterval(const long intervalMs) { mGnssMeasurementIntervalMs = intervalMs; } std::shared_ptr<GnssLocation> Gnss::getLastLocation() const { return mLastLocation; } } // namespace aidl::android::hardware::gnss gnss/aidl/default/Gnss.h +5 −3 Original line number Diff line number Diff line Loading @@ -87,18 +87,19 @@ class Gnss : public BnGnss { void reportSvStatus() const; void setGnssMeasurementEnabled(const bool enabled); void setGnssMeasurementInterval(const long intervalMs); std::shared_ptr<GnssLocation> getLastLocation() const; std::shared_ptr<GnssConfiguration> mGnssConfiguration; std::shared_ptr<GnssPowerIndication> mGnssPowerIndication; std::shared_ptr<GnssMeasurementInterface> mGnssMeasurementInterface; private: void reportLocation(const GnssLocation&) const; void reportLocation(const GnssLocation&); void reportSvStatus(const std::vector<IGnssCallback::GnssSvInfo>& svInfoList) const; void reportGnssStatusValue(const IGnssCallback::GnssStatusValue gnssStatusValue) const; void reportNmea() const; std::vector<IGnssCallback::GnssSvInfo> filterBlocklistedSatellites( std::vector<IGnssCallback::GnssSvInfo> gnssSvInfoList) const; void reportGnssStatusValue(const IGnssCallback::GnssStatusValue gnssStatusValue) const; std::unique_ptr<GnssLocation> getLocationFromHW(); void reportNmea() const; static std::shared_ptr<IGnssCallback> sGnssCallback; Loading @@ -109,6 +110,7 @@ class Gnss : public BnGnss { std::atomic<bool> mIsNmeaActive; std::atomic<bool> mFirstFixReceived; std::atomic<bool> mGnssMeasurementEnabled; std::shared_ptr<GnssLocation> mLastLocation; std::thread mThread; ::android::hardware::gnss::common::ThreadBlocker mThreadBlocker; Loading gnss/aidl/default/GnssDebug.cpp +92 −3 Original line number Diff line number Diff line Loading @@ -18,10 +18,15 @@ #include "GnssDebug.h" #include <log/log.h> #include <utils/SystemClock.h> #include "Constants.h" #include "Gnss.h" #include "MockLocation.h" namespace aidl::android::hardware::gnss { using ::android::hardware::gnss::common::kMockTimestamp; ndk::ScopedAStatus GnssDebug::getDebugData(DebugData* debugData) { ALOGD("GnssDebug::getDebugData"); Loading @@ -36,10 +41,94 @@ ndk::ScopedAStatus GnssDebug::getDebugData(DebugData* debugData) { .speedAccuracyMetersPerSecond = 1, .bearingAccuracyDegrees = 90, .ageSeconds = 0.99}; TimeDebug timeDebug = {.timeEstimateMs = 1519930775453L, TimeDebug timeDebug = {.timeEstimateMs = static_cast<int64_t>( kMockTimestamp + ::android::elapsedRealtimeNano() / 1e6), .timeUncertaintyNs = 1000, .frequencyUncertaintyNsPerSec = 5.0e4}; std::vector<SatelliteData> satelliteDataArrayDebug = {}; .frequencyUncertaintyNsPerSec = 800}; SatelliteData satelliteData1 = { .svid = 3, .constellation = GnssConstellationType::GPS, .ephemerisType = SatelliteEphemerisType::EPHEMERIS, .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM, .ephemerisHealth = SatelliteEphemerisHealth::GOOD, .ephemerisAgeSeconds = 12, .serverPredictionIsAvailable = true, .serverPredictionAgeSeconds = 30}; SatelliteData satelliteData2 = { .svid = 5, .constellation = GnssConstellationType::GPS, .ephemerisType = SatelliteEphemerisType::EPHEMERIS, .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM, .ephemerisHealth = SatelliteEphemerisHealth::GOOD, .ephemerisAgeSeconds = 12, .serverPredictionIsAvailable = true, .serverPredictionAgeSeconds = 30}; SatelliteData satelliteData3 = { .svid = 17, .constellation = GnssConstellationType::GPS, .ephemerisType = SatelliteEphemerisType::EPHEMERIS, .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM, .ephemerisHealth = SatelliteEphemerisHealth::GOOD, .ephemerisAgeSeconds = 12, .serverPredictionIsAvailable = true, .serverPredictionAgeSeconds = 30}; SatelliteData satelliteData4 = { .svid = 26, .constellation = GnssConstellationType::GPS, .ephemerisType = SatelliteEphemerisType::EPHEMERIS, .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM, .ephemerisHealth = SatelliteEphemerisHealth::GOOD, .ephemerisAgeSeconds = 12, .serverPredictionIsAvailable = true, .serverPredictionAgeSeconds = 30}; SatelliteData satelliteData5 = { .svid = 5, .constellation = GnssConstellationType::GLONASS, .ephemerisType = SatelliteEphemerisType::EPHEMERIS, .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM, .ephemerisHealth = SatelliteEphemerisHealth::GOOD, .ephemerisAgeSeconds = 12, .serverPredictionIsAvailable = true, .serverPredictionAgeSeconds = 30}; SatelliteData satelliteData6 = { .svid = 17, .constellation = GnssConstellationType::GLONASS, .ephemerisType = SatelliteEphemerisType::EPHEMERIS, .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM, .ephemerisHealth = SatelliteEphemerisHealth::GOOD, .ephemerisAgeSeconds = 12, .serverPredictionIsAvailable = true, .serverPredictionAgeSeconds = 30}; SatelliteData satelliteData7 = { .svid = 18, .constellation = GnssConstellationType::GLONASS, .ephemerisType = SatelliteEphemerisType::EPHEMERIS, .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM, .ephemerisHealth = SatelliteEphemerisHealth::GOOD, .ephemerisAgeSeconds = 12, .serverPredictionIsAvailable = true, .serverPredictionAgeSeconds = 30}; SatelliteData satelliteData8 = { .svid = 10, .constellation = GnssConstellationType::GLONASS, .ephemerisType = SatelliteEphemerisType::EPHEMERIS, .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM, .ephemerisHealth = SatelliteEphemerisHealth::GOOD, .ephemerisAgeSeconds = 12, .serverPredictionIsAvailable = true, .serverPredictionAgeSeconds = 30}; SatelliteData satelliteData9 = { .svid = 3, .constellation = GnssConstellationType::IRNSS, .ephemerisType = SatelliteEphemerisType::EPHEMERIS, .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM, .ephemerisHealth = SatelliteEphemerisHealth::GOOD, .ephemerisAgeSeconds = 12, .serverPredictionIsAvailable = true, .serverPredictionAgeSeconds = 30}; std::vector<SatelliteData> satelliteDataArrayDebug = { satelliteData1, satelliteData2, satelliteData3, satelliteData4, satelliteData5, satelliteData6, satelliteData7, satelliteData8, satelliteData9}; debugData->position = positionDebug; debugData->time = timeDebug; debugData->satelliteDataArray = satelliteDataArrayDebug; Loading gnss/aidl/default/GnssDebug.h +2 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ namespace aidl::android::hardware::gnss { class Gnss; struct GnssDebug : public BnGnssDebug { public: ndk::ScopedAStatus getDebugData(DebugData* debugData) override; Loading gnss/aidl/vts/gnss_hal_test_cases.cpp +128 −29 Original line number Diff line number Diff line Loading @@ -1149,40 +1149,139 @@ TEST_P(GnssHalTest, GnssDebugValuesSanityTest) { sp<IGnssDebug> iGnssDebug; auto status = aidl_gnss_hal_->getExtensionGnssDebug(&iGnssDebug); ASSERT_TRUE(status.isOk()); if (!IsAutomotiveDevice()) { if (IsAutomotiveDevice()) { return; } ASSERT_TRUE(iGnssDebug != nullptr); IGnssDebug::DebugData data; auto status = iGnssDebug->getDebugData(&data); ASSERT_TRUE(status.isOk()); if (data.position.valid) { ASSERT_TRUE(data.position.latitudeDegrees >= -90 && data.position.latitudeDegrees <= 90); ASSERT_TRUE(data.position.longitudeDegrees >= -180 && data.position.longitudeDegrees <= 180); ASSERT_TRUE(data.position.altitudeMeters >= -1000 && // Dead Sea: -414m data.position.altitudeMeters <= 20000); // Mount Everest: 8850m ASSERT_TRUE(data.position.speedMetersPerSec >= 0 && data.position.speedMetersPerSec <= 600); ASSERT_TRUE(data.position.bearingDegrees >= -360 && data.position.bearingDegrees <= 360); ASSERT_TRUE(data.position.horizontalAccuracyMeters > 0 && data.position.horizontalAccuracyMeters <= 20000000); ASSERT_TRUE(data.position.verticalAccuracyMeters > 0 && data.position.verticalAccuracyMeters <= 20000); ASSERT_TRUE(data.position.speedAccuracyMetersPerSecond > 0 && data.position.speedAccuracyMetersPerSecond <= 500); ASSERT_TRUE(data.position.bearingAccuracyDegrees > 0 && data.position.bearingAccuracyDegrees <= 180); ASSERT_TRUE(data.position.ageSeconds >= 0); } ASSERT_TRUE(data.time.timeEstimateMs >= 1483228800000); // Jan 01 2017 00:00:00 GMT. ASSERT_TRUE(data.time.timeUncertaintyNs > 0); ASSERT_TRUE(data.time.frequencyUncertaintyNsPerSec > 0 && data.time.frequencyUncertaintyNsPerSec <= 2.0e5); // 200 ppm status = iGnssDebug->getDebugData(&data); ASSERT_TRUE(status.isOk()); Utils::checkPositionDebug(data); // Additional GnssDebug tests for AIDL version >= 4 (launched in Android 15(V)+) if (aidl_gnss_hal_->getInterfaceVersion() <= 3) { return; } // Start location and check the consistency between SvStatus and DebugData aidl_gnss_cb_->location_cbq_.reset(); aidl_gnss_cb_->sv_info_list_cbq_.reset(); StartAndCheckLocations(/* count= */ 2); int location_called_count = aidl_gnss_cb_->location_cbq_.calledCount(); ALOGD("Observed %d GnssSvStatus, while awaiting 2 locations (%d received)", aidl_gnss_cb_->sv_info_list_cbq_.size(), location_called_count); // Wait for up to kNumSvInfoLists events for kTimeoutSeconds for each event. int kTimeoutSeconds = 2; int kNumSvInfoLists = 4; std::list<std::vector<IGnssCallback::GnssSvInfo>> sv_info_lists; std::vector<IGnssCallback::GnssSvInfo> last_sv_info_list; do { EXPECT_GT(aidl_gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_lists, kNumSvInfoLists, kTimeoutSeconds), 0); if (!sv_info_lists.empty()) { last_sv_info_list = sv_info_lists.back(); ALOGD("last_sv_info size = %d", (int)last_sv_info_list.size()); } } while (!sv_info_lists.empty() && last_sv_info_list.size() == 0); StopAndClearLocations(); status = iGnssDebug->getDebugData(&data); Utils::checkPositionDebug(data); // Validate SatelliteEphemerisType, SatelliteEphemerisSource, SatelliteEphemerisHealth for (auto sv_info : last_sv_info_list) { if ((sv_info.svFlag & static_cast<int>(IGnssCallback::GnssSvFlags::USED_IN_FIX)) == 0) { continue; } ALOGD("Found usedInFix const: %d, svid: %d", static_cast<int>(sv_info.constellation), sv_info.svid); bool foundDebugData = false; for (auto satelliteData : data.satelliteDataArray) { if (satelliteData.constellation == sv_info.constellation && satelliteData.svid == sv_info.svid) { foundDebugData = true; ALOGD("Found GnssDebug data for this sv."); EXPECT_TRUE(satelliteData.serverPredictionIsAvailable || satelliteData.ephemerisType == IGnssDebug::SatelliteEphemerisType::EPHEMERIS); // for satellites with ephType=0, they need ephHealth=0 if used-in-fix if (satelliteData.ephemerisType == IGnssDebug::SatelliteEphemerisType::EPHEMERIS) { EXPECT_TRUE(satelliteData.ephemerisHealth == IGnssDebug::SatelliteEphemerisHealth::GOOD); } break; } } // Every Satellite where GnssStatus says it is used-in-fix has a valid ephemeris - i.e. it's // it shows either a serverPredAvail: 1, or a ephType=0 EXPECT_TRUE(foundDebugData); } bool hasServerPredictionAvailable = false; bool hasNoneZeroServerPredictionAgeSeconds = false; bool hasNoneDemodEphSource = false; for (auto satelliteData : data.satelliteDataArray) { // for satellites with serverPredAvail: 1, the serverPredAgeSec: is not 0 for all // satellites (at least not on 2 fixes in a row - it could get lucky once) if (satelliteData.serverPredictionIsAvailable) { hasServerPredictionAvailable = true; if (satelliteData.serverPredictionAgeSeconds != 0) { hasNoneZeroServerPredictionAgeSeconds = true; } } // for satellites with ephType=0, they need ephSource 0-3 if (satelliteData.ephemerisType == IGnssDebug::SatelliteEphemerisType::EPHEMERIS) { EXPECT_TRUE(satelliteData.ephemerisSource >= SatellitePvt::SatelliteEphemerisSource::DEMODULATED && satelliteData.ephemerisSource <= SatellitePvt::SatelliteEphemerisSource::OTHER); if (satelliteData.ephemerisSource != SatellitePvt::SatelliteEphemerisSource::DEMODULATED) { hasNoneDemodEphSource = true; } } } if (hasNoneDemodEphSource && hasServerPredictionAvailable) { EXPECT_TRUE(hasNoneZeroServerPredictionAgeSeconds); } /** - Gnss Location Data:: should show some valid information, ideally reasonably close (+/-1km) to the Location output - at least after the 2nd valid location output (maybe in general, wait for 2 good Location outputs before checking this, in case they don't update the assistance until after they output the Location) */ double distanceM = Utils::distanceMeters(data.position.latitudeDegrees, data.position.longitudeDegrees, aidl_gnss_cb_->last_location_.latitudeDegrees, aidl_gnss_cb_->last_location_.longitudeDegrees); ALOGD("distance between debug position and last position: %.2lf", distanceM); EXPECT_LT(distanceM, 1000.0); // 1km /** - Gnss Time Data:: timeEstimate should be reasonably close to the current GPS time. - Gnss Time Data:: timeUncertaintyNs should always be > 0 and < 5e9 (could be large due to solve-for-time type solutions) - Gnss Time Data:: frequencyUncertaintyNsPerSec: should always be > 0 and < 1000 (1000 ns/s corresponds to roughly a 300 m/s speed error, which should be pretty rare) */ ALOGD("debug time: %" PRId64 ", position time: %" PRId64, data.time.timeEstimateMs, aidl_gnss_cb_->last_location_.timestampMillis); // Allowing 5s between the last location time and the current GPS time EXPECT_LT(abs(data.time.timeEstimateMs - aidl_gnss_cb_->last_location_.timestampMillis), 5000); ALOGD("debug time uncertainty: %f ns", data.time.timeUncertaintyNs); EXPECT_GT(data.time.timeUncertaintyNs, 0); EXPECT_LT(data.time.timeUncertaintyNs, 5e9); ALOGD("debug freq uncertainty: %f ns/s", data.time.frequencyUncertaintyNsPerSec); EXPECT_GT(data.time.frequencyUncertaintyNsPerSec, 0); EXPECT_LT(data.time.frequencyUncertaintyNsPerSec, 1000); } /* Loading Loading
gnss/aidl/default/Gnss.cpp +6 −2 Original line number Diff line number Diff line Loading @@ -162,12 +162,13 @@ ScopedAStatus Gnss::close() { return ScopedAStatus::ok(); } void Gnss::reportLocation(const GnssLocation& location) const { void Gnss::reportLocation(const GnssLocation& location) { std::unique_lock<std::mutex> lock(mMutex); if (sGnssCallback == nullptr) { ALOGE("%s: GnssCallback is null.", __func__); return; } mLastLocation = std::make_shared<GnssLocation>(location); auto status = sGnssCallback->gnssLocationCb(location); if (!status.isOk()) { ALOGE("%s: Unable to invoke gnssLocationCb", __func__); Loading Loading @@ -359,7 +360,6 @@ ScopedAStatus Gnss::getExtensionGnssNavigationMessage( ndk::ScopedAStatus Gnss::getExtensionGnssDebug(std::shared_ptr<IGnssDebug>* iGnssDebug) { ALOGD("Gnss::getExtensionGnssDebug"); *iGnssDebug = SharedRefBase::make<GnssDebug>(); return ndk::ScopedAStatus::ok(); } Loading Loading @@ -398,4 +398,8 @@ void Gnss::setGnssMeasurementInterval(const long intervalMs) { mGnssMeasurementIntervalMs = intervalMs; } std::shared_ptr<GnssLocation> Gnss::getLastLocation() const { return mLastLocation; } } // namespace aidl::android::hardware::gnss
gnss/aidl/default/Gnss.h +5 −3 Original line number Diff line number Diff line Loading @@ -87,18 +87,19 @@ class Gnss : public BnGnss { void reportSvStatus() const; void setGnssMeasurementEnabled(const bool enabled); void setGnssMeasurementInterval(const long intervalMs); std::shared_ptr<GnssLocation> getLastLocation() const; std::shared_ptr<GnssConfiguration> mGnssConfiguration; std::shared_ptr<GnssPowerIndication> mGnssPowerIndication; std::shared_ptr<GnssMeasurementInterface> mGnssMeasurementInterface; private: void reportLocation(const GnssLocation&) const; void reportLocation(const GnssLocation&); void reportSvStatus(const std::vector<IGnssCallback::GnssSvInfo>& svInfoList) const; void reportGnssStatusValue(const IGnssCallback::GnssStatusValue gnssStatusValue) const; void reportNmea() const; std::vector<IGnssCallback::GnssSvInfo> filterBlocklistedSatellites( std::vector<IGnssCallback::GnssSvInfo> gnssSvInfoList) const; void reportGnssStatusValue(const IGnssCallback::GnssStatusValue gnssStatusValue) const; std::unique_ptr<GnssLocation> getLocationFromHW(); void reportNmea() const; static std::shared_ptr<IGnssCallback> sGnssCallback; Loading @@ -109,6 +110,7 @@ class Gnss : public BnGnss { std::atomic<bool> mIsNmeaActive; std::atomic<bool> mFirstFixReceived; std::atomic<bool> mGnssMeasurementEnabled; std::shared_ptr<GnssLocation> mLastLocation; std::thread mThread; ::android::hardware::gnss::common::ThreadBlocker mThreadBlocker; Loading
gnss/aidl/default/GnssDebug.cpp +92 −3 Original line number Diff line number Diff line Loading @@ -18,10 +18,15 @@ #include "GnssDebug.h" #include <log/log.h> #include <utils/SystemClock.h> #include "Constants.h" #include "Gnss.h" #include "MockLocation.h" namespace aidl::android::hardware::gnss { using ::android::hardware::gnss::common::kMockTimestamp; ndk::ScopedAStatus GnssDebug::getDebugData(DebugData* debugData) { ALOGD("GnssDebug::getDebugData"); Loading @@ -36,10 +41,94 @@ ndk::ScopedAStatus GnssDebug::getDebugData(DebugData* debugData) { .speedAccuracyMetersPerSecond = 1, .bearingAccuracyDegrees = 90, .ageSeconds = 0.99}; TimeDebug timeDebug = {.timeEstimateMs = 1519930775453L, TimeDebug timeDebug = {.timeEstimateMs = static_cast<int64_t>( kMockTimestamp + ::android::elapsedRealtimeNano() / 1e6), .timeUncertaintyNs = 1000, .frequencyUncertaintyNsPerSec = 5.0e4}; std::vector<SatelliteData> satelliteDataArrayDebug = {}; .frequencyUncertaintyNsPerSec = 800}; SatelliteData satelliteData1 = { .svid = 3, .constellation = GnssConstellationType::GPS, .ephemerisType = SatelliteEphemerisType::EPHEMERIS, .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM, .ephemerisHealth = SatelliteEphemerisHealth::GOOD, .ephemerisAgeSeconds = 12, .serverPredictionIsAvailable = true, .serverPredictionAgeSeconds = 30}; SatelliteData satelliteData2 = { .svid = 5, .constellation = GnssConstellationType::GPS, .ephemerisType = SatelliteEphemerisType::EPHEMERIS, .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM, .ephemerisHealth = SatelliteEphemerisHealth::GOOD, .ephemerisAgeSeconds = 12, .serverPredictionIsAvailable = true, .serverPredictionAgeSeconds = 30}; SatelliteData satelliteData3 = { .svid = 17, .constellation = GnssConstellationType::GPS, .ephemerisType = SatelliteEphemerisType::EPHEMERIS, .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM, .ephemerisHealth = SatelliteEphemerisHealth::GOOD, .ephemerisAgeSeconds = 12, .serverPredictionIsAvailable = true, .serverPredictionAgeSeconds = 30}; SatelliteData satelliteData4 = { .svid = 26, .constellation = GnssConstellationType::GPS, .ephemerisType = SatelliteEphemerisType::EPHEMERIS, .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM, .ephemerisHealth = SatelliteEphemerisHealth::GOOD, .ephemerisAgeSeconds = 12, .serverPredictionIsAvailable = true, .serverPredictionAgeSeconds = 30}; SatelliteData satelliteData5 = { .svid = 5, .constellation = GnssConstellationType::GLONASS, .ephemerisType = SatelliteEphemerisType::EPHEMERIS, .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM, .ephemerisHealth = SatelliteEphemerisHealth::GOOD, .ephemerisAgeSeconds = 12, .serverPredictionIsAvailable = true, .serverPredictionAgeSeconds = 30}; SatelliteData satelliteData6 = { .svid = 17, .constellation = GnssConstellationType::GLONASS, .ephemerisType = SatelliteEphemerisType::EPHEMERIS, .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM, .ephemerisHealth = SatelliteEphemerisHealth::GOOD, .ephemerisAgeSeconds = 12, .serverPredictionIsAvailable = true, .serverPredictionAgeSeconds = 30}; SatelliteData satelliteData7 = { .svid = 18, .constellation = GnssConstellationType::GLONASS, .ephemerisType = SatelliteEphemerisType::EPHEMERIS, .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM, .ephemerisHealth = SatelliteEphemerisHealth::GOOD, .ephemerisAgeSeconds = 12, .serverPredictionIsAvailable = true, .serverPredictionAgeSeconds = 30}; SatelliteData satelliteData8 = { .svid = 10, .constellation = GnssConstellationType::GLONASS, .ephemerisType = SatelliteEphemerisType::EPHEMERIS, .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM, .ephemerisHealth = SatelliteEphemerisHealth::GOOD, .ephemerisAgeSeconds = 12, .serverPredictionIsAvailable = true, .serverPredictionAgeSeconds = 30}; SatelliteData satelliteData9 = { .svid = 3, .constellation = GnssConstellationType::IRNSS, .ephemerisType = SatelliteEphemerisType::EPHEMERIS, .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM, .ephemerisHealth = SatelliteEphemerisHealth::GOOD, .ephemerisAgeSeconds = 12, .serverPredictionIsAvailable = true, .serverPredictionAgeSeconds = 30}; std::vector<SatelliteData> satelliteDataArrayDebug = { satelliteData1, satelliteData2, satelliteData3, satelliteData4, satelliteData5, satelliteData6, satelliteData7, satelliteData8, satelliteData9}; debugData->position = positionDebug; debugData->time = timeDebug; debugData->satelliteDataArray = satelliteDataArrayDebug; Loading
gnss/aidl/default/GnssDebug.h +2 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ namespace aidl::android::hardware::gnss { class Gnss; struct GnssDebug : public BnGnssDebug { public: ndk::ScopedAStatus getDebugData(DebugData* debugData) override; Loading
gnss/aidl/vts/gnss_hal_test_cases.cpp +128 −29 Original line number Diff line number Diff line Loading @@ -1149,40 +1149,139 @@ TEST_P(GnssHalTest, GnssDebugValuesSanityTest) { sp<IGnssDebug> iGnssDebug; auto status = aidl_gnss_hal_->getExtensionGnssDebug(&iGnssDebug); ASSERT_TRUE(status.isOk()); if (!IsAutomotiveDevice()) { if (IsAutomotiveDevice()) { return; } ASSERT_TRUE(iGnssDebug != nullptr); IGnssDebug::DebugData data; auto status = iGnssDebug->getDebugData(&data); ASSERT_TRUE(status.isOk()); if (data.position.valid) { ASSERT_TRUE(data.position.latitudeDegrees >= -90 && data.position.latitudeDegrees <= 90); ASSERT_TRUE(data.position.longitudeDegrees >= -180 && data.position.longitudeDegrees <= 180); ASSERT_TRUE(data.position.altitudeMeters >= -1000 && // Dead Sea: -414m data.position.altitudeMeters <= 20000); // Mount Everest: 8850m ASSERT_TRUE(data.position.speedMetersPerSec >= 0 && data.position.speedMetersPerSec <= 600); ASSERT_TRUE(data.position.bearingDegrees >= -360 && data.position.bearingDegrees <= 360); ASSERT_TRUE(data.position.horizontalAccuracyMeters > 0 && data.position.horizontalAccuracyMeters <= 20000000); ASSERT_TRUE(data.position.verticalAccuracyMeters > 0 && data.position.verticalAccuracyMeters <= 20000); ASSERT_TRUE(data.position.speedAccuracyMetersPerSecond > 0 && data.position.speedAccuracyMetersPerSecond <= 500); ASSERT_TRUE(data.position.bearingAccuracyDegrees > 0 && data.position.bearingAccuracyDegrees <= 180); ASSERT_TRUE(data.position.ageSeconds >= 0); } ASSERT_TRUE(data.time.timeEstimateMs >= 1483228800000); // Jan 01 2017 00:00:00 GMT. ASSERT_TRUE(data.time.timeUncertaintyNs > 0); ASSERT_TRUE(data.time.frequencyUncertaintyNsPerSec > 0 && data.time.frequencyUncertaintyNsPerSec <= 2.0e5); // 200 ppm status = iGnssDebug->getDebugData(&data); ASSERT_TRUE(status.isOk()); Utils::checkPositionDebug(data); // Additional GnssDebug tests for AIDL version >= 4 (launched in Android 15(V)+) if (aidl_gnss_hal_->getInterfaceVersion() <= 3) { return; } // Start location and check the consistency between SvStatus and DebugData aidl_gnss_cb_->location_cbq_.reset(); aidl_gnss_cb_->sv_info_list_cbq_.reset(); StartAndCheckLocations(/* count= */ 2); int location_called_count = aidl_gnss_cb_->location_cbq_.calledCount(); ALOGD("Observed %d GnssSvStatus, while awaiting 2 locations (%d received)", aidl_gnss_cb_->sv_info_list_cbq_.size(), location_called_count); // Wait for up to kNumSvInfoLists events for kTimeoutSeconds for each event. int kTimeoutSeconds = 2; int kNumSvInfoLists = 4; std::list<std::vector<IGnssCallback::GnssSvInfo>> sv_info_lists; std::vector<IGnssCallback::GnssSvInfo> last_sv_info_list; do { EXPECT_GT(aidl_gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_lists, kNumSvInfoLists, kTimeoutSeconds), 0); if (!sv_info_lists.empty()) { last_sv_info_list = sv_info_lists.back(); ALOGD("last_sv_info size = %d", (int)last_sv_info_list.size()); } } while (!sv_info_lists.empty() && last_sv_info_list.size() == 0); StopAndClearLocations(); status = iGnssDebug->getDebugData(&data); Utils::checkPositionDebug(data); // Validate SatelliteEphemerisType, SatelliteEphemerisSource, SatelliteEphemerisHealth for (auto sv_info : last_sv_info_list) { if ((sv_info.svFlag & static_cast<int>(IGnssCallback::GnssSvFlags::USED_IN_FIX)) == 0) { continue; } ALOGD("Found usedInFix const: %d, svid: %d", static_cast<int>(sv_info.constellation), sv_info.svid); bool foundDebugData = false; for (auto satelliteData : data.satelliteDataArray) { if (satelliteData.constellation == sv_info.constellation && satelliteData.svid == sv_info.svid) { foundDebugData = true; ALOGD("Found GnssDebug data for this sv."); EXPECT_TRUE(satelliteData.serverPredictionIsAvailable || satelliteData.ephemerisType == IGnssDebug::SatelliteEphemerisType::EPHEMERIS); // for satellites with ephType=0, they need ephHealth=0 if used-in-fix if (satelliteData.ephemerisType == IGnssDebug::SatelliteEphemerisType::EPHEMERIS) { EXPECT_TRUE(satelliteData.ephemerisHealth == IGnssDebug::SatelliteEphemerisHealth::GOOD); } break; } } // Every Satellite where GnssStatus says it is used-in-fix has a valid ephemeris - i.e. it's // it shows either a serverPredAvail: 1, or a ephType=0 EXPECT_TRUE(foundDebugData); } bool hasServerPredictionAvailable = false; bool hasNoneZeroServerPredictionAgeSeconds = false; bool hasNoneDemodEphSource = false; for (auto satelliteData : data.satelliteDataArray) { // for satellites with serverPredAvail: 1, the serverPredAgeSec: is not 0 for all // satellites (at least not on 2 fixes in a row - it could get lucky once) if (satelliteData.serverPredictionIsAvailable) { hasServerPredictionAvailable = true; if (satelliteData.serverPredictionAgeSeconds != 0) { hasNoneZeroServerPredictionAgeSeconds = true; } } // for satellites with ephType=0, they need ephSource 0-3 if (satelliteData.ephemerisType == IGnssDebug::SatelliteEphemerisType::EPHEMERIS) { EXPECT_TRUE(satelliteData.ephemerisSource >= SatellitePvt::SatelliteEphemerisSource::DEMODULATED && satelliteData.ephemerisSource <= SatellitePvt::SatelliteEphemerisSource::OTHER); if (satelliteData.ephemerisSource != SatellitePvt::SatelliteEphemerisSource::DEMODULATED) { hasNoneDemodEphSource = true; } } } if (hasNoneDemodEphSource && hasServerPredictionAvailable) { EXPECT_TRUE(hasNoneZeroServerPredictionAgeSeconds); } /** - Gnss Location Data:: should show some valid information, ideally reasonably close (+/-1km) to the Location output - at least after the 2nd valid location output (maybe in general, wait for 2 good Location outputs before checking this, in case they don't update the assistance until after they output the Location) */ double distanceM = Utils::distanceMeters(data.position.latitudeDegrees, data.position.longitudeDegrees, aidl_gnss_cb_->last_location_.latitudeDegrees, aidl_gnss_cb_->last_location_.longitudeDegrees); ALOGD("distance between debug position and last position: %.2lf", distanceM); EXPECT_LT(distanceM, 1000.0); // 1km /** - Gnss Time Data:: timeEstimate should be reasonably close to the current GPS time. - Gnss Time Data:: timeUncertaintyNs should always be > 0 and < 5e9 (could be large due to solve-for-time type solutions) - Gnss Time Data:: frequencyUncertaintyNsPerSec: should always be > 0 and < 1000 (1000 ns/s corresponds to roughly a 300 m/s speed error, which should be pretty rare) */ ALOGD("debug time: %" PRId64 ", position time: %" PRId64, data.time.timeEstimateMs, aidl_gnss_cb_->last_location_.timestampMillis); // Allowing 5s between the last location time and the current GPS time EXPECT_LT(abs(data.time.timeEstimateMs - aidl_gnss_cb_->last_location_.timestampMillis), 5000); ALOGD("debug time uncertainty: %f ns", data.time.timeUncertaintyNs); EXPECT_GT(data.time.timeUncertaintyNs, 0); EXPECT_LT(data.time.timeUncertaintyNs, 5e9); ALOGD("debug freq uncertainty: %f ns/s", data.time.frequencyUncertaintyNsPerSec); EXPECT_GT(data.time.frequencyUncertaintyNsPerSec, 0); EXPECT_LT(data.time.frequencyUncertaintyNsPerSec, 1000); } /* Loading