1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "GnssHalTestCases"
18 
19 #include <gnss_hal_test.h>
20 #include <cmath>
21 #include "Utils.h"
22 
23 #include <gtest/gtest.h>
24 
25 using android::hardware::hidl_string;
26 using android::hardware::hidl_vec;
27 
28 using android::hardware::gnss::common::Utils;
29 
30 using android::hardware::gnss::V2_1::IGnssAntennaInfo;
31 using android::hardware::gnss::V2_1::IGnssAntennaInfoCallback;
32 
33 using IGnssMeasurement_2_1 = android::hardware::gnss::V2_1::IGnssMeasurement;
34 using IGnssMeasurement_2_0 = android::hardware::gnss::V2_0::IGnssMeasurement;
35 using IGnssMeasurement_1_1 = android::hardware::gnss::V1_1::IGnssMeasurement;
36 using IGnssMeasurement_1_0 = android::hardware::gnss::V1_0::IGnssMeasurement;
37 
38 using IGnssConfiguration_2_1 = android::hardware::gnss::V2_1::IGnssConfiguration;
39 using IGnssConfiguration_2_0 = android::hardware::gnss::V2_0::IGnssConfiguration;
40 using IGnssConfiguration_1_1 = android::hardware::gnss::V1_1::IGnssConfiguration;
41 using IGnssConfiguration_1_0 = android::hardware::gnss::V1_0::IGnssConfiguration;
42 
43 using android::hardware::gnss::V2_0::GnssConstellationType;
44 using android::hardware::gnss::V2_1::IGnssConfiguration;
45 
46 using GnssMeasurementFlags = IGnssMeasurementCallback_2_1::GnssMeasurementFlags;
47 using IMeasurementCorrections_1_1 =
48         android::hardware::gnss::measurement_corrections::V1_1::IMeasurementCorrections;
49 
50 /*
51  * SetupTeardownCreateCleanup:
52  * Requests the gnss HAL then calls cleanup
53  *
54  * Empty test fixture to verify basic Setup & Teardown
55  */
TEST_P(GnssHalTest,SetupTeardownCreateCleanup)56 TEST_P(GnssHalTest, SetupTeardownCreateCleanup) {}
57 
58 /*
59  * TestGnssMeasurementExtension:
60  * Gets the GnssMeasurementExtension and verifies that it returns an actual extension.
61  */
TEST_P(GnssHalTest,TestGnssMeasurementExtension)62 TEST_P(GnssHalTest, TestGnssMeasurementExtension) {
63     auto gnssMeasurement_2_1 = gnss_hal_->getExtensionGnssMeasurement_2_1();
64     auto gnssMeasurement_2_0 = gnss_hal_->getExtensionGnssMeasurement_2_0();
65     auto gnssMeasurement_1_1 = gnss_hal_->getExtensionGnssMeasurement_1_1();
66     auto gnssMeasurement_1_0 = gnss_hal_->getExtensionGnssMeasurement();
67     ASSERT_TRUE(gnssMeasurement_2_1.isOk() && gnssMeasurement_2_0.isOk() &&
68                 gnssMeasurement_1_1.isOk() && gnssMeasurement_1_0.isOk());
69 
70     // CDD does not require Android Automotive OS devices to support
71     // GnssMeasurements.
72     if (Utils::isAutomotiveDevice()) {
73         ALOGI("Test GnssMeasurementExtension skipped. Android Automotive OS de  ice is not "
74               "required to support GNSS measurements.");
75         return;
76     }
77 
78     sp<IGnssMeasurement_2_1> iGnssMeas_2_1 = gnssMeasurement_2_1;
79     sp<IGnssMeasurement_2_0> iGnssMeas_2_0 = gnssMeasurement_2_0;
80     sp<IGnssMeasurement_1_1> iGnssMeas_1_1 = gnssMeasurement_1_1;
81     sp<IGnssMeasurement_1_0> iGnssMeas_1_0 = gnssMeasurement_1_0;
82     // At least one interface is non-null.
83     int numNonNull = (int)(iGnssMeas_2_1 != nullptr) + (int)(iGnssMeas_2_0 != nullptr) +
84                      (int)(iGnssMeas_1_1 != nullptr) + (int)(iGnssMeas_1_0 != nullptr);
85     ASSERT_TRUE(numNonNull >= 1);
86 }
87 
88 /*
89  * TestGnssConfigurationExtension:
90  * Gets the GnssConfigurationExtension and verifies that it returns an actual extension.
91  */
TEST_P(GnssHalTest,TestGnssConfigurationExtension)92 TEST_P(GnssHalTest, TestGnssConfigurationExtension) {
93     if (!IsGnssHalVersion_2_1()) {
94         ALOGI("Test TestGnssConfigurationExtension skipped. GNSS HAL version is greater than 2.1.");
95         return;
96     }
97     auto gnssConfiguration_2_1 = gnss_hal_->getExtensionGnssConfiguration_2_1();
98     auto gnssConfiguration_2_0 = gnss_hal_->getExtensionGnssConfiguration_2_0();
99     auto gnssConfiguration_1_1 = gnss_hal_->getExtensionGnssConfiguration_1_1();
100     auto gnssConfiguration_1_0 = gnss_hal_->getExtensionGnssConfiguration();
101     ASSERT_TRUE(gnssConfiguration_2_1.isOk() && gnssConfiguration_2_0.isOk() &&
102                 gnssConfiguration_1_1.isOk() && gnssConfiguration_1_0.isOk());
103     sp<IGnssConfiguration_2_1> iGnssConfig_2_1 = gnssConfiguration_2_1;
104     sp<IGnssConfiguration_2_0> iGnssConfig_2_0 = gnssConfiguration_2_0;
105     sp<IGnssConfiguration_1_1> iGnssConfig_1_1 = gnssConfiguration_1_1;
106     sp<IGnssConfiguration_1_0> iGnssConfig_1_0 = gnssConfiguration_1_0;
107     // At least one interface is non-null.
108     int numNonNull = (int)(iGnssConfig_2_1 != nullptr) + (int)(iGnssConfig_2_0 != nullptr) +
109                      (int)(iGnssConfig_1_1 != nullptr) + (int)(iGnssConfig_1_0 != nullptr);
110     ASSERT_TRUE(numNonNull >= 1);
111 }
112 
113 /*
114  * TestGnssMeasurementFields:
115  * Sets a GnssMeasurementCallback, waits for a measurement, and verifies
116  * 1. basebandCN0DbHz is valid
117  * 2. ISB fields are valid
118  */
TEST_P(GnssHalTest,TestGnssMeasurementFields)119 TEST_P(GnssHalTest, TestGnssMeasurementFields) {
120     const int kFirstGnssMeasurementTimeoutSeconds = 10;
121 
122     auto gnssMeasurement = gnss_hal_->getExtensionGnssMeasurement_2_1();
123     ASSERT_TRUE(gnssMeasurement.isOk());
124 
125     // Skip test if GnssMeasurement v2.1 is not supported
126     sp<IGnssMeasurement_2_1> iGnssMeasurement = gnssMeasurement;
127     if (iGnssMeasurement == nullptr) {
128         return;
129     }
130 
131     sp<GnssMeasurementCallback> callback = new GnssMeasurementCallback();
132     auto result = iGnssMeasurement->setCallback_2_1(callback, /* enableFullTracking= */ true);
133     ASSERT_TRUE(result.isOk());
134     EXPECT_EQ(result, IGnssMeasurement_1_0::GnssMeasurementStatus::SUCCESS);
135 
136     IGnssMeasurementCallback_2_1::GnssData lastMeasurement;
137     ASSERT_TRUE(callback->measurement_cbq_.retrieve(lastMeasurement,
138                                                     kFirstGnssMeasurementTimeoutSeconds));
139     EXPECT_EQ(callback->measurement_cbq_.calledCount(), 1);
140     ASSERT_TRUE(lastMeasurement.measurements.size() > 0);
141     for (auto measurement : lastMeasurement.measurements) {
142         // Verify basebandCn0DbHz is valid.
143         ASSERT_TRUE(measurement.basebandCN0DbHz > 0.0 && measurement.basebandCN0DbHz <= 65.0);
144 
145         if (((uint32_t)(measurement.flags & GnssMeasurementFlags::HAS_FULL_ISB) > 0) &&
146             ((uint32_t)(measurement.flags & GnssMeasurementFlags::HAS_FULL_ISB_UNCERTAINTY) > 0) &&
147             ((uint32_t)(measurement.flags & GnssMeasurementFlags::HAS_SATELLITE_ISB) > 0) &&
148             ((uint32_t)(measurement.flags & GnssMeasurementFlags::HAS_SATELLITE_ISB_UNCERTAINTY) >
149              0)) {
150             GnssConstellationType referenceConstellation =
151                     lastMeasurement.clock.referenceSignalTypeForIsb.constellation;
152             double carrierFrequencyHz =
153                     lastMeasurement.clock.referenceSignalTypeForIsb.carrierFrequencyHz;
154             std::string codeType = lastMeasurement.clock.referenceSignalTypeForIsb.codeType;
155 
156             ASSERT_TRUE(referenceConstellation >= GnssConstellationType::UNKNOWN &&
157                         referenceConstellation <= GnssConstellationType::IRNSS);
158             ASSERT_TRUE(carrierFrequencyHz > 0);
159             ASSERT_TRUE(codeType != "");
160 
161             ASSERT_TRUE(std::abs(measurement.fullInterSignalBiasNs) < 1.0e6);
162             ASSERT_TRUE(measurement.fullInterSignalBiasUncertaintyNs >= 0);
163             ASSERT_TRUE(std::abs(measurement.satelliteInterSignalBiasNs) < 1.0e6);
164             ASSERT_TRUE(measurement.satelliteInterSignalBiasUncertaintyNs >= 0);
165         }
166     }
167 
168     iGnssMeasurement->close();
169 }
170 
171 /*
172  * TestGnssAntennaInfo:
173  * Sets a GnssAntennaInfoCallback, waits for report, and verifies
174  * 1. phaseCenterOffsetCoordinateMillimeters is valid
175  * 2. phaseCenterOffsetCoordinateUncertaintyMillimeters is valid.
176  * PhaseCenterVariationCorrections and SignalGainCorrections are optional.
177  */
TEST_P(GnssHalTest,TestGnssAntennaInfo)178 TEST_P(GnssHalTest, TestGnssAntennaInfo) {
179     const int kAntennaInfoTimeoutSeconds = 2;
180 
181     auto gnssAntennaInfo = gnss_hal_->getExtensionGnssAntennaInfo();
182     ASSERT_TRUE(gnssAntennaInfo.isOk());
183 
184     // Skip test if GnssAntennaInfo v2.1 is not supported
185     sp<IGnssAntennaInfo> iGnssAntennaInfo = gnssAntennaInfo;
186     if (!(gnss_cb_->last_capabilities_ & IGnssCallback_2_1::Capabilities::ANTENNA_INFO) ||
187         iGnssAntennaInfo == nullptr) {
188         ALOGD("GnssAntennaInfo v2.1 is not supported.");
189         return;
190     }
191 
192     sp<GnssAntennaInfoCallback> callback = new GnssAntennaInfoCallback();
193     auto result = iGnssAntennaInfo->setCallback(callback);
194     ASSERT_TRUE(result.isOk());
195     EXPECT_EQ(result, IGnssAntennaInfo::GnssAntennaInfoStatus::SUCCESS);
196 
197     hidl_vec<IGnssAntennaInfoCallback::GnssAntennaInfo> antennaInfos;
198     ASSERT_TRUE(callback->antenna_info_cbq_.retrieve(antennaInfos, kAntennaInfoTimeoutSeconds));
199     EXPECT_EQ(callback->antenna_info_cbq_.calledCount(), 1);
200     ASSERT_TRUE(antennaInfos.size() > 0);
201 
202     for (auto antennaInfo : antennaInfos) {
203         // Remaining fields are optional
204         if (antennaInfo.phaseCenterVariationCorrectionMillimeters != NULL) {
205             int numRows = antennaInfo.phaseCenterVariationCorrectionMillimeters.size();
206             int numColumns = antennaInfo.phaseCenterVariationCorrectionMillimeters[0].row.size();
207             // Must have at least 1 row and 2 columns
208             ASSERT_TRUE(numRows >= 1 && numColumns >= 2);
209 
210             // Corrections and uncertainties must have same dimensions
211             ASSERT_TRUE(antennaInfo.phaseCenterVariationCorrectionMillimeters.size() ==
212                         antennaInfo.phaseCenterVariationCorrectionUncertaintyMillimeters.size());
213             ASSERT_TRUE(
214                     antennaInfo.phaseCenterVariationCorrectionMillimeters[0].row.size() ==
215                     antennaInfo.phaseCenterVariationCorrectionUncertaintyMillimeters[0].row.size());
216 
217             // Must be rectangular
218             for (auto row : antennaInfo.phaseCenterVariationCorrectionMillimeters) {
219                 ASSERT_TRUE(row.row.size() == numColumns);
220             }
221             for (auto row : antennaInfo.phaseCenterVariationCorrectionUncertaintyMillimeters) {
222                 ASSERT_TRUE(row.row.size() == numColumns);
223             }
224         }
225         if (antennaInfo.signalGainCorrectionDbi != NULL) {
226             int numRows = antennaInfo.signalGainCorrectionDbi.size();
227             int numColumns = antennaInfo.signalGainCorrectionUncertaintyDbi[0].row.size();
228             // Must have at least 1 row and 2 columns
229             ASSERT_TRUE(numRows >= 1 && numColumns >= 2);
230 
231             // Corrections and uncertainties must have same dimensions
232             ASSERT_TRUE(antennaInfo.signalGainCorrectionDbi.size() ==
233                         antennaInfo.signalGainCorrectionUncertaintyDbi.size());
234             ASSERT_TRUE(antennaInfo.signalGainCorrectionDbi[0].row.size() ==
235                         antennaInfo.signalGainCorrectionUncertaintyDbi[0].row.size());
236 
237             // Must be rectangular
238             for (auto row : antennaInfo.signalGainCorrectionDbi) {
239                 ASSERT_TRUE(row.row.size() == numColumns);
240             }
241             for (auto row : antennaInfo.signalGainCorrectionUncertaintyDbi) {
242                 ASSERT_TRUE(row.row.size() == numColumns);
243             }
244         }
245     }
246 
247     iGnssAntennaInfo->close();
248 }
249 
250 /*
251  * TestGnssSvInfoFields:
252  * Gets 1 location and a (non-empty) GnssSvInfo, and verifies basebandCN0DbHz is valid.
253  */
TEST_P(GnssHalTest,TestGnssSvInfoFields)254 TEST_P(GnssHalTest, TestGnssSvInfoFields) {
255     gnss_cb_->location_cbq_.reset();
256     gnss_cb_->sv_info_list_cbq_.reset();
257     StartAndCheckFirstLocation(/* min_interval_msec= */ 1000, /* low_power_mode= */ false);
258     int location_called_count = gnss_cb_->location_cbq_.calledCount();
259     ALOGD("Observed %d GnssSvStatus, while awaiting one location (%d received)",
260           gnss_cb_->sv_info_list_cbq_.size(), location_called_count);
261 
262     // Wait for up to kNumSvInfoLists events for kTimeoutSeconds for each event.
263     int kTimeoutSeconds = 2;
264     int kNumSvInfoLists = 4;
265     std::list<hidl_vec<IGnssCallback_2_1::GnssSvInfo>> sv_info_lists;
266     hidl_vec<IGnssCallback_2_1::GnssSvInfo> last_sv_info_list;
267 
268     do {
269         EXPECT_GT(gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_lists, kNumSvInfoLists,
270                                                        kTimeoutSeconds),
271                   0);
272         last_sv_info_list = sv_info_lists.back();
273     } while (last_sv_info_list.size() == 0);
274 
275     ALOGD("last_sv_info size = %d", (int)last_sv_info_list.size());
276     bool nonZeroCn0Found = false;
277     for (auto sv_info : last_sv_info_list) {
278         EXPECT_TRUE(sv_info.basebandCN0DbHz >= 0.0 && sv_info.basebandCN0DbHz <= 65.0);
279         if (sv_info.basebandCN0DbHz > 0.0) {
280             nonZeroCn0Found = true;
281         }
282     }
283     // Assert at least one value is non-zero. Zero is ok in status as it's possibly
284     // reporting a searched but not found satellite.
285     EXPECT_TRUE(nonZeroCn0Found);
286     StopAndClearLocations();
287 }
288 
289 /*
290  * FindStrongFrequentNonGpsSource:
291  *
292  * Search through a GnssSvStatus list for the strongest non-GPS satellite observed enough times
293  *
294  * returns the strongest source,
295  *         or a source with constellation == UNKNOWN if none are found sufficient times
296  * TODO(skz): create a template for this to reduce code duplication of v2.1 and v2.0 since both
297  * are using vectors.
298  */
FindStrongFrequentNonGpsSource(const std::list<hidl_vec<IGnssCallback_2_1::GnssSvInfo>> sv_info_list,const int min_observations)299 IGnssConfiguration::BlacklistedSource FindStrongFrequentNonGpsSource(
300         const std::list<hidl_vec<IGnssCallback_2_1::GnssSvInfo>> sv_info_list,
301         const int min_observations) {
302     struct ComparableBlacklistedSource {
303         IGnssConfiguration::BlacklistedSource id;
304 
305         ComparableBlacklistedSource() {
306             id.constellation = GnssConstellationType::UNKNOWN;
307             id.svid = 0;
308         }
309 
310         bool operator<(const ComparableBlacklistedSource& compare) const {
311             return ((id.svid < compare.id.svid) || ((id.svid == compare.id.svid) &&
312                                                     (id.constellation < compare.id.constellation)));
313         }
314     };
315 
316     struct SignalCounts {
317         int observations;
318         float max_cn0_dbhz;
319     };
320 
321     std::map<ComparableBlacklistedSource, SignalCounts> mapSignals;
322 
323     for (const auto& sv_info_vec : sv_info_list) {
324         for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
325             const auto& gnss_sv = sv_info_vec[iSv];
326             if ((gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX) &&
327                 (gnss_sv.v2_0.constellation != GnssConstellationType::GPS)) {
328                 ComparableBlacklistedSource source;
329                 source.id.svid = gnss_sv.v2_0.v1_0.svid;
330                 source.id.constellation = gnss_sv.v2_0.constellation;
331 
332                 const auto& itSignal = mapSignals.find(source);
333                 if (itSignal == mapSignals.end()) {
334                     SignalCounts counts;
335                     counts.observations = 1;
336                     counts.max_cn0_dbhz = gnss_sv.v2_0.v1_0.cN0Dbhz;
337                     mapSignals.insert(
338                             std::pair<ComparableBlacklistedSource, SignalCounts>(source, counts));
339                 } else {
340                     itSignal->second.observations++;
341                     if (itSignal->second.max_cn0_dbhz < gnss_sv.v2_0.v1_0.cN0Dbhz) {
342                         itSignal->second.max_cn0_dbhz = gnss_sv.v2_0.v1_0.cN0Dbhz;
343                     }
344                 }
345             }
346         }
347     }
348 
349     float max_cn0_dbhz_with_sufficient_count = 0.;
350     int total_observation_count = 0;
351     int blacklisted_source_count_observation = 0;
352 
353     ComparableBlacklistedSource source_to_blacklist;  // initializes to zero = UNKNOWN constellation
354     for (auto const& pairSignal : mapSignals) {
355         total_observation_count += pairSignal.second.observations;
356         if ((pairSignal.second.observations >= min_observations) &&
357             (pairSignal.second.max_cn0_dbhz > max_cn0_dbhz_with_sufficient_count)) {
358             source_to_blacklist = pairSignal.first;
359             blacklisted_source_count_observation = pairSignal.second.observations;
360             max_cn0_dbhz_with_sufficient_count = pairSignal.second.max_cn0_dbhz;
361         }
362     }
363     ALOGD("Among %d observations, chose svid %d, constellation %d, "
364           "with %d observations at %.1f max CNo",
365           total_observation_count, source_to_blacklist.id.svid,
366           (int)source_to_blacklist.id.constellation, blacklisted_source_count_observation,
367           max_cn0_dbhz_with_sufficient_count);
368 
369     return source_to_blacklist.id;
370 }
371 
372 /*
373  * BlocklistIndividualSatellites:
374  *
375  * 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding
376  * GnssStatus for common satellites (strongest and one other.)
377  * 2a & b) Turns off location, and blocklists common satellites.
378  * 3) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding
379  * GnssStatus does not use those satellites.
380  * 4a & b) Turns off location, and send in empty blocklist.
381  * 5a) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding
382  * GnssStatus does re-use at least the previously strongest satellite
383  * 5b) Retry a few times, in case GNSS search strategy takes a while to reacquire even the
384  * formerly strongest satellite
385  */
TEST_P(GnssHalTest,BlocklistIndividualSatellites)386 TEST_P(GnssHalTest, BlocklistIndividualSatellites) {
387     if (!IsGnssHalVersion_2_1()) {
388         ALOGI("Test BlocklistIndividualSatellites skipped. GNSS HAL version is greater than 2.1.");
389         return;
390     }
391     if (!(gnss_cb_->last_capabilities_ & IGnssCallback_2_1::Capabilities::SATELLITE_BLACKLIST)) {
392         ALOGI("Test BlacklistIndividualSatellites skipped. SATELLITE_BLACKLIST capability not "
393               "supported.");
394         return;
395     }
396 
397     const int kLocationsToAwait = 3;
398     const int kRetriesToUnBlacklist = 10;
399 
400     gnss_cb_->location_cbq_.reset();
401     StartAndCheckLocations(kLocationsToAwait);
402     int location_called_count = gnss_cb_->location_cbq_.calledCount();
403 
404     // Tolerate 1 less sv status to handle edge cases in reporting.
405     int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
406     EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
407     ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations (%d received)",
408           sv_info_list_cbq_size, kLocationsToAwait, location_called_count);
409 
410     /*
411      * Identify strongest SV seen at least kLocationsToAwait -1 times
412      * Why -1?  To avoid test flakiness in case of (plausible) slight flakiness in strongest signal
413      * observability (one epoch RF null)
414      */
415 
416     const int kGnssSvInfoListTimeout = 2;
417     std::list<hidl_vec<IGnssCallback_2_1::GnssSvInfo>> sv_info_vec_list;
418     int count = gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec_list, sv_info_list_cbq_size,
419                                                      kGnssSvInfoListTimeout);
420 
421     ASSERT_EQ(count, sv_info_list_cbq_size);
422 
423     IGnssConfiguration::BlacklistedSource source_to_blacklist =
424             FindStrongFrequentNonGpsSource(sv_info_vec_list, kLocationsToAwait - 1);
425 
426     if (source_to_blacklist.constellation == GnssConstellationType::UNKNOWN) {
427         // Cannot find a non-GPS satellite. Let the test pass.
428         ALOGD("Cannot find a non-GPS satellite. Letting the test pass.");
429         return;
430     }
431 
432     // Stop locations, blacklist the common SV
433     StopAndClearLocations();
434 
435     auto gnss_configuration_hal_return = gnss_hal_->getExtensionGnssConfiguration_2_1();
436     ASSERT_TRUE(gnss_configuration_hal_return.isOk());
437     sp<IGnssConfiguration> gnss_configuration_hal = gnss_configuration_hal_return;
438     ASSERT_NE(gnss_configuration_hal, nullptr);
439 
440     hidl_vec<IGnssConfiguration::BlacklistedSource> sources;
441     sources.resize(1);
442     sources[0] = source_to_blacklist;
443 
444     auto result = gnss_configuration_hal->setBlacklist_2_1(sources);
445     ASSERT_TRUE(result.isOk());
446     EXPECT_TRUE(result);
447 
448     // retry and ensure satellite not used
449     gnss_cb_->sv_info_list_cbq_.reset();
450 
451     gnss_cb_->location_cbq_.reset();
452     StartAndCheckLocations(kLocationsToAwait);
453 
454     // early exit if test is being run with insufficient signal
455     location_called_count = gnss_cb_->location_cbq_.calledCount();
456     if (location_called_count == 0) {
457         ALOGE("0 Gnss locations received - ensure sufficient signal and retry");
458     }
459     ASSERT_TRUE(location_called_count > 0);
460 
461     // Tolerate 1 less sv status to handle edge cases in reporting.
462     sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
463     EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
464     ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations (%d received)",
465           sv_info_list_cbq_size, kLocationsToAwait, location_called_count);
466     for (int i = 0; i < sv_info_list_cbq_size; ++i) {
467         hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
468         gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
469         for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
470             const auto& gnss_sv = sv_info_vec[iSv];
471             EXPECT_FALSE((gnss_sv.v2_0.v1_0.svid == source_to_blacklist.svid) &&
472                          (gnss_sv.v2_0.constellation == source_to_blacklist.constellation) &&
473                          (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
474         }
475     }
476 
477     // clear blacklist and restart - this time updating the blacklist while location is still on
478     sources.resize(0);
479 
480     result = gnss_configuration_hal->setBlacklist_2_1(sources);
481     ASSERT_TRUE(result.isOk());
482     EXPECT_TRUE(result);
483 
484     bool strongest_sv_is_reobserved = false;
485     // do several loops awaiting a few locations, allowing non-immediate reacquisition strategies
486     int unblacklist_loops_remaining = kRetriesToUnBlacklist;
487     while (!strongest_sv_is_reobserved && (unblacklist_loops_remaining-- > 0)) {
488         StopAndClearLocations();
489         gnss_cb_->sv_info_list_cbq_.reset();
490 
491         gnss_cb_->location_cbq_.reset();
492         StartAndCheckLocations(kLocationsToAwait);
493 
494         // early exit loop if test is being run with insufficient signal
495         location_called_count = gnss_cb_->location_cbq_.calledCount();
496         if (location_called_count == 0) {
497             ALOGE("0 Gnss locations received - ensure sufficient signal and retry");
498         }
499         ASSERT_TRUE(location_called_count > 0);
500 
501         // Tolerate 1 less sv status to handle edge cases in reporting.
502         sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
503         EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
504         ALOGD("Clear blacklist, observed %d GnssSvInfo, while awaiting %d Locations"
505               ", tries remaining %d",
506               sv_info_list_cbq_size, kLocationsToAwait, unblacklist_loops_remaining);
507 
508         for (int i = 0; i < sv_info_list_cbq_size; ++i) {
509             hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
510             gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
511             for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
512                 const auto& gnss_sv = sv_info_vec[iSv];
513                 if ((gnss_sv.v2_0.v1_0.svid == source_to_blacklist.svid) &&
514                     (gnss_sv.v2_0.constellation == source_to_blacklist.constellation) &&
515                     (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX)) {
516                     strongest_sv_is_reobserved = true;
517                     break;
518                 }
519             }
520             if (strongest_sv_is_reobserved) break;
521         }
522     }
523     EXPECT_TRUE(strongest_sv_is_reobserved);
524     StopAndClearLocations();
525 }
526 
527 /*
528  * BlocklistConstellationLocationOff:
529  *
530  * 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding
531  * GnssStatus for any non-GPS constellations.
532  * 2a & b) Turns off location, and blocklist first non-GPS constellations.
533  * 3) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding
534  * GnssStatus does not use any constellation but GPS.
535  * 4a & b) Clean up by turning off location, and send in empty blocklist.
536  */
TEST_P(GnssHalTest,BlocklistConstellationLocationOff)537 TEST_P(GnssHalTest, BlocklistConstellationLocationOff) {
538     if (!IsGnssHalVersion_2_1()) {
539         ALOGI("Test BlocklistConstellationLocationOff skipped. GNSS HAL version is greater than "
540               "2.1.");
541         return;
542     }
543     if (!(gnss_cb_->last_capabilities_ & IGnssCallback_2_1::Capabilities::SATELLITE_BLACKLIST)) {
544         ALOGI("Test BlacklistConstellationLocationOff skipped. SATELLITE_BLACKLIST capability not "
545               "supported.");
546         return;
547     }
548 
549     const int kLocationsToAwait = 3;
550     const int kGnssSvInfoListTimeout = 2;
551 
552     // Find first non-GPS constellation to blacklist
553     GnssConstellationType constellation_to_blacklist =
554             startLocationAndGetNonGpsConstellation(kLocationsToAwait, kGnssSvInfoListTimeout);
555 
556     // Turns off location
557     StopAndClearLocations();
558 
559     IGnssConfiguration::BlacklistedSource source_to_blacklist_1;
560     source_to_blacklist_1.constellation = constellation_to_blacklist;
561     source_to_blacklist_1.svid = 0;  // documented wildcard for all satellites in this constellation
562 
563     // IRNSS was added in 2.0. Always attempt to blacklist IRNSS to verify that the new enum is
564     // supported.
565     IGnssConfiguration::BlacklistedSource source_to_blacklist_2;
566     source_to_blacklist_2.constellation = GnssConstellationType::IRNSS;
567     source_to_blacklist_2.svid = 0;  // documented wildcard for all satellites in this constellation
568 
569     auto gnss_configuration_hal_return = gnss_hal_->getExtensionGnssConfiguration_2_1();
570     ASSERT_TRUE(gnss_configuration_hal_return.isOk());
571     sp<IGnssConfiguration> gnss_configuration_hal = gnss_configuration_hal_return;
572     ASSERT_NE(gnss_configuration_hal, nullptr);
573 
574     hidl_vec<IGnssConfiguration::BlacklistedSource> sources;
575     sources.resize(2);
576     sources[0] = source_to_blacklist_1;
577     sources[1] = source_to_blacklist_2;
578 
579     auto result = gnss_configuration_hal->setBlacklist_2_1(sources);
580     ASSERT_TRUE(result.isOk());
581     EXPECT_TRUE(result);
582 
583     // retry and ensure constellation not used
584     gnss_cb_->sv_info_list_cbq_.reset();
585 
586     gnss_cb_->location_cbq_.reset();
587     StartAndCheckLocations(kLocationsToAwait);
588 
589     // Tolerate 1 less sv status to handle edge cases in reporting.
590     int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
591     EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
592     ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations", sv_info_list_cbq_size,
593           kLocationsToAwait);
594     for (int i = 0; i < sv_info_list_cbq_size; ++i) {
595         hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
596         gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
597         for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
598             const auto& gnss_sv = sv_info_vec[iSv];
599             EXPECT_FALSE((gnss_sv.v2_0.constellation == source_to_blacklist_1.constellation) &&
600                          (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
601             EXPECT_FALSE((gnss_sv.v2_0.constellation == source_to_blacklist_2.constellation) &&
602                          (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
603         }
604     }
605 
606     // clean up
607     StopAndClearLocations();
608     sources.resize(0);
609     result = gnss_configuration_hal->setBlacklist_2_1(sources);
610     ASSERT_TRUE(result.isOk());
611     EXPECT_TRUE(result);
612 }
613 
614 /*
615  * BlocklistConstellationLocationOn:
616  *
617  * 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding
618  * GnssStatus for any non-GPS constellations.
619  * 2a & b) Blocklist first non-GPS constellation, and turn off location.
620  * 3) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding
621  * GnssStatus does not use any constellation but GPS.
622  * 4a & b) Clean up by turning off location, and send in empty blocklist.
623  */
TEST_P(GnssHalTest,BlocklistConstellationLocationOn)624 TEST_P(GnssHalTest, BlocklistConstellationLocationOn) {
625     if (!IsGnssHalVersion_2_1()) {
626         ALOGI("Test BlocklistConstellationLocationOn skipped. GNSS HAL version is greater than "
627               "2.1.");
628         return;
629     }
630     if (!(gnss_cb_->last_capabilities_ & IGnssCallback_2_1::Capabilities::SATELLITE_BLACKLIST)) {
631         ALOGI("Test BlacklistConstellationLocationOn skipped. SATELLITE_BLACKLIST capability not "
632               "supported.");
633         return;
634     }
635 
636     const int kLocationsToAwait = 3;
637     const int kGnssSvInfoListTimeout = 2;
638 
639     // Find first non-GPS constellation to blacklist
640     GnssConstellationType constellation_to_blacklist =
641             startLocationAndGetNonGpsConstellation(kLocationsToAwait, kGnssSvInfoListTimeout);
642 
643     IGnssConfiguration::BlacklistedSource source_to_blacklist_1;
644     source_to_blacklist_1.constellation = constellation_to_blacklist;
645     source_to_blacklist_1.svid = 0;  // documented wildcard for all satellites in this constellation
646 
647     // IRNSS was added in 2.0. Always attempt to blacklist IRNSS to verify that the new enum is
648     // supported.
649     IGnssConfiguration::BlacklistedSource source_to_blacklist_2;
650     source_to_blacklist_2.constellation = GnssConstellationType::IRNSS;
651     source_to_blacklist_2.svid = 0;  // documented wildcard for all satellites in this constellation
652 
653     auto gnss_configuration_hal_return = gnss_hal_->getExtensionGnssConfiguration_2_1();
654     ASSERT_TRUE(gnss_configuration_hal_return.isOk());
655     sp<IGnssConfiguration> gnss_configuration_hal = gnss_configuration_hal_return;
656     ASSERT_NE(gnss_configuration_hal, nullptr);
657 
658     hidl_vec<IGnssConfiguration::BlacklistedSource> sources;
659     sources.resize(2);
660     sources[0] = source_to_blacklist_1;
661     sources[1] = source_to_blacklist_2;
662 
663     auto result = gnss_configuration_hal->setBlacklist_2_1(sources);
664     ASSERT_TRUE(result.isOk());
665     EXPECT_TRUE(result);
666 
667     // Turns off location
668     StopAndClearLocations();
669 
670     // retry and ensure constellation not used
671     gnss_cb_->sv_info_list_cbq_.reset();
672 
673     gnss_cb_->location_cbq_.reset();
674     StartAndCheckLocations(kLocationsToAwait);
675 
676     // Tolerate 1 less sv status to handle edge cases in reporting.
677     int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
678     EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
679     ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations", sv_info_list_cbq_size,
680           kLocationsToAwait);
681     for (int i = 0; i < sv_info_list_cbq_size; ++i) {
682         hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
683         gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
684         for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
685             const auto& gnss_sv = sv_info_vec[iSv];
686             EXPECT_FALSE((gnss_sv.v2_0.constellation == source_to_blacklist_1.constellation) &&
687                          (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
688             EXPECT_FALSE((gnss_sv.v2_0.constellation == source_to_blacklist_2.constellation) &&
689                          (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
690         }
691     }
692 
693     // clean up
694     StopAndClearLocations();
695     sources.resize(0);
696     result = gnss_configuration_hal->setBlacklist_2_1(sources);
697     ASSERT_TRUE(result.isOk());
698     EXPECT_TRUE(result);
699 }
700 
701 /*
702  * TestGnssMeasurementCorrections:
703  * If measurement corrections capability is supported, verifies that it supports the
704  * gnss.measurement_corrections@1.1::IMeasurementCorrections interface by invoking a method.
705  */
TEST_P(GnssHalTest,TestGnssMeasurementCorrections)706 TEST_P(GnssHalTest, TestGnssMeasurementCorrections) {
707     if (!(gnss_cb_->last_capabilities_ &
708           IGnssCallback_2_1::Capabilities::MEASUREMENT_CORRECTIONS)) {
709         return;
710     }
711 
712     // Verify IMeasurementCorrections is supported.
713     auto measurementCorrections = gnss_hal_->getExtensionMeasurementCorrections_1_1();
714     ASSERT_TRUE(measurementCorrections.isOk());
715     sp<IMeasurementCorrections_1_1> iMeasurementCorrections = measurementCorrections;
716     ASSERT_NE(iMeasurementCorrections, nullptr);
717 
718     sp<GnssMeasurementCorrectionsCallback> callback = new GnssMeasurementCorrectionsCallback();
719     iMeasurementCorrections->setCallback(callback);
720 
721     const int kMeasurementCorrectionsCapabilitiesTimeoutSeconds = 5;
722     callback->capabilities_cbq_.retrieve(callback->last_capabilities_,
723                                          kMeasurementCorrectionsCapabilitiesTimeoutSeconds);
724     ASSERT_TRUE(callback->capabilities_cbq_.calledCount() > 0);
725 
726     // Set a mock MeasurementCorrections.
727     auto result =
728             iMeasurementCorrections->setCorrections_1_1(Utils::getMockMeasurementCorrections_1_1());
729     ASSERT_TRUE(result.isOk());
730     EXPECT_TRUE(result);
731 }
732