Loading gnss/aidl/default/GnssDebug.cpp +39 −2 Original line number Diff line number Diff line Loading @@ -126,9 +126,46 @@ ndk::ScopedAStatus GnssDebug::getDebugData(DebugData* debugData) { .ephemerisAgeSeconds = 12, .serverPredictionIsAvailable = true, .serverPredictionAgeSeconds = 30}; SatelliteData satelliteData10 = { .svid = 2, .constellation = GnssConstellationType::GALILEO, .ephemerisType = SatelliteEphemerisType::EPHEMERIS, .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM, .ephemerisHealth = SatelliteEphemerisHealth::GOOD, .ephemerisAgeSeconds = 12, .serverPredictionIsAvailable = true, .serverPredictionAgeSeconds = 30}; SatelliteData satelliteData11 = { .svid = 4, .constellation = GnssConstellationType::GALILEO, .ephemerisType = SatelliteEphemerisType::EPHEMERIS, .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM, .ephemerisHealth = SatelliteEphemerisHealth::GOOD, .ephemerisAgeSeconds = 12, .serverPredictionIsAvailable = true, .serverPredictionAgeSeconds = 30}; SatelliteData satelliteData12 = { .svid = 10, .constellation = GnssConstellationType::GALILEO, .ephemerisType = SatelliteEphemerisType::EPHEMERIS, .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM, .ephemerisHealth = SatelliteEphemerisHealth::GOOD, .ephemerisAgeSeconds = 12, .serverPredictionIsAvailable = true, .serverPredictionAgeSeconds = 30}; SatelliteData satelliteData13 = { .svid = 29, .constellation = GnssConstellationType::GALILEO, .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}; satelliteData6, satelliteData7, satelliteData8, satelliteData9, satelliteData10, satelliteData11, satelliteData12, satelliteData13}; debugData->position = positionDebug; debugData->time = timeDebug; debugData->satelliteDataArray = satelliteDataArrayDebug; Loading gnss/aidl/vts/gnss_hal_test.cpp +89 −32 Original line number Diff line number Diff line Loading @@ -276,35 +276,43 @@ std::list<std::vector<IGnssCallback::GnssSvInfo>> GnssHalTest::convertToAidl( } /* * FindStrongFrequentBlockableSource: * FindStrongFrequentSource: * * Search through a GnssSvStatus list for the strongest blockable satellite observed enough times * Search through a GnssSvStatus list for the strongest satellite observed enough times per * constellation * * returns the strongest source, * or a source with constellation == UNKNOWN if none are found sufficient times * returns the strongest sources for each constellation, * or an empty vector if none are found sufficient times */ BlocklistedSource GnssHalTest::FindStrongFrequentBlockableSource( std::vector<BlocklistedSource> GnssHalTest::FindStrongFrequentSources( const std::list<hidl_vec<IGnssCallback_2_1::GnssSvInfo>> sv_info_list, const int min_observations) { return FindStrongFrequentBlockableSource(convertToAidl(sv_info_list), min_observations); return FindStrongFrequentSources(convertToAidl(sv_info_list), min_observations); } BlocklistedSource GnssHalTest::FindStrongFrequentBlockableSource( bool GnssHalTest::isBlockableConstellation(const GnssConstellationType constellation, const bool isCnBuild) { if (constellation == GnssConstellationType::GPS) { return false; } if (isCnBuild && (constellation == GnssConstellationType::BEIDOU)) { // Do not blocklist BDS on CN builds return false; } return true; } std::vector<BlocklistedSource> GnssHalTest::FindStrongFrequentSources( const std::list<std::vector<IGnssCallback::GnssSvInfo>> sv_info_list, const int min_observations) { std::map<ComparableBlocklistedSource, SignalCounts> mapSignals; ALOGD("Find strongest sv from %d sv_info_list with %d min_observations.", (int)sv_info_list.size(), min_observations); bool isCnBuild = Utils::isCnBuild(); ALOGD("isCnBuild: %s", isCnBuild ? "true" : "false"); std::map<ComparableBlocklistedSource, SignalCounts> mapSignals; for (const auto& sv_info_vec : sv_info_list) { for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) { const auto& gnss_sv = sv_info_vec[iSv]; if ((gnss_sv.svFlag & (int)IGnssCallback::GnssSvFlags::USED_IN_FIX) && (gnss_sv.constellation != GnssConstellationType::GPS)) { if (isCnBuild && (gnss_sv.constellation == GnssConstellationType::BEIDOU)) { // Do not blocklist BDS on CN builds continue; } if (gnss_sv.svFlag & (int)IGnssCallback::GnssSvFlags::USED_IN_FIX) { ComparableBlocklistedSource source; source.id.svid = gnss_sv.svid; source.id.constellation = gnss_sv.constellation; Loading @@ -326,27 +334,76 @@ BlocklistedSource GnssHalTest::FindStrongFrequentBlockableSource( } } float max_cn0_dbhz_with_sufficient_count = 0.; int total_observation_count = 0; int blocklisted_source_count_observation = 0; // the Cn0 of the strongest SV per constellation std::unordered_map<GnssConstellationType, float> max_cn0_map; // # of total observations of all signals per constellation std::unordered_map<GnssConstellationType, int> total_observation_count_map; // # of observations of the strongest sv per constellation std::unordered_map<GnssConstellationType, int> source_observation_count_map; // the source to blocklist per constellation std::unordered_map<GnssConstellationType, ComparableBlocklistedSource> source_map; // # of signals per constellation std::unordered_map<GnssConstellationType, int> signal_count_map; ComparableBlocklistedSource source_to_blocklist; // initializes to zero = UNKNOWN constellation for (auto const& pairSignal : mapSignals) { total_observation_count += pairSignal.second.observations; if ((pairSignal.second.observations >= min_observations) && (pairSignal.second.max_cn0_dbhz > max_cn0_dbhz_with_sufficient_count)) { source_to_blocklist = pairSignal.first; blocklisted_source_count_observation = pairSignal.second.observations; max_cn0_dbhz_with_sufficient_count = pairSignal.second.max_cn0_dbhz; ComparableBlocklistedSource source = pairSignal.first; total_observation_count_map[source.id.constellation] += pairSignal.second.observations; signal_count_map[source.id.constellation]++; if (pairSignal.second.observations < min_observations) { continue; } if (pairSignal.second.max_cn0_dbhz > max_cn0_map[source.id.constellation]) { source_map[source.id.constellation] = pairSignal.first; source_observation_count_map[source.id.constellation] = pairSignal.second.observations; max_cn0_map[source.id.constellation] = pairSignal.second.max_cn0_dbhz; } } std::vector<BlocklistedSource> sources; if (aidl_gnss_hal_->getInterfaceVersion() <= 4) { /* For AIDL version <= 4 (launched-in-15 or earlier), only blocklist 1 sv */ float max_cn0 = 0; ComparableBlocklistedSource source_to_blocklist; for (auto const& pair : source_map) { GnssConstellationType constellation = pair.first; ComparableBlocklistedSource source = pair.second; if (max_cn0_map[constellation] > max_cn0) { max_cn0 = max_cn0_map[constellation]; source_to_blocklist = source; } } if (source_to_blocklist.id.constellation != GnssConstellationType::UNKNOWN) { ALOGD("In constellation %d, among %d observed SVs, svid %d is chosen to blocklist. " "It has %d observations with max Cn0: %.1f among %d total observations of this " "constellation.", (int)source_to_blocklist.id.constellation, signal_count_map[source_to_blocklist.id.constellation], source_to_blocklist.id.svid, source_observation_count_map[source_to_blocklist.id.constellation], max_cn0, total_observation_count_map[source_to_blocklist.id.constellation]); sources.push_back(source_to_blocklist.id); } } else { /* For AIDL version >= 5 (launched-in-16 or later), blocklist 1 sv per constellation */ for (auto const& pair : source_map) { ComparableBlocklistedSource source = pair.second; if (signal_count_map[source.id.constellation] < 4) { // Skip the constellation with a small number of signals // 4 is arbitrarily chosen to avoid affecting constellations with a limited coverage continue; } ALOGD("In constellation %d, among %d observed SVs, svid %d is chosen to blocklist. " "It has %d observations with max Cn0: %.1f among %d total observations of this " "constellation.", (int)source.id.constellation, signal_count_map[source.id.constellation], source.id.svid, source_observation_count_map[source.id.constellation], max_cn0_map[source.id.constellation], total_observation_count_map[source.id.constellation]); sources.push_back(source.id); } } ALOGD("Among %d observations, chose svid %d, constellation %d, " "with %d observations at %.1f max CNo", total_observation_count, source_to_blocklist.id.svid, (int)source_to_blocklist.id.constellation, blocklisted_source_count_observation, max_cn0_dbhz_with_sufficient_count); return source_to_blocklist.id; return sources; } GnssConstellationType GnssHalTest::startLocationAndGetBlockableConstellation( Loading gnss/aidl/vts/gnss_hal_test.h +5 −2 Original line number Diff line number Diff line Loading @@ -81,14 +81,17 @@ class GnssHalTest : public android::hardware::gnss::common::GnssHalTestTemplate< std::list<std::vector<android::hardware::gnss::IGnssCallback::GnssSvInfo>> convertToAidl( const std::list<hidl_vec<android::hardware::gnss::V2_1::IGnssCallback::GnssSvInfo>>& sv_info_list); android::hardware::gnss::BlocklistedSource FindStrongFrequentBlockableSource( std::vector<android::hardware::gnss::BlocklistedSource> FindStrongFrequentSources( const std::list<hidl_vec<android::hardware::gnss::V2_1::IGnssCallback::GnssSvInfo>> sv_info_list, const int min_observations); android::hardware::gnss::BlocklistedSource FindStrongFrequentBlockableSource( std::vector<android::hardware::gnss::BlocklistedSource> FindStrongFrequentSources( const std::list<std::vector<android::hardware::gnss::IGnssCallback::GnssSvInfo>> sv_info_list, const int min_observations); bool isBlockableConstellation( const android::hardware::gnss::GnssConstellationType constellation, const bool isCnBuild); void checkGnssMeasurementClockFields(const android::hardware::gnss::GnssData& measurement); void checkGnssMeasurementFlags(const android::hardware::gnss::GnssMeasurement& measurement); Loading gnss/aidl/vts/gnss_hal_test_cases.cpp +81 −43 Original line number Diff line number Diff line Loading @@ -615,7 +615,7 @@ TEST_P(GnssHalTest, TestGnssPowerIndication) { * BlocklistIndividualSatellites: * * 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding * GnssStatus for common satellites (strongest and one other.) * GnssStatus for common satellites (strongest one in each constellation.) * 2a & b) Turns off location, and blocklists common satellites. * 3) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding * GnssStatus does not use those satellites. Loading @@ -633,6 +633,7 @@ TEST_P(GnssHalTest, BlocklistIndividualSatellites) { return; } const int kWarmUpLocations = 3; const int kLocationsToAwait = 3; const int kRetriesToUnBlocklist = 10; Loading @@ -641,7 +642,7 @@ TEST_P(GnssHalTest, BlocklistIndividualSatellites) { } else { aidl_gnss_cb_->location_cbq_.reset(); } StartAndCheckLocations(kLocationsToAwait); StartAndCheckLocations(kLocationsToAwait + kWarmUpLocations); int location_called_count = (aidl_gnss_hal_->getInterfaceVersion() <= 1) ? gnss_cb_->location_cbq_.calledCount() : aidl_gnss_cb_->location_cbq_.calledCount(); Loading @@ -650,37 +651,50 @@ TEST_P(GnssHalTest, BlocklistIndividualSatellites) { int sv_info_list_cbq_size = (aidl_gnss_hal_->getInterfaceVersion() <= 1) ? gnss_cb_->sv_info_list_cbq_.size() : aidl_gnss_cb_->sv_info_list_cbq_.size(); EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait); EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait + kWarmUpLocations); ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations (%d received)", sv_info_list_cbq_size, kLocationsToAwait, location_called_count); sv_info_list_cbq_size, kLocationsToAwait + kWarmUpLocations, location_called_count); /* * Identify strongest SV seen at least kLocationsToAwait -1 times * Why -1? To avoid test flakiness in case of (plausible) slight flakiness in strongest signal * observability (one epoch RF null) * Identify strongest SV per constellation seen seen at least kLocationsToAwait -1 times. * * Why not (kLocationsToAwait + kWarmUpLocations)? To avoid test flakiness in case of * (plausible) slight flakiness in strongest signal observability (one epoch RF null) */ const int kGnssSvInfoListTimeout = 2; BlocklistedSource source_to_blocklist; std::vector<BlocklistedSource> sources_to_blocklist; if (aidl_gnss_hal_->getInterfaceVersion() <= 1) { // Discard kWarmUpLocations sv_info_vec std::list<hidl_vec<IGnssCallback_2_1::GnssSvInfo>> tmp; int count = gnss_cb_->sv_info_list_cbq_.retrieve(tmp, kWarmUpLocations, kGnssSvInfoListTimeout); ASSERT_EQ(count, kWarmUpLocations); // Retrieve (sv_info_list_cbq_size - kWarmUpLocations) sv_info_vec std::list<hidl_vec<IGnssCallback_2_1::GnssSvInfo>> sv_info_vec_list; int count = gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec_list, sv_info_list_cbq_size, kGnssSvInfoListTimeout); ASSERT_EQ(count, sv_info_list_cbq_size); source_to_blocklist = FindStrongFrequentBlockableSource(sv_info_vec_list, kLocationsToAwait - 1); count = gnss_cb_->sv_info_list_cbq_.retrieve( sv_info_vec_list, sv_info_list_cbq_size - kWarmUpLocations, kGnssSvInfoListTimeout); ASSERT_EQ(count, sv_info_list_cbq_size - kWarmUpLocations); sources_to_blocklist = FindStrongFrequentSources(sv_info_vec_list, kLocationsToAwait - 1); } else { // Discard kWarmUpLocations sv_info_vec std::list<std::vector<IGnssCallback::GnssSvInfo>> tmp; int count = aidl_gnss_cb_->sv_info_list_cbq_.retrieve(tmp, kWarmUpLocations, kGnssSvInfoListTimeout); ASSERT_EQ(count, kWarmUpLocations); // Retrieve (sv_info_list_cbq_size - kWarmUpLocations) sv_info_vec std::list<std::vector<IGnssCallback::GnssSvInfo>> sv_info_vec_list; int count = aidl_gnss_cb_->sv_info_list_cbq_.retrieve( sv_info_vec_list, sv_info_list_cbq_size, kGnssSvInfoListTimeout); ASSERT_EQ(count, sv_info_list_cbq_size); source_to_blocklist = FindStrongFrequentBlockableSource(sv_info_vec_list, kLocationsToAwait - 1); count = aidl_gnss_cb_->sv_info_list_cbq_.retrieve( sv_info_vec_list, sv_info_list_cbq_size - kWarmUpLocations, kGnssSvInfoListTimeout); ASSERT_EQ(count, sv_info_list_cbq_size - kWarmUpLocations); sources_to_blocklist = FindStrongFrequentSources(sv_info_vec_list, kLocationsToAwait - 1); } if (source_to_blocklist.constellation == GnssConstellationType::UNKNOWN) { // Cannot find a blockable satellite. Let the test pass. ALOGD("Cannot find a blockable satellite. Letting the test pass."); if (sources_to_blocklist.empty()) { // Cannot find a satellite to blocklist. Let the test pass. ALOGD("Cannot find a satellite to blocklist. Letting the test pass."); return; } Loading @@ -693,9 +707,7 @@ TEST_P(GnssHalTest, BlocklistIndividualSatellites) { ASSERT_NE(gnss_configuration_hal, nullptr); std::vector<BlocklistedSource> sources; sources.resize(1); sources[0] = source_to_blocklist; sources = sources_to_blocklist; status = gnss_configuration_hal->setBlocklist(sources); ASSERT_TRUE(status.isOk()); Loading Loading @@ -726,26 +738,47 @@ TEST_P(GnssHalTest, BlocklistIndividualSatellites) { EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait); ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations (%d received)", sv_info_list_cbq_size, kLocationsToAwait, location_called_count); bool isCnBuild = Utils::isCnBuild(); for (int i = 0; i < sv_info_list_cbq_size; ++i) { if (aidl_gnss_hal_->getInterfaceVersion() <= 1) { hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec; gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout); for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) { auto& gnss_sv = sv_info_vec[iSv]; EXPECT_FALSE( (gnss_sv.v2_0.v1_0.svid == source_to_blocklist.svid) && if (!(gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX)) { continue; } for (auto const& source : sources_to_blocklist) { if (isBlockableConstellation(source.constellation, isCnBuild)) { EXPECT_FALSE((gnss_sv.v2_0.v1_0.svid == source.svid) && (static_cast<GnssConstellationType>( gnss_sv.v2_0.constellation) == source.constellation)); } else if ((gnss_sv.v2_0.v1_0.svid == source.svid) && (static_cast<GnssConstellationType>(gnss_sv.v2_0.constellation) == source_to_blocklist.constellation) && (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX)); source.constellation)) { ALOGW("Found constellation %d, svid %d blocklisted but still used-in-fix.", source.constellation, source.svid); } } } } else { std::vector<IGnssCallback::GnssSvInfo> sv_info_vec; aidl_gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout); for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) { auto& gnss_sv = sv_info_vec[iSv]; EXPECT_FALSE((gnss_sv.svid == source_to_blocklist.svid) && (gnss_sv.constellation == source_to_blocklist.constellation) && (gnss_sv.svFlag & (int)IGnssCallback::GnssSvFlags::USED_IN_FIX)); if (!(gnss_sv.svFlag & (int)IGnssCallback::GnssSvFlags::USED_IN_FIX)) { continue; } for (auto const& source : sources_to_blocklist) { if (isBlockableConstellation(source.constellation, isCnBuild)) { EXPECT_FALSE((gnss_sv.svid == source.svid) && (gnss_sv.constellation == source.constellation)); } else if ((gnss_sv.svid == source.svid) && (gnss_sv.constellation == source.constellation)) { ALOGW("Found constellation %d, svid %d blocklisted but still used-in-fix.", gnss_sv.constellation, gnss_sv.svid); } } } } } Loading Loading @@ -795,27 +828,32 @@ TEST_P(GnssHalTest, BlocklistIndividualSatellites) { gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout); for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) { auto& gnss_sv = sv_info_vec[iSv]; if ((gnss_sv.v2_0.v1_0.svid == source_to_blocklist.svid) && for (auto const& source : sources_to_blocklist) { if ((gnss_sv.v2_0.v1_0.svid == source.svid) && (static_cast<GnssConstellationType>(gnss_sv.v2_0.constellation) == source_to_blocklist.constellation) && (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX)) { source.constellation) && (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX)) { strongest_sv_is_reobserved = true; break; } } } } else { std::vector<IGnssCallback::GnssSvInfo> sv_info_vec; aidl_gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout); for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) { auto& gnss_sv = sv_info_vec[iSv]; if ((gnss_sv.svid == source_to_blocklist.svid) && (gnss_sv.constellation == source_to_blocklist.constellation) && for (auto const& source : sources_to_blocklist) { if ((gnss_sv.svid == source.svid) && (gnss_sv.constellation == source.constellation) && (gnss_sv.svFlag & (int)IGnssCallback::GnssSvFlags::USED_IN_FIX)) { strongest_sv_is_reobserved = true; break; } } } } if (strongest_sv_is_reobserved) break; } } Loading gnss/common/utils/default/Utils.cpp +9 −0 Original line number Diff line number Diff line Loading @@ -338,16 +338,25 @@ GnssSvInfo getMockSvInfo(int svid, GnssConstellationType type, float cN0DbHz, fl std::vector<GnssSvInfo> Utils::getMockSvInfoList() { std::vector<GnssSvInfo> gnssSvInfoList = { // svid in [1, 32] for GPS getMockSvInfo(3, GnssConstellationType::GPS, 32.5, 27.5, 59.1, 166.5, kGpsL1FreqHz), getMockSvInfo(5, GnssConstellationType::GPS, 27.0, 22.0, 29.0, 56.5, kGpsL1FreqHz), getMockSvInfo(17, GnssConstellationType::GPS, 30.5, 25.5, 71.0, 77.0, kGpsL5FreqHz), getMockSvInfo(26, GnssConstellationType::GPS, 24.1, 19.1, 28.0, 253.0, kGpsL5FreqHz), // svid in [1, 36] for GAL getMockSvInfo(2, GnssConstellationType::GALILEO, 33.5, 27.5, 59.1, 166.5, kGalE1FreqHz), getMockSvInfo(4, GnssConstellationType::GALILEO, 28.0, 22.0, 29.0, 56.5, kGalE1FreqHz), getMockSvInfo(10, GnssConstellationType::GALILEO, 35.5, 25.5, 71.0, 77.0, kGalE1FreqHz), getMockSvInfo(29, GnssConstellationType::GALILEO, 34.1, 19.1, 28.0, 253.0, kGalE1FreqHz), // "1 <= svid <= 25 || 93 <= svid <= 106" for GLO getMockSvInfo(5, GnssConstellationType::GLONASS, 20.5, 15.5, 11.5, 116.0, kGloG1FreqHz), getMockSvInfo(17, GnssConstellationType::GLONASS, 21.5, 16.5, 28.5, 186.0, kGloG1FreqHz), getMockSvInfo(18, GnssConstellationType::GLONASS, 28.3, 25.3, 38.8, 69.0, kGloG1FreqHz), getMockSvInfo(10, GnssConstellationType::GLONASS, 25.0, 20.0, 66.0, 247.0, kGloG1FreqHz), // "1 <= X <= 14" for IRNSS getMockSvInfo(3, GnssConstellationType::IRNSS, 22.0, 19.7, 35.0, 112.0, kIrnssL5FreqHz), }; return gnssSvInfoList; Loading Loading
gnss/aidl/default/GnssDebug.cpp +39 −2 Original line number Diff line number Diff line Loading @@ -126,9 +126,46 @@ ndk::ScopedAStatus GnssDebug::getDebugData(DebugData* debugData) { .ephemerisAgeSeconds = 12, .serverPredictionIsAvailable = true, .serverPredictionAgeSeconds = 30}; SatelliteData satelliteData10 = { .svid = 2, .constellation = GnssConstellationType::GALILEO, .ephemerisType = SatelliteEphemerisType::EPHEMERIS, .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM, .ephemerisHealth = SatelliteEphemerisHealth::GOOD, .ephemerisAgeSeconds = 12, .serverPredictionIsAvailable = true, .serverPredictionAgeSeconds = 30}; SatelliteData satelliteData11 = { .svid = 4, .constellation = GnssConstellationType::GALILEO, .ephemerisType = SatelliteEphemerisType::EPHEMERIS, .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM, .ephemerisHealth = SatelliteEphemerisHealth::GOOD, .ephemerisAgeSeconds = 12, .serverPredictionIsAvailable = true, .serverPredictionAgeSeconds = 30}; SatelliteData satelliteData12 = { .svid = 10, .constellation = GnssConstellationType::GALILEO, .ephemerisType = SatelliteEphemerisType::EPHEMERIS, .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM, .ephemerisHealth = SatelliteEphemerisHealth::GOOD, .ephemerisAgeSeconds = 12, .serverPredictionIsAvailable = true, .serverPredictionAgeSeconds = 30}; SatelliteData satelliteData13 = { .svid = 29, .constellation = GnssConstellationType::GALILEO, .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}; satelliteData6, satelliteData7, satelliteData8, satelliteData9, satelliteData10, satelliteData11, satelliteData12, satelliteData13}; debugData->position = positionDebug; debugData->time = timeDebug; debugData->satelliteDataArray = satelliteDataArrayDebug; Loading
gnss/aidl/vts/gnss_hal_test.cpp +89 −32 Original line number Diff line number Diff line Loading @@ -276,35 +276,43 @@ std::list<std::vector<IGnssCallback::GnssSvInfo>> GnssHalTest::convertToAidl( } /* * FindStrongFrequentBlockableSource: * FindStrongFrequentSource: * * Search through a GnssSvStatus list for the strongest blockable satellite observed enough times * Search through a GnssSvStatus list for the strongest satellite observed enough times per * constellation * * returns the strongest source, * or a source with constellation == UNKNOWN if none are found sufficient times * returns the strongest sources for each constellation, * or an empty vector if none are found sufficient times */ BlocklistedSource GnssHalTest::FindStrongFrequentBlockableSource( std::vector<BlocklistedSource> GnssHalTest::FindStrongFrequentSources( const std::list<hidl_vec<IGnssCallback_2_1::GnssSvInfo>> sv_info_list, const int min_observations) { return FindStrongFrequentBlockableSource(convertToAidl(sv_info_list), min_observations); return FindStrongFrequentSources(convertToAidl(sv_info_list), min_observations); } BlocklistedSource GnssHalTest::FindStrongFrequentBlockableSource( bool GnssHalTest::isBlockableConstellation(const GnssConstellationType constellation, const bool isCnBuild) { if (constellation == GnssConstellationType::GPS) { return false; } if (isCnBuild && (constellation == GnssConstellationType::BEIDOU)) { // Do not blocklist BDS on CN builds return false; } return true; } std::vector<BlocklistedSource> GnssHalTest::FindStrongFrequentSources( const std::list<std::vector<IGnssCallback::GnssSvInfo>> sv_info_list, const int min_observations) { std::map<ComparableBlocklistedSource, SignalCounts> mapSignals; ALOGD("Find strongest sv from %d sv_info_list with %d min_observations.", (int)sv_info_list.size(), min_observations); bool isCnBuild = Utils::isCnBuild(); ALOGD("isCnBuild: %s", isCnBuild ? "true" : "false"); std::map<ComparableBlocklistedSource, SignalCounts> mapSignals; for (const auto& sv_info_vec : sv_info_list) { for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) { const auto& gnss_sv = sv_info_vec[iSv]; if ((gnss_sv.svFlag & (int)IGnssCallback::GnssSvFlags::USED_IN_FIX) && (gnss_sv.constellation != GnssConstellationType::GPS)) { if (isCnBuild && (gnss_sv.constellation == GnssConstellationType::BEIDOU)) { // Do not blocklist BDS on CN builds continue; } if (gnss_sv.svFlag & (int)IGnssCallback::GnssSvFlags::USED_IN_FIX) { ComparableBlocklistedSource source; source.id.svid = gnss_sv.svid; source.id.constellation = gnss_sv.constellation; Loading @@ -326,27 +334,76 @@ BlocklistedSource GnssHalTest::FindStrongFrequentBlockableSource( } } float max_cn0_dbhz_with_sufficient_count = 0.; int total_observation_count = 0; int blocklisted_source_count_observation = 0; // the Cn0 of the strongest SV per constellation std::unordered_map<GnssConstellationType, float> max_cn0_map; // # of total observations of all signals per constellation std::unordered_map<GnssConstellationType, int> total_observation_count_map; // # of observations of the strongest sv per constellation std::unordered_map<GnssConstellationType, int> source_observation_count_map; // the source to blocklist per constellation std::unordered_map<GnssConstellationType, ComparableBlocklistedSource> source_map; // # of signals per constellation std::unordered_map<GnssConstellationType, int> signal_count_map; ComparableBlocklistedSource source_to_blocklist; // initializes to zero = UNKNOWN constellation for (auto const& pairSignal : mapSignals) { total_observation_count += pairSignal.second.observations; if ((pairSignal.second.observations >= min_observations) && (pairSignal.second.max_cn0_dbhz > max_cn0_dbhz_with_sufficient_count)) { source_to_blocklist = pairSignal.first; blocklisted_source_count_observation = pairSignal.second.observations; max_cn0_dbhz_with_sufficient_count = pairSignal.second.max_cn0_dbhz; ComparableBlocklistedSource source = pairSignal.first; total_observation_count_map[source.id.constellation] += pairSignal.second.observations; signal_count_map[source.id.constellation]++; if (pairSignal.second.observations < min_observations) { continue; } if (pairSignal.second.max_cn0_dbhz > max_cn0_map[source.id.constellation]) { source_map[source.id.constellation] = pairSignal.first; source_observation_count_map[source.id.constellation] = pairSignal.second.observations; max_cn0_map[source.id.constellation] = pairSignal.second.max_cn0_dbhz; } } std::vector<BlocklistedSource> sources; if (aidl_gnss_hal_->getInterfaceVersion() <= 4) { /* For AIDL version <= 4 (launched-in-15 or earlier), only blocklist 1 sv */ float max_cn0 = 0; ComparableBlocklistedSource source_to_blocklist; for (auto const& pair : source_map) { GnssConstellationType constellation = pair.first; ComparableBlocklistedSource source = pair.second; if (max_cn0_map[constellation] > max_cn0) { max_cn0 = max_cn0_map[constellation]; source_to_blocklist = source; } } if (source_to_blocklist.id.constellation != GnssConstellationType::UNKNOWN) { ALOGD("In constellation %d, among %d observed SVs, svid %d is chosen to blocklist. " "It has %d observations with max Cn0: %.1f among %d total observations of this " "constellation.", (int)source_to_blocklist.id.constellation, signal_count_map[source_to_blocklist.id.constellation], source_to_blocklist.id.svid, source_observation_count_map[source_to_blocklist.id.constellation], max_cn0, total_observation_count_map[source_to_blocklist.id.constellation]); sources.push_back(source_to_blocklist.id); } } else { /* For AIDL version >= 5 (launched-in-16 or later), blocklist 1 sv per constellation */ for (auto const& pair : source_map) { ComparableBlocklistedSource source = pair.second; if (signal_count_map[source.id.constellation] < 4) { // Skip the constellation with a small number of signals // 4 is arbitrarily chosen to avoid affecting constellations with a limited coverage continue; } ALOGD("In constellation %d, among %d observed SVs, svid %d is chosen to blocklist. " "It has %d observations with max Cn0: %.1f among %d total observations of this " "constellation.", (int)source.id.constellation, signal_count_map[source.id.constellation], source.id.svid, source_observation_count_map[source.id.constellation], max_cn0_map[source.id.constellation], total_observation_count_map[source.id.constellation]); sources.push_back(source.id); } } ALOGD("Among %d observations, chose svid %d, constellation %d, " "with %d observations at %.1f max CNo", total_observation_count, source_to_blocklist.id.svid, (int)source_to_blocklist.id.constellation, blocklisted_source_count_observation, max_cn0_dbhz_with_sufficient_count); return source_to_blocklist.id; return sources; } GnssConstellationType GnssHalTest::startLocationAndGetBlockableConstellation( Loading
gnss/aidl/vts/gnss_hal_test.h +5 −2 Original line number Diff line number Diff line Loading @@ -81,14 +81,17 @@ class GnssHalTest : public android::hardware::gnss::common::GnssHalTestTemplate< std::list<std::vector<android::hardware::gnss::IGnssCallback::GnssSvInfo>> convertToAidl( const std::list<hidl_vec<android::hardware::gnss::V2_1::IGnssCallback::GnssSvInfo>>& sv_info_list); android::hardware::gnss::BlocklistedSource FindStrongFrequentBlockableSource( std::vector<android::hardware::gnss::BlocklistedSource> FindStrongFrequentSources( const std::list<hidl_vec<android::hardware::gnss::V2_1::IGnssCallback::GnssSvInfo>> sv_info_list, const int min_observations); android::hardware::gnss::BlocklistedSource FindStrongFrequentBlockableSource( std::vector<android::hardware::gnss::BlocklistedSource> FindStrongFrequentSources( const std::list<std::vector<android::hardware::gnss::IGnssCallback::GnssSvInfo>> sv_info_list, const int min_observations); bool isBlockableConstellation( const android::hardware::gnss::GnssConstellationType constellation, const bool isCnBuild); void checkGnssMeasurementClockFields(const android::hardware::gnss::GnssData& measurement); void checkGnssMeasurementFlags(const android::hardware::gnss::GnssMeasurement& measurement); Loading
gnss/aidl/vts/gnss_hal_test_cases.cpp +81 −43 Original line number Diff line number Diff line Loading @@ -615,7 +615,7 @@ TEST_P(GnssHalTest, TestGnssPowerIndication) { * BlocklistIndividualSatellites: * * 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding * GnssStatus for common satellites (strongest and one other.) * GnssStatus for common satellites (strongest one in each constellation.) * 2a & b) Turns off location, and blocklists common satellites. * 3) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding * GnssStatus does not use those satellites. Loading @@ -633,6 +633,7 @@ TEST_P(GnssHalTest, BlocklistIndividualSatellites) { return; } const int kWarmUpLocations = 3; const int kLocationsToAwait = 3; const int kRetriesToUnBlocklist = 10; Loading @@ -641,7 +642,7 @@ TEST_P(GnssHalTest, BlocklistIndividualSatellites) { } else { aidl_gnss_cb_->location_cbq_.reset(); } StartAndCheckLocations(kLocationsToAwait); StartAndCheckLocations(kLocationsToAwait + kWarmUpLocations); int location_called_count = (aidl_gnss_hal_->getInterfaceVersion() <= 1) ? gnss_cb_->location_cbq_.calledCount() : aidl_gnss_cb_->location_cbq_.calledCount(); Loading @@ -650,37 +651,50 @@ TEST_P(GnssHalTest, BlocklistIndividualSatellites) { int sv_info_list_cbq_size = (aidl_gnss_hal_->getInterfaceVersion() <= 1) ? gnss_cb_->sv_info_list_cbq_.size() : aidl_gnss_cb_->sv_info_list_cbq_.size(); EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait); EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait + kWarmUpLocations); ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations (%d received)", sv_info_list_cbq_size, kLocationsToAwait, location_called_count); sv_info_list_cbq_size, kLocationsToAwait + kWarmUpLocations, location_called_count); /* * Identify strongest SV seen at least kLocationsToAwait -1 times * Why -1? To avoid test flakiness in case of (plausible) slight flakiness in strongest signal * observability (one epoch RF null) * Identify strongest SV per constellation seen seen at least kLocationsToAwait -1 times. * * Why not (kLocationsToAwait + kWarmUpLocations)? To avoid test flakiness in case of * (plausible) slight flakiness in strongest signal observability (one epoch RF null) */ const int kGnssSvInfoListTimeout = 2; BlocklistedSource source_to_blocklist; std::vector<BlocklistedSource> sources_to_blocklist; if (aidl_gnss_hal_->getInterfaceVersion() <= 1) { // Discard kWarmUpLocations sv_info_vec std::list<hidl_vec<IGnssCallback_2_1::GnssSvInfo>> tmp; int count = gnss_cb_->sv_info_list_cbq_.retrieve(tmp, kWarmUpLocations, kGnssSvInfoListTimeout); ASSERT_EQ(count, kWarmUpLocations); // Retrieve (sv_info_list_cbq_size - kWarmUpLocations) sv_info_vec std::list<hidl_vec<IGnssCallback_2_1::GnssSvInfo>> sv_info_vec_list; int count = gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec_list, sv_info_list_cbq_size, kGnssSvInfoListTimeout); ASSERT_EQ(count, sv_info_list_cbq_size); source_to_blocklist = FindStrongFrequentBlockableSource(sv_info_vec_list, kLocationsToAwait - 1); count = gnss_cb_->sv_info_list_cbq_.retrieve( sv_info_vec_list, sv_info_list_cbq_size - kWarmUpLocations, kGnssSvInfoListTimeout); ASSERT_EQ(count, sv_info_list_cbq_size - kWarmUpLocations); sources_to_blocklist = FindStrongFrequentSources(sv_info_vec_list, kLocationsToAwait - 1); } else { // Discard kWarmUpLocations sv_info_vec std::list<std::vector<IGnssCallback::GnssSvInfo>> tmp; int count = aidl_gnss_cb_->sv_info_list_cbq_.retrieve(tmp, kWarmUpLocations, kGnssSvInfoListTimeout); ASSERT_EQ(count, kWarmUpLocations); // Retrieve (sv_info_list_cbq_size - kWarmUpLocations) sv_info_vec std::list<std::vector<IGnssCallback::GnssSvInfo>> sv_info_vec_list; int count = aidl_gnss_cb_->sv_info_list_cbq_.retrieve( sv_info_vec_list, sv_info_list_cbq_size, kGnssSvInfoListTimeout); ASSERT_EQ(count, sv_info_list_cbq_size); source_to_blocklist = FindStrongFrequentBlockableSource(sv_info_vec_list, kLocationsToAwait - 1); count = aidl_gnss_cb_->sv_info_list_cbq_.retrieve( sv_info_vec_list, sv_info_list_cbq_size - kWarmUpLocations, kGnssSvInfoListTimeout); ASSERT_EQ(count, sv_info_list_cbq_size - kWarmUpLocations); sources_to_blocklist = FindStrongFrequentSources(sv_info_vec_list, kLocationsToAwait - 1); } if (source_to_blocklist.constellation == GnssConstellationType::UNKNOWN) { // Cannot find a blockable satellite. Let the test pass. ALOGD("Cannot find a blockable satellite. Letting the test pass."); if (sources_to_blocklist.empty()) { // Cannot find a satellite to blocklist. Let the test pass. ALOGD("Cannot find a satellite to blocklist. Letting the test pass."); return; } Loading @@ -693,9 +707,7 @@ TEST_P(GnssHalTest, BlocklistIndividualSatellites) { ASSERT_NE(gnss_configuration_hal, nullptr); std::vector<BlocklistedSource> sources; sources.resize(1); sources[0] = source_to_blocklist; sources = sources_to_blocklist; status = gnss_configuration_hal->setBlocklist(sources); ASSERT_TRUE(status.isOk()); Loading Loading @@ -726,26 +738,47 @@ TEST_P(GnssHalTest, BlocklistIndividualSatellites) { EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait); ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations (%d received)", sv_info_list_cbq_size, kLocationsToAwait, location_called_count); bool isCnBuild = Utils::isCnBuild(); for (int i = 0; i < sv_info_list_cbq_size; ++i) { if (aidl_gnss_hal_->getInterfaceVersion() <= 1) { hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec; gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout); for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) { auto& gnss_sv = sv_info_vec[iSv]; EXPECT_FALSE( (gnss_sv.v2_0.v1_0.svid == source_to_blocklist.svid) && if (!(gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX)) { continue; } for (auto const& source : sources_to_blocklist) { if (isBlockableConstellation(source.constellation, isCnBuild)) { EXPECT_FALSE((gnss_sv.v2_0.v1_0.svid == source.svid) && (static_cast<GnssConstellationType>( gnss_sv.v2_0.constellation) == source.constellation)); } else if ((gnss_sv.v2_0.v1_0.svid == source.svid) && (static_cast<GnssConstellationType>(gnss_sv.v2_0.constellation) == source_to_blocklist.constellation) && (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX)); source.constellation)) { ALOGW("Found constellation %d, svid %d blocklisted but still used-in-fix.", source.constellation, source.svid); } } } } else { std::vector<IGnssCallback::GnssSvInfo> sv_info_vec; aidl_gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout); for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) { auto& gnss_sv = sv_info_vec[iSv]; EXPECT_FALSE((gnss_sv.svid == source_to_blocklist.svid) && (gnss_sv.constellation == source_to_blocklist.constellation) && (gnss_sv.svFlag & (int)IGnssCallback::GnssSvFlags::USED_IN_FIX)); if (!(gnss_sv.svFlag & (int)IGnssCallback::GnssSvFlags::USED_IN_FIX)) { continue; } for (auto const& source : sources_to_blocklist) { if (isBlockableConstellation(source.constellation, isCnBuild)) { EXPECT_FALSE((gnss_sv.svid == source.svid) && (gnss_sv.constellation == source.constellation)); } else if ((gnss_sv.svid == source.svid) && (gnss_sv.constellation == source.constellation)) { ALOGW("Found constellation %d, svid %d blocklisted but still used-in-fix.", gnss_sv.constellation, gnss_sv.svid); } } } } } Loading Loading @@ -795,27 +828,32 @@ TEST_P(GnssHalTest, BlocklistIndividualSatellites) { gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout); for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) { auto& gnss_sv = sv_info_vec[iSv]; if ((gnss_sv.v2_0.v1_0.svid == source_to_blocklist.svid) && for (auto const& source : sources_to_blocklist) { if ((gnss_sv.v2_0.v1_0.svid == source.svid) && (static_cast<GnssConstellationType>(gnss_sv.v2_0.constellation) == source_to_blocklist.constellation) && (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX)) { source.constellation) && (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX)) { strongest_sv_is_reobserved = true; break; } } } } else { std::vector<IGnssCallback::GnssSvInfo> sv_info_vec; aidl_gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout); for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) { auto& gnss_sv = sv_info_vec[iSv]; if ((gnss_sv.svid == source_to_blocklist.svid) && (gnss_sv.constellation == source_to_blocklist.constellation) && for (auto const& source : sources_to_blocklist) { if ((gnss_sv.svid == source.svid) && (gnss_sv.constellation == source.constellation) && (gnss_sv.svFlag & (int)IGnssCallback::GnssSvFlags::USED_IN_FIX)) { strongest_sv_is_reobserved = true; break; } } } } if (strongest_sv_is_reobserved) break; } } Loading
gnss/common/utils/default/Utils.cpp +9 −0 Original line number Diff line number Diff line Loading @@ -338,16 +338,25 @@ GnssSvInfo getMockSvInfo(int svid, GnssConstellationType type, float cN0DbHz, fl std::vector<GnssSvInfo> Utils::getMockSvInfoList() { std::vector<GnssSvInfo> gnssSvInfoList = { // svid in [1, 32] for GPS getMockSvInfo(3, GnssConstellationType::GPS, 32.5, 27.5, 59.1, 166.5, kGpsL1FreqHz), getMockSvInfo(5, GnssConstellationType::GPS, 27.0, 22.0, 29.0, 56.5, kGpsL1FreqHz), getMockSvInfo(17, GnssConstellationType::GPS, 30.5, 25.5, 71.0, 77.0, kGpsL5FreqHz), getMockSvInfo(26, GnssConstellationType::GPS, 24.1, 19.1, 28.0, 253.0, kGpsL5FreqHz), // svid in [1, 36] for GAL getMockSvInfo(2, GnssConstellationType::GALILEO, 33.5, 27.5, 59.1, 166.5, kGalE1FreqHz), getMockSvInfo(4, GnssConstellationType::GALILEO, 28.0, 22.0, 29.0, 56.5, kGalE1FreqHz), getMockSvInfo(10, GnssConstellationType::GALILEO, 35.5, 25.5, 71.0, 77.0, kGalE1FreqHz), getMockSvInfo(29, GnssConstellationType::GALILEO, 34.1, 19.1, 28.0, 253.0, kGalE1FreqHz), // "1 <= svid <= 25 || 93 <= svid <= 106" for GLO getMockSvInfo(5, GnssConstellationType::GLONASS, 20.5, 15.5, 11.5, 116.0, kGloG1FreqHz), getMockSvInfo(17, GnssConstellationType::GLONASS, 21.5, 16.5, 28.5, 186.0, kGloG1FreqHz), getMockSvInfo(18, GnssConstellationType::GLONASS, 28.3, 25.3, 38.8, 69.0, kGloG1FreqHz), getMockSvInfo(10, GnssConstellationType::GLONASS, 25.0, 20.0, 66.0, 247.0, kGloG1FreqHz), // "1 <= X <= 14" for IRNSS getMockSvInfo(3, GnssConstellationType::IRNSS, 22.0, 19.7, 35.0, 112.0, kIrnssL5FreqHz), }; return gnssSvInfoList; Loading