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