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