1 /*
2 * Copyright (C) 2020 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 <android/hardware/gnss/IGnss.h>
20 #include <android/hardware/gnss/IGnssMeasurementCallback.h>
21 #include <android/hardware/gnss/IGnssMeasurementInterface.h>
22 #include <android/hardware/gnss/IGnssPowerIndication.h>
23 #include <android/hardware/gnss/IGnssPsds.h>
24 #include "GnssMeasurementCallbackAidl.h"
25 #include "GnssPowerIndicationCallback.h"
26 #include "gnss_hal_test.h"
27
28 using android::sp;
29 using android::hardware::gnss::BlocklistedSource;
30 using android::hardware::gnss::ElapsedRealtime;
31 using android::hardware::gnss::GnssClock;
32 using android::hardware::gnss::GnssData;
33 using android::hardware::gnss::GnssMeasurement;
34 using android::hardware::gnss::GnssPowerStats;
35 using android::hardware::gnss::IGnss;
36 using android::hardware::gnss::IGnssConfiguration;
37 using android::hardware::gnss::IGnssMeasurementCallback;
38 using android::hardware::gnss::IGnssMeasurementInterface;
39 using android::hardware::gnss::IGnssPowerIndication;
40 using android::hardware::gnss::IGnssPsds;
41 using android::hardware::gnss::PsdsType;
42 using android::hardware::gnss::SatellitePvt;
43
44 using GnssConstellationTypeAidl = android::hardware::gnss::GnssConstellationType;
45
46 /*
47 * SetupTeardownCreateCleanup:
48 * Requests the gnss HAL then calls cleanup
49 *
50 * Empty test fixture to verify basic Setup & Teardown
51 */
TEST_P(GnssHalTest,SetupTeardownCreateCleanup)52 TEST_P(GnssHalTest, SetupTeardownCreateCleanup) {}
53
54 /*
55 * TestPsdsExtension:
56 * 1. Gets the PsdsExtension and verifies that it returns a non-null extension.
57 * 2. Injects empty PSDS data and verifies that it returns an error.
58 */
TEST_P(GnssHalTest,TestPsdsExtension)59 TEST_P(GnssHalTest, TestPsdsExtension) {
60 sp<IGnssPsds> iGnssPsds;
61 auto status = aidl_gnss_hal_->getExtensionPsds(&iGnssPsds);
62 ASSERT_TRUE(status.isOk());
63 ASSERT_TRUE(iGnssPsds != nullptr);
64
65 status = iGnssPsds->injectPsdsData(PsdsType::LONG_TERM, std::vector<uint8_t>());
66 ASSERT_FALSE(status.isOk());
67 }
68
CheckSatellitePvt(const SatellitePvt & satellitePvt)69 void CheckSatellitePvt(const SatellitePvt& satellitePvt) {
70 const double kMaxOrbitRadiusMeters = 43000000.0;
71 const double kMaxVelocityMps = 4000.0;
72 // The below values are determined using GPS ICD Table 20-1
73 const double kMinHardwareCodeBiasMeters = -17.869;
74 const double kMaxHardwareCodeBiasMeters = 17.729;
75 const double kMaxTimeCorrelationMeters = 3e6;
76 const double kMaxSatClkDriftMps = 1.117;
77
78 ASSERT_TRUE(satellitePvt.flags & SatellitePvt::HAS_POSITION_VELOCITY_CLOCK_INFO ||
79 satellitePvt.flags & SatellitePvt::HAS_IONO ||
80 satellitePvt.flags & SatellitePvt::HAS_TROPO);
81 if (satellitePvt.flags & SatellitePvt::HAS_POSITION_VELOCITY_CLOCK_INFO) {
82 ALOGD("Found HAS_POSITION_VELOCITY_CLOCK_INFO");
83 ASSERT_TRUE(satellitePvt.satPosEcef.posXMeters >= -kMaxOrbitRadiusMeters &&
84 satellitePvt.satPosEcef.posXMeters <= kMaxOrbitRadiusMeters);
85 ASSERT_TRUE(satellitePvt.satPosEcef.posYMeters >= -kMaxOrbitRadiusMeters &&
86 satellitePvt.satPosEcef.posYMeters <= kMaxOrbitRadiusMeters);
87 ASSERT_TRUE(satellitePvt.satPosEcef.posZMeters >= -kMaxOrbitRadiusMeters &&
88 satellitePvt.satPosEcef.posZMeters <= kMaxOrbitRadiusMeters);
89 ASSERT_TRUE(satellitePvt.satPosEcef.ureMeters > 0);
90 ASSERT_TRUE(satellitePvt.satVelEcef.velXMps >= -kMaxVelocityMps &&
91 satellitePvt.satVelEcef.velXMps <= kMaxVelocityMps);
92 ASSERT_TRUE(satellitePvt.satVelEcef.velYMps >= -kMaxVelocityMps &&
93 satellitePvt.satVelEcef.velYMps <= kMaxVelocityMps);
94 ASSERT_TRUE(satellitePvt.satVelEcef.velZMps >= -kMaxVelocityMps &&
95 satellitePvt.satVelEcef.velZMps <= kMaxVelocityMps);
96 ASSERT_TRUE(satellitePvt.satVelEcef.ureRateMps > 0);
97 ASSERT_TRUE(
98 satellitePvt.satClockInfo.satHardwareCodeBiasMeters > kMinHardwareCodeBiasMeters &&
99 satellitePvt.satClockInfo.satHardwareCodeBiasMeters < kMaxHardwareCodeBiasMeters);
100 ASSERT_TRUE(satellitePvt.satClockInfo.satTimeCorrectionMeters >
101 -kMaxTimeCorrelationMeters &&
102 satellitePvt.satClockInfo.satTimeCorrectionMeters < kMaxTimeCorrelationMeters);
103 ASSERT_TRUE(satellitePvt.satClockInfo.satClkDriftMps > -kMaxSatClkDriftMps &&
104 satellitePvt.satClockInfo.satClkDriftMps < kMaxSatClkDriftMps);
105 }
106 if (satellitePvt.flags & SatellitePvt::HAS_IONO) {
107 ALOGD("Found HAS_IONO");
108 ASSERT_TRUE(satellitePvt.ionoDelayMeters > 0 && satellitePvt.ionoDelayMeters < 100);
109 }
110 if (satellitePvt.flags & SatellitePvt::HAS_TROPO) {
111 ALOGD("Found HAS_TROPO");
112 ASSERT_TRUE(satellitePvt.tropoDelayMeters > 0 && satellitePvt.tropoDelayMeters < 100);
113 }
114 }
115
CheckGnssMeasurementClockFields(const GnssData & measurement)116 void CheckGnssMeasurementClockFields(const GnssData& measurement) {
117 ASSERT_TRUE(measurement.elapsedRealtime.flags >= 0 &&
118 measurement.elapsedRealtime.flags <= (ElapsedRealtime::HAS_TIMESTAMP_NS |
119 ElapsedRealtime::HAS_TIME_UNCERTAINTY_NS));
120 if (measurement.elapsedRealtime.flags & ElapsedRealtime::HAS_TIMESTAMP_NS) {
121 ASSERT_TRUE(measurement.elapsedRealtime.timestampNs > 0);
122 }
123 if (measurement.elapsedRealtime.flags & ElapsedRealtime::HAS_TIME_UNCERTAINTY_NS) {
124 ASSERT_TRUE(measurement.elapsedRealtime.timeUncertaintyNs > 0);
125 }
126 ASSERT_TRUE(measurement.clock.gnssClockFlags >= 0 &&
127 measurement.clock.gnssClockFlags <=
128 (GnssClock::HAS_LEAP_SECOND | GnssClock::HAS_TIME_UNCERTAINTY |
129 GnssClock::HAS_FULL_BIAS | GnssClock::HAS_BIAS |
130 GnssClock::HAS_BIAS_UNCERTAINTY | GnssClock::HAS_DRIFT |
131 GnssClock::HAS_DRIFT_UNCERTAINTY));
132 }
133
CheckGnssMeasurementFlags(const GnssMeasurement & measurement)134 void CheckGnssMeasurementFlags(const GnssMeasurement& measurement) {
135 ASSERT_TRUE(measurement.flags >= 0 &&
136 measurement.flags <=
137 (GnssMeasurement::HAS_SNR | GnssMeasurement::HAS_CARRIER_FREQUENCY |
138 GnssMeasurement::HAS_CARRIER_CYCLES | GnssMeasurement::HAS_CARRIER_PHASE |
139 GnssMeasurement::HAS_CARRIER_PHASE_UNCERTAINTY |
140 GnssMeasurement::HAS_AUTOMATIC_GAIN_CONTROL |
141 GnssMeasurement::HAS_FULL_ISB | GnssMeasurement::HAS_FULL_ISB_UNCERTAINTY |
142 GnssMeasurement::HAS_SATELLITE_ISB |
143 GnssMeasurement::HAS_SATELLITE_ISB_UNCERTAINTY |
144 GnssMeasurement::HAS_SATELLITE_PVT |
145 GnssMeasurement::HAS_CORRELATION_VECTOR));
146 }
147
148 /*
149 * TestGnssMeasurementExtensionAndSatellitePvt:
150 * 1. Gets the GnssMeasurementExtension and verifies that it returns a non-null extension.
151 * 2. Sets a GnssMeasurementCallback, waits for a measurement, and verifies mandatory fields are
152 * valid.
153 * 3. If SatellitePvt is supported, waits for a measurement with SatellitePvt, and verifies the
154 * fields are valid.
155 */
TEST_P(GnssHalTest,TestGnssMeasurementExtensionAndSatellitePvt)156 TEST_P(GnssHalTest, TestGnssMeasurementExtensionAndSatellitePvt) {
157 const bool kIsSatellitePvtSupported =
158 aidl_gnss_cb_->last_capabilities_ & (int)GnssCallbackAidl::CAPABILITY_SATELLITE_PVT;
159 ALOGD("SatellitePvt supported: %s", kIsSatellitePvtSupported ? "true" : "false");
160 const int kFirstGnssMeasurementTimeoutSeconds = 10;
161 const int kNumMeasurementEvents = 75;
162
163 sp<IGnssMeasurementInterface> iGnssMeasurement;
164 auto status = aidl_gnss_hal_->getExtensionGnssMeasurement(&iGnssMeasurement);
165 ASSERT_TRUE(status.isOk());
166 ASSERT_TRUE(iGnssMeasurement != nullptr);
167
168 auto callback = sp<GnssMeasurementCallbackAidl>::make();
169 status = iGnssMeasurement->setCallback(callback, /* enableFullTracking= */ true,
170 /* enableCorrVecOutputs */ false);
171 ASSERT_TRUE(status.isOk());
172
173 bool satellitePvtFound = false;
174 for (int i = 0; i < kNumMeasurementEvents; i++) {
175 if (i > 0 && (!kIsSatellitePvtSupported || satellitePvtFound)) {
176 break;
177 }
178 GnssData lastMeasurement;
179 ASSERT_TRUE(callback->gnss_data_cbq_.retrieve(lastMeasurement,
180 kFirstGnssMeasurementTimeoutSeconds));
181 EXPECT_EQ(callback->gnss_data_cbq_.calledCount(), i + 1);
182 ASSERT_TRUE(lastMeasurement.measurements.size() > 0);
183
184 // Validity check GnssData fields
185 CheckGnssMeasurementClockFields(lastMeasurement);
186
187 for (const auto& measurement : lastMeasurement.measurements) {
188 CheckGnssMeasurementFlags(measurement);
189 if (measurement.flags & GnssMeasurement::HAS_SATELLITE_PVT &&
190 kIsSatellitePvtSupported == true) {
191 ALOGD("Found a measurement with SatellitePvt");
192 satellitePvtFound = true;
193 CheckSatellitePvt(measurement.satellitePvt);
194 }
195 }
196 }
197 if (kIsSatellitePvtSupported) {
198 ASSERT_TRUE(satellitePvtFound);
199 }
200
201 status = iGnssMeasurement->close();
202 ASSERT_TRUE(status.isOk());
203 }
204
205 /*
206 * TestCorrelationVector:
207 * 1. Gets the GnssMeasurementExtension and verifies that it returns a non-null extension.
208 * 2. Sets a GnssMeasurementCallback, waits for GnssMeasurements with CorrelationVector, and
209 * verifies fields are valid.
210 */
TEST_P(GnssHalTest,TestCorrelationVector)211 TEST_P(GnssHalTest, TestCorrelationVector) {
212 const bool kIsCorrelationVectorSupported = aidl_gnss_cb_->last_capabilities_ &
213 (int)GnssCallbackAidl::CAPABILITY_CORRELATION_VECTOR;
214 const int kNumMeasurementEvents = 75;
215 // Pass the test if CorrelationVector is not supported
216 if (!kIsCorrelationVectorSupported) {
217 return;
218 }
219
220 const int kFirstGnssMeasurementTimeoutSeconds = 10;
221 sp<IGnssMeasurementInterface> iGnssMeasurement;
222 auto status = aidl_gnss_hal_->getExtensionGnssMeasurement(&iGnssMeasurement);
223 ASSERT_TRUE(status.isOk());
224 ASSERT_TRUE(iGnssMeasurement != nullptr);
225
226 auto callback = sp<GnssMeasurementCallbackAidl>::make();
227 status =
228 iGnssMeasurement->setCallback(callback, /* enableFullTracking= */ true,
229 /* enableCorrVecOutputs */ kIsCorrelationVectorSupported);
230 ASSERT_TRUE(status.isOk());
231
232 bool correlationVectorFound = false;
233 for (int i = 0; i < kNumMeasurementEvents; i++) {
234 // Pass the test if at least one CorrelationVector has been found.
235 if (correlationVectorFound) {
236 break;
237 }
238 GnssData lastMeasurement;
239 ASSERT_TRUE(callback->gnss_data_cbq_.retrieve(lastMeasurement,
240 kFirstGnssMeasurementTimeoutSeconds));
241 EXPECT_EQ(callback->gnss_data_cbq_.calledCount(), i + 1);
242 ASSERT_TRUE(lastMeasurement.measurements.size() > 0);
243
244 // Validity check GnssData fields
245 CheckGnssMeasurementClockFields(lastMeasurement);
246
247 for (const auto& measurement : lastMeasurement.measurements) {
248 CheckGnssMeasurementFlags(measurement);
249 if (measurement.flags & GnssMeasurement::HAS_CORRELATION_VECTOR) {
250 correlationVectorFound = true;
251 ASSERT_TRUE(measurement.correlationVectors.size() > 0);
252 for (const auto& correlationVector : measurement.correlationVectors) {
253 ASSERT_GE(correlationVector.frequencyOffsetMps, 0);
254 ASSERT_GT(correlationVector.samplingWidthM, 0);
255 ASSERT_TRUE(correlationVector.magnitude.size() > 0);
256 for (const auto& magnitude : correlationVector.magnitude) {
257 ASSERT_TRUE(magnitude >= -32768 && magnitude <= 32767);
258 }
259 }
260 }
261 }
262 }
263 ASSERT_TRUE(correlationVectorFound);
264
265 status = iGnssMeasurement->close();
266 ASSERT_TRUE(status.isOk());
267 }
268
269 /*
270 * TestGnssPowerIndication
271 * 1. Gets the GnssPowerIndicationExtension.
272 * 2. Sets a GnssPowerIndicationCallback.
273 * 3. Requests and verifies the 1st GnssPowerStats is received.
274 * 4. Gets a location.
275 * 5. Requests the 2nd GnssPowerStats, and verifies it has larger values than the 1st one.
276 */
TEST_P(GnssHalTest,TestGnssPowerIndication)277 TEST_P(GnssHalTest, TestGnssPowerIndication) {
278 // Set up gnssPowerIndication and callback
279 sp<IGnssPowerIndication> iGnssPowerIndication;
280 auto status = aidl_gnss_hal_->getExtensionGnssPowerIndication(&iGnssPowerIndication);
281 ASSERT_TRUE(status.isOk());
282 ASSERT_TRUE(iGnssPowerIndication != nullptr);
283
284 auto gnssPowerIndicationCallback = sp<GnssPowerIndicationCallback>::make();
285 status = iGnssPowerIndication->setCallback(gnssPowerIndicationCallback);
286 ASSERT_TRUE(status.isOk());
287
288 const int kTimeoutSec = 2;
289 EXPECT_TRUE(gnssPowerIndicationCallback->capabilities_cbq_.retrieve(
290 gnssPowerIndicationCallback->last_capabilities_, kTimeoutSec));
291
292 EXPECT_EQ(gnssPowerIndicationCallback->capabilities_cbq_.calledCount(), 1);
293
294 // Request and verify a GnssPowerStats is received
295 gnssPowerIndicationCallback->gnss_power_stats_cbq_.reset();
296 iGnssPowerIndication->requestGnssPowerStats();
297
298 EXPECT_TRUE(gnssPowerIndicationCallback->gnss_power_stats_cbq_.retrieve(
299 gnssPowerIndicationCallback->last_gnss_power_stats_, kTimeoutSec));
300 EXPECT_EQ(gnssPowerIndicationCallback->gnss_power_stats_cbq_.calledCount(), 1);
301 auto powerStats1 = gnssPowerIndicationCallback->last_gnss_power_stats_;
302
303 // Get a location and request another GnssPowerStats
304 gnss_cb_->location_cbq_.reset();
305 StartAndCheckFirstLocation(/* min_interval_msec= */ 1000, /* low_power_mode= */ false);
306
307 // Request and verify the 2nd GnssPowerStats has larger values than the 1st one
308 iGnssPowerIndication->requestGnssPowerStats();
309
310 EXPECT_TRUE(gnssPowerIndicationCallback->gnss_power_stats_cbq_.retrieve(
311 gnssPowerIndicationCallback->last_gnss_power_stats_, kTimeoutSec));
312 EXPECT_EQ(gnssPowerIndicationCallback->gnss_power_stats_cbq_.calledCount(), 2);
313
314 auto powerStats2 = gnssPowerIndicationCallback->last_gnss_power_stats_;
315
316 if ((gnssPowerIndicationCallback->last_capabilities_ &
317 (int)GnssPowerIndicationCallback::CAPABILITY_TOTAL)) {
318 // Elapsed realtime must increase
319 EXPECT_GT(powerStats2.elapsedRealtime.timestampNs, powerStats1.elapsedRealtime.timestampNs);
320
321 // Total energy must increase
322 EXPECT_GT(powerStats2.totalEnergyMilliJoule, powerStats1.totalEnergyMilliJoule);
323 }
324
325 // At least oone of singleband and multiband acquisition energy must increase
326 bool singlebandAcqEnergyIncreased = powerStats2.singlebandAcquisitionModeEnergyMilliJoule >
327 powerStats1.singlebandAcquisitionModeEnergyMilliJoule;
328 bool multibandAcqEnergyIncreased = powerStats2.multibandAcquisitionModeEnergyMilliJoule >
329 powerStats1.multibandAcquisitionModeEnergyMilliJoule;
330
331 if ((gnssPowerIndicationCallback->last_capabilities_ &
332 (int)GnssPowerIndicationCallback::CAPABILITY_SINGLEBAND_ACQUISITION) ||
333 (gnssPowerIndicationCallback->last_capabilities_ &
334 (int)GnssPowerIndicationCallback::CAPABILITY_MULTIBAND_ACQUISITION)) {
335 EXPECT_TRUE(singlebandAcqEnergyIncreased || multibandAcqEnergyIncreased);
336 }
337
338 // At least one of singleband and multiband tracking energy must increase
339 bool singlebandTrackingEnergyIncreased = powerStats2.singlebandTrackingModeEnergyMilliJoule >
340 powerStats1.singlebandTrackingModeEnergyMilliJoule;
341 bool multibandTrackingEnergyIncreased = powerStats2.multibandTrackingModeEnergyMilliJoule >
342 powerStats1.multibandTrackingModeEnergyMilliJoule;
343 if ((gnssPowerIndicationCallback->last_capabilities_ &
344 (int)GnssPowerIndicationCallback::CAPABILITY_SINGLEBAND_TRACKING) ||
345 (gnssPowerIndicationCallback->last_capabilities_ &
346 (int)GnssPowerIndicationCallback::CAPABILITY_MULTIBAND_TRACKING)) {
347 EXPECT_TRUE(singlebandTrackingEnergyIncreased || multibandTrackingEnergyIncreased);
348 }
349
350 // Clean up
351 StopAndClearLocations();
352 }
353
354 /*
355 * FindStrongFrequentNonGpsSource:
356 *
357 * Search through a GnssSvStatus list for the strongest non-GPS satellite observed enough times
358 *
359 * returns the strongest source,
360 * or a source with constellation == UNKNOWN if none are found sufficient times
361 */
FindStrongFrequentNonGpsSource(const std::list<hidl_vec<IGnssCallback_2_1::GnssSvInfo>> sv_info_list,const int min_observations)362 BlocklistedSource FindStrongFrequentNonGpsSource(
363 const std::list<hidl_vec<IGnssCallback_2_1::GnssSvInfo>> sv_info_list,
364 const int min_observations) {
365 struct ComparableBlocklistedSource {
366 BlocklistedSource id;
367
368 ComparableBlocklistedSource() {
369 id.constellation = GnssConstellationTypeAidl::UNKNOWN;
370 id.svid = 0;
371 }
372
373 bool operator<(const ComparableBlocklistedSource& compare) const {
374 return ((id.svid < compare.id.svid) || ((id.svid == compare.id.svid) &&
375 (id.constellation < compare.id.constellation)));
376 }
377 };
378
379 struct SignalCounts {
380 int observations;
381 float max_cn0_dbhz;
382 };
383
384 std::map<ComparableBlocklistedSource, SignalCounts> mapSignals;
385
386 for (const auto& sv_info_vec : sv_info_list) {
387 for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
388 const auto& gnss_sv = sv_info_vec[iSv];
389 if ((gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX) &&
390 (gnss_sv.v2_0.constellation != GnssConstellationType::GPS)) {
391 ComparableBlocklistedSource source;
392 source.id.svid = gnss_sv.v2_0.v1_0.svid;
393 source.id.constellation =
394 static_cast<GnssConstellationTypeAidl>(gnss_sv.v2_0.constellation);
395
396 const auto& itSignal = mapSignals.find(source);
397 if (itSignal == mapSignals.end()) {
398 SignalCounts counts;
399 counts.observations = 1;
400 counts.max_cn0_dbhz = gnss_sv.v2_0.v1_0.cN0Dbhz;
401 mapSignals.insert(
402 std::pair<ComparableBlocklistedSource, SignalCounts>(source, counts));
403 } else {
404 itSignal->second.observations++;
405 if (itSignal->second.max_cn0_dbhz < gnss_sv.v2_0.v1_0.cN0Dbhz) {
406 itSignal->second.max_cn0_dbhz = gnss_sv.v2_0.v1_0.cN0Dbhz;
407 }
408 }
409 }
410 }
411 }
412
413 float max_cn0_dbhz_with_sufficient_count = 0.;
414 int total_observation_count = 0;
415 int blocklisted_source_count_observation = 0;
416
417 ComparableBlocklistedSource source_to_blocklist; // initializes to zero = UNKNOWN constellation
418 for (auto const& pairSignal : mapSignals) {
419 total_observation_count += pairSignal.second.observations;
420 if ((pairSignal.second.observations >= min_observations) &&
421 (pairSignal.second.max_cn0_dbhz > max_cn0_dbhz_with_sufficient_count)) {
422 source_to_blocklist = pairSignal.first;
423 blocklisted_source_count_observation = pairSignal.second.observations;
424 max_cn0_dbhz_with_sufficient_count = pairSignal.second.max_cn0_dbhz;
425 }
426 }
427 ALOGD("Among %d observations, chose svid %d, constellation %d, "
428 "with %d observations at %.1f max CNo",
429 total_observation_count, source_to_blocklist.id.svid,
430 (int)source_to_blocklist.id.constellation, blocklisted_source_count_observation,
431 max_cn0_dbhz_with_sufficient_count);
432
433 return source_to_blocklist.id;
434 }
435
436 /*
437 * BlocklistIndividualSatellites:
438 *
439 * 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding
440 * GnssStatus for common satellites (strongest and one other.)
441 * 2a & b) Turns off location, and blocklists common satellites.
442 * 3) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding
443 * GnssStatus does not use those satellites.
444 * 4a & b) Turns off location, and send in empty blocklist.
445 * 5a) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding
446 * GnssStatus does re-use at least the previously strongest satellite
447 * 5b) Retry a few times, in case GNSS search strategy takes a while to reacquire even the
448 * formerly strongest satellite
449 */
TEST_P(GnssHalTest,BlocklistIndividualSatellites)450 TEST_P(GnssHalTest, BlocklistIndividualSatellites) {
451 if (!(aidl_gnss_cb_->last_capabilities_ &
452 (int)GnssCallbackAidl::CAPABILITY_SATELLITE_BLOCKLIST)) {
453 ALOGI("Test BlocklistIndividualSatellites skipped. SATELLITE_BLOCKLIST capability not "
454 "supported.");
455 return;
456 }
457
458 const int kLocationsToAwait = 3;
459 const int kRetriesToUnBlocklist = 10;
460
461 gnss_cb_->location_cbq_.reset();
462 StartAndCheckLocations(kLocationsToAwait);
463 int location_called_count = gnss_cb_->location_cbq_.calledCount();
464
465 // Tolerate 1 less sv status to handle edge cases in reporting.
466 int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
467 EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
468 ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations (%d received)",
469 sv_info_list_cbq_size, kLocationsToAwait, location_called_count);
470
471 /*
472 * Identify strongest SV seen at least kLocationsToAwait -1 times
473 * Why -1? To avoid test flakiness in case of (plausible) slight flakiness in strongest signal
474 * observability (one epoch RF null)
475 */
476
477 const int kGnssSvInfoListTimeout = 2;
478 std::list<hidl_vec<IGnssCallback_2_1::GnssSvInfo>> sv_info_vec_list;
479 int count = gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec_list, sv_info_list_cbq_size,
480 kGnssSvInfoListTimeout);
481
482 ASSERT_EQ(count, sv_info_list_cbq_size);
483
484 BlocklistedSource source_to_blocklist =
485 FindStrongFrequentNonGpsSource(sv_info_vec_list, kLocationsToAwait - 1);
486
487 if (source_to_blocklist.constellation == GnssConstellationTypeAidl::UNKNOWN) {
488 // Cannot find a non-GPS satellite. Let the test pass.
489 ALOGD("Cannot find a non-GPS satellite. Letting the test pass.");
490 return;
491 }
492
493 // Stop locations, blocklist the common SV
494 StopAndClearLocations();
495
496 sp<IGnssConfiguration> gnss_configuration_hal;
497 auto status = aidl_gnss_hal_->getExtensionGnssConfiguration(&gnss_configuration_hal);
498 ASSERT_TRUE(status.isOk());
499 ASSERT_NE(gnss_configuration_hal, nullptr);
500
501 std::vector<BlocklistedSource> sources;
502 sources.resize(1);
503 sources[0] = source_to_blocklist;
504
505 status = gnss_configuration_hal->setBlocklist(sources);
506 ASSERT_TRUE(status.isOk());
507
508 // retry and ensure satellite not used
509 gnss_cb_->sv_info_list_cbq_.reset();
510
511 gnss_cb_->location_cbq_.reset();
512 StartAndCheckLocations(kLocationsToAwait);
513
514 // early exit if test is being run with insufficient signal
515 location_called_count = gnss_cb_->location_cbq_.calledCount();
516 if (location_called_count == 0) {
517 ALOGE("0 Gnss locations received - ensure sufficient signal and retry");
518 }
519 ASSERT_TRUE(location_called_count > 0);
520
521 // Tolerate 1 less sv status to handle edge cases in reporting.
522 sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
523 EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
524 ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations (%d received)",
525 sv_info_list_cbq_size, kLocationsToAwait, location_called_count);
526 for (int i = 0; i < sv_info_list_cbq_size; ++i) {
527 hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
528 gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
529 for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
530 const auto& gnss_sv = sv_info_vec[iSv];
531 EXPECT_FALSE((gnss_sv.v2_0.v1_0.svid == source_to_blocklist.svid) &&
532 (static_cast<GnssConstellationTypeAidl>(gnss_sv.v2_0.constellation) ==
533 source_to_blocklist.constellation) &&
534 (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
535 }
536 }
537
538 // clear blocklist and restart - this time updating the blocklist while location is still on
539 sources.resize(0);
540
541 status = gnss_configuration_hal->setBlocklist(sources);
542 ASSERT_TRUE(status.isOk());
543
544 bool strongest_sv_is_reobserved = false;
545 // do several loops awaiting a few locations, allowing non-immediate reacquisition strategies
546 int unblocklist_loops_remaining = kRetriesToUnBlocklist;
547 while (!strongest_sv_is_reobserved && (unblocklist_loops_remaining-- > 0)) {
548 StopAndClearLocations();
549 gnss_cb_->sv_info_list_cbq_.reset();
550
551 gnss_cb_->location_cbq_.reset();
552 StartAndCheckLocations(kLocationsToAwait);
553
554 // early exit loop if test is being run with insufficient signal
555 location_called_count = gnss_cb_->location_cbq_.calledCount();
556 if (location_called_count == 0) {
557 ALOGE("0 Gnss locations received - ensure sufficient signal and retry");
558 }
559 ASSERT_TRUE(location_called_count > 0);
560
561 // Tolerate 1 less sv status to handle edge cases in reporting.
562 sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
563 EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
564 ALOGD("Clear blocklist, observed %d GnssSvInfo, while awaiting %d Locations"
565 ", tries remaining %d",
566 sv_info_list_cbq_size, kLocationsToAwait, unblocklist_loops_remaining);
567
568 for (int i = 0; i < sv_info_list_cbq_size; ++i) {
569 hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
570 gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
571 for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
572 const auto& gnss_sv = sv_info_vec[iSv];
573 if ((gnss_sv.v2_0.v1_0.svid == source_to_blocklist.svid) &&
574 (static_cast<GnssConstellationTypeAidl>(gnss_sv.v2_0.constellation) ==
575 source_to_blocklist.constellation) &&
576 (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX)) {
577 strongest_sv_is_reobserved = true;
578 break;
579 }
580 }
581 if (strongest_sv_is_reobserved) break;
582 }
583 }
584 EXPECT_TRUE(strongest_sv_is_reobserved);
585 StopAndClearLocations();
586 }
587
588 /*
589 * BlocklistConstellationLocationOff:
590 *
591 * 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding
592 * GnssStatus for any non-GPS constellations.
593 * 2a & b) Turns off location, and blocklist first non-GPS constellations.
594 * 3) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding
595 * GnssStatus does not use any constellation but GPS.
596 * 4a & b) Clean up by turning off location, and send in empty blocklist.
597 */
TEST_P(GnssHalTest,BlocklistConstellationLocationOff)598 TEST_P(GnssHalTest, BlocklistConstellationLocationOff) {
599 if (!(aidl_gnss_cb_->last_capabilities_ &
600 (int)GnssCallbackAidl::CAPABILITY_SATELLITE_BLOCKLIST)) {
601 ALOGI("Test BlocklistConstellationLocationOff skipped. SATELLITE_BLOCKLIST capability not "
602 "supported.");
603 return;
604 }
605
606 const int kLocationsToAwait = 3;
607 const int kGnssSvInfoListTimeout = 2;
608
609 // Find first non-GPS constellation to blocklist
610 GnssConstellationTypeAidl constellation_to_blocklist = static_cast<GnssConstellationTypeAidl>(
611 startLocationAndGetNonGpsConstellation(kLocationsToAwait, kGnssSvInfoListTimeout));
612
613 // Turns off location
614 StopAndClearLocations();
615
616 BlocklistedSource source_to_blocklist_1;
617 source_to_blocklist_1.constellation = constellation_to_blocklist;
618 source_to_blocklist_1.svid = 0; // documented wildcard for all satellites in this constellation
619
620 // IRNSS was added in 2.0. Always attempt to blocklist IRNSS to verify that the new enum is
621 // supported.
622 BlocklistedSource source_to_blocklist_2;
623 source_to_blocklist_2.constellation = GnssConstellationTypeAidl::IRNSS;
624 source_to_blocklist_2.svid = 0; // documented wildcard for all satellites in this constellation
625
626 sp<IGnssConfiguration> gnss_configuration_hal;
627 auto status = aidl_gnss_hal_->getExtensionGnssConfiguration(&gnss_configuration_hal);
628 ASSERT_TRUE(status.isOk());
629 ASSERT_NE(gnss_configuration_hal, nullptr);
630
631 hidl_vec<BlocklistedSource> sources;
632 sources.resize(2);
633 sources[0] = source_to_blocklist_1;
634 sources[1] = source_to_blocklist_2;
635
636 status = gnss_configuration_hal->setBlocklist(sources);
637 ASSERT_TRUE(status.isOk());
638
639 // retry and ensure constellation not used
640 gnss_cb_->sv_info_list_cbq_.reset();
641
642 gnss_cb_->location_cbq_.reset();
643 StartAndCheckLocations(kLocationsToAwait);
644
645 // Tolerate 1 less sv status to handle edge cases in reporting.
646 int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
647 EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
648 ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations", sv_info_list_cbq_size,
649 kLocationsToAwait);
650 for (int i = 0; i < sv_info_list_cbq_size; ++i) {
651 hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
652 gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
653 for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
654 const auto& gnss_sv = sv_info_vec[iSv];
655 EXPECT_FALSE((static_cast<GnssConstellationTypeAidl>(gnss_sv.v2_0.constellation) ==
656 source_to_blocklist_1.constellation) &&
657 (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
658 EXPECT_FALSE((static_cast<GnssConstellationTypeAidl>(gnss_sv.v2_0.constellation) ==
659 source_to_blocklist_2.constellation) &&
660 (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
661 }
662 }
663
664 // clean up
665 StopAndClearLocations();
666 sources.resize(0);
667 status = gnss_configuration_hal->setBlocklist(sources);
668 ASSERT_TRUE(status.isOk());
669 }
670
671 /*
672 * BlocklistConstellationLocationOn:
673 *
674 * 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding
675 * GnssStatus for any non-GPS constellations.
676 * 2a & b) Blocklist first non-GPS constellation, and turn off location.
677 * 3) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding
678 * GnssStatus does not use any constellation but GPS.
679 * 4a & b) Clean up by turning off location, and send in empty blocklist.
680 */
TEST_P(GnssHalTest,BlocklistConstellationLocationOn)681 TEST_P(GnssHalTest, BlocklistConstellationLocationOn) {
682 if (!(aidl_gnss_cb_->last_capabilities_ &
683 (int)GnssCallbackAidl::CAPABILITY_SATELLITE_BLOCKLIST)) {
684 ALOGI("Test BlocklistConstellationLocationOn skipped. SATELLITE_BLOCKLIST capability not "
685 "supported.");
686 return;
687 }
688
689 const int kLocationsToAwait = 3;
690 const int kGnssSvInfoListTimeout = 2;
691
692 // Find first non-GPS constellation to blocklist
693 GnssConstellationTypeAidl constellation_to_blocklist = static_cast<GnssConstellationTypeAidl>(
694 startLocationAndGetNonGpsConstellation(kLocationsToAwait, kGnssSvInfoListTimeout));
695
696 BlocklistedSource source_to_blocklist_1;
697 source_to_blocklist_1.constellation = constellation_to_blocklist;
698 source_to_blocklist_1.svid = 0; // documented wildcard for all satellites in this constellation
699
700 // IRNSS was added in 2.0. Always attempt to blocklist IRNSS to verify that the new enum is
701 // supported.
702 BlocklistedSource source_to_blocklist_2;
703 source_to_blocklist_2.constellation = GnssConstellationTypeAidl::IRNSS;
704 source_to_blocklist_2.svid = 0; // documented wildcard for all satellites in this constellation
705
706 sp<IGnssConfiguration> gnss_configuration_hal;
707 auto status = aidl_gnss_hal_->getExtensionGnssConfiguration(&gnss_configuration_hal);
708 ASSERT_TRUE(status.isOk());
709 ASSERT_NE(gnss_configuration_hal, nullptr);
710
711 hidl_vec<BlocklistedSource> sources;
712 sources.resize(2);
713 sources[0] = source_to_blocklist_1;
714 sources[1] = source_to_blocklist_2;
715
716 status = gnss_configuration_hal->setBlocklist(sources);
717 ASSERT_TRUE(status.isOk());
718
719 // Turns off location
720 StopAndClearLocations();
721
722 // retry and ensure constellation not used
723 gnss_cb_->sv_info_list_cbq_.reset();
724
725 gnss_cb_->location_cbq_.reset();
726 StartAndCheckLocations(kLocationsToAwait);
727
728 // Tolerate 1 less sv status to handle edge cases in reporting.
729 int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
730 EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
731 ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations", sv_info_list_cbq_size,
732 kLocationsToAwait);
733 for (int i = 0; i < sv_info_list_cbq_size; ++i) {
734 hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
735 gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
736 for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
737 const auto& gnss_sv = sv_info_vec[iSv];
738 EXPECT_FALSE((static_cast<GnssConstellationTypeAidl>(gnss_sv.v2_0.constellation) ==
739 source_to_blocklist_1.constellation) &&
740 (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
741 EXPECT_FALSE((static_cast<GnssConstellationTypeAidl>(gnss_sv.v2_0.constellation) ==
742 source_to_blocklist_2.constellation) &&
743 (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
744 }
745 }
746
747 // clean up
748 StopAndClearLocations();
749 sources.resize(0);
750 status = gnss_configuration_hal->setBlocklist(sources);
751 ASSERT_TRUE(status.isOk());
752 }
753