1 /*
2 * Copyright (C) 2018 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 "Utils.h"
21
22 #include <gtest/gtest.h>
23
24 using android::hardware::hidl_string;
25 using android::hardware::hidl_vec;
26
27 using IGnssConfiguration_2_0 = android::hardware::gnss::V2_0::IGnssConfiguration;
28 using IGnssConfiguration_1_1 = android::hardware::gnss::V1_1::IGnssConfiguration;
29 using IAGnssRil_2_0 = android::hardware::gnss::V2_0::IAGnssRil;
30 using IGnssMeasurement_2_0 = android::hardware::gnss::V2_0::IGnssMeasurement;
31 using IGnssMeasurement_1_1 = android::hardware::gnss::V1_1::IGnssMeasurement;
32 using IGnssMeasurement_1_0 = android::hardware::gnss::V1_0::IGnssMeasurement;
33 using IAGnssRil_2_0 = android::hardware::gnss::V2_0::IAGnssRil;
34 using IAGnssRil_1_0 = android::hardware::gnss::V1_0::IAGnssRil;
35 using IAGnss_2_0 = android::hardware::gnss::V2_0::IAGnss;
36 using IAGnss_1_0 = android::hardware::gnss::V1_0::IAGnss;
37 using IAGnssCallback_2_0 = android::hardware::gnss::V2_0::IAGnssCallback;
38
39 using android::hardware::gnss::common::Utils;
40 using android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections;
41 using android::hardware::gnss::measurement_corrections::V1_0::MeasurementCorrections;
42 using android::hardware::gnss::V1_0::IGnssNi;
43 using android::hardware::gnss::V2_0::ElapsedRealtimeFlags;
44 using android::hardware::gnss::V2_0::IGnssCallback;
45 using android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl;
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_0 = gnss_hal_->getExtensionGnssMeasurement_2_0();
61 auto gnssMeasurement_1_1 = gnss_hal_->getExtensionGnssMeasurement_1_1();
62 auto gnssMeasurement_1_0 = gnss_hal_->getExtensionGnssMeasurement();
63 ASSERT_TRUE(gnssMeasurement_2_0.isOk() && gnssMeasurement_1_1.isOk() &&
64 gnssMeasurement_1_0.isOk());
65
66 // CDD does not require Android Automotive OS devices to support
67 // GnssMeasurements.
68 if (Utils::isAutomotiveDevice()) {
69 ALOGI("Test GnssMeasurementExtension skipped. Android Automotive OS deice is not required "
70 "to support GNSS measurements.");
71 return;
72 }
73
74 sp<IGnssMeasurement_2_0> iGnssMeas_2_0 = gnssMeasurement_2_0;
75 sp<IGnssMeasurement_1_1> iGnssMeas_1_1 = gnssMeasurement_1_1;
76 sp<IGnssMeasurement_1_0> iGnssMeas_1_0 = gnssMeasurement_1_0;
77 // At least one interface is non-null.
78 int numNonNull = (int)(iGnssMeas_2_0 != nullptr) + (int)(iGnssMeas_1_1 != nullptr) +
79 (int)(iGnssMeas_1_0 != nullptr);
80 ASSERT_TRUE(numNonNull >= 1);
81 }
82
83 /*
84 * TestGnssConfigurationExtension:
85 * Gets the GnssConfigurationExtension and verifies that it returns an actual extension by
86 * calling a method.
87 *
88 * The GNSS HAL 2.0 implementation must support @2.0::IGnssConfiguration interface due to
89 * the deprecation of some methods in @1.0::IGnssConfiguration interface.
90 */
TEST_P(GnssHalTest,TestGnssConfigurationExtension)91 TEST_P(GnssHalTest, TestGnssConfigurationExtension) {
92 auto gnssConfiguration = gnss_hal_->getExtensionGnssConfiguration_2_0();
93 ASSERT_TRUE(gnssConfiguration.isOk());
94 sp<IGnssConfiguration_2_0> iGnssConfiguration = gnssConfiguration;
95 ASSERT_NE(iGnssConfiguration, nullptr);
96
97 auto result = iGnssConfiguration->setEsExtensionSec(180);
98 ASSERT_TRUE(result.isOk());
99 // Expected result can be true or false depending on whether HAL implementation supports
100 // detecting emergency sessions without involving the framework.
101 }
102
103 /*
104 * TestGnssConfiguration_setSuplEs_Deprecation:
105 * Calls setSuplEs and verifies that it returns false.
106 */
TEST_P(GnssHalTest,TestGnssConfiguration_setSuplEs_Deprecation)107 TEST_P(GnssHalTest, TestGnssConfiguration_setSuplEs_Deprecation) {
108 auto gnssConfiguration = gnss_hal_->getExtensionGnssConfiguration_2_0();
109 ASSERT_TRUE(gnssConfiguration.isOk());
110 sp<IGnssConfiguration_2_0> iGnssConfiguration = gnssConfiguration;
111 ASSERT_NE(iGnssConfiguration, nullptr);
112
113 auto result = iGnssConfiguration->setSuplEs(false);
114 ASSERT_TRUE(result.isOk());
115 EXPECT_FALSE(result);
116 }
117
118 /*
119 * TestGnssConfiguration_setGpsLock_Deprecation:
120 * Calls setGpsLock and verifies that it returns false.
121 */
TEST_P(GnssHalTest,TestGnssConfiguration_setGpsLock_Deprecation)122 TEST_P(GnssHalTest, TestGnssConfiguration_setGpsLock_Deprecation) {
123 auto gnssConfiguration = gnss_hal_->getExtensionGnssConfiguration_2_0();
124 ASSERT_TRUE(gnssConfiguration.isOk());
125 sp<IGnssConfiguration_2_0> iGnssConfiguration = gnssConfiguration;
126 ASSERT_NE(iGnssConfiguration, nullptr);
127
128 auto result = iGnssConfiguration->setGpsLock(0);
129 ASSERT_TRUE(result.isOk());
130 EXPECT_FALSE(result);
131 }
132
133 /*
134 * TestAGnssRilExtension:
135 * Gets the AGnssRilExtension and verifies that it returns an actual extension.
136 *
137 * If IAGnssRil interface is supported, then the GNSS HAL 2.0 implementation must support
138 * @2.0::IAGnssRil interface due to the deprecation of framework network API methods needed
139 * to support the @1.0::IAGnssRil interface.
140 */
TEST_P(GnssHalTest,TestAGnssRilExtension)141 TEST_P(GnssHalTest, TestAGnssRilExtension) {
142 auto agnssRil_2_0 = gnss_hal_->getExtensionAGnssRil_2_0();
143 ASSERT_TRUE(agnssRil_2_0.isOk());
144 sp<IAGnssRil_2_0> iAGnssRil_2_0 = agnssRil_2_0;
145 if (iAGnssRil_2_0 == nullptr) {
146 // Verify IAGnssRil 1.0 is not supported.
147 auto agnssRil_1_0 = gnss_hal_->getExtensionAGnssRil();
148 ASSERT_TRUE(agnssRil_1_0.isOk());
149 sp<IAGnssRil_1_0> iAGnssRil_1_0 = agnssRil_1_0;
150 ASSERT_EQ(iAGnssRil_1_0, nullptr);
151 }
152 }
153
154 /*
155 * TestAGnssRil_UpdateNetworkState_2_0:
156 * 1. Updates GNSS HAL that a network has connected.
157 * 2. Updates GNSS HAL that network has disconnected.
158 */
TEST_P(GnssHalTest,TestAGnssRil_UpdateNetworkState_2_0)159 TEST_P(GnssHalTest, TestAGnssRil_UpdateNetworkState_2_0) {
160 auto agnssRil = gnss_hal_->getExtensionAGnssRil_2_0();
161 ASSERT_TRUE(agnssRil.isOk());
162 sp<IAGnssRil_2_0> iAGnssRil = agnssRil;
163 if (iAGnssRil == nullptr) {
164 return;
165 }
166
167 // Update GNSS HAL that a network has connected.
168 IAGnssRil_2_0::NetworkAttributes networkAttributes = {
169 .networkHandle = static_cast<uint64_t>(7700664333),
170 .isConnected = true,
171 .capabilities = static_cast<uint16_t>(IAGnssRil_2_0::NetworkCapability::NOT_ROAMING),
172 .apn = "dummy-apn"};
173 auto result = iAGnssRil->updateNetworkState_2_0(networkAttributes);
174 ASSERT_TRUE(result.isOk());
175 EXPECT_TRUE(result);
176
177 // Update GNSS HAL that network has disconnected.
178 networkAttributes.isConnected = false;
179 result = iAGnssRil->updateNetworkState_2_0(networkAttributes);
180 ASSERT_TRUE(result.isOk());
181 EXPECT_TRUE(result);
182 }
183
184 /*
185 * TestGnssMeasurementFields:
186 * Sets a GnssMeasurementCallback, waits for a measurement, and verifies
187 * 1. codeType is valid,
188 * 2. constellation is valid.
189 * 3. state is valid.
190 */
TEST_P(GnssHalTest,TestGnssMeasurementFields)191 TEST_P(GnssHalTest, TestGnssMeasurementFields) {
192 if (!IsGnssHalVersion_2_0()) {
193 ALOGI("Test GnssMeasurementFields skipped. GNSS HAL version is greater than 2.0.");
194 return;
195 }
196 const int kFirstGnssMeasurementTimeoutSeconds = 10;
197
198 auto gnssMeasurement = gnss_hal_->getExtensionGnssMeasurement_2_0();
199 if (!gnssMeasurement.isOk()) {
200 return;
201 }
202
203 sp<IGnssMeasurement_2_0> iGnssMeasurement = gnssMeasurement;
204 if (iGnssMeasurement == nullptr) {
205 return;
206 }
207
208 sp<GnssMeasurementCallback> callback = new GnssMeasurementCallback();
209 auto result = iGnssMeasurement->setCallback_2_0(callback, /* enableFullTracking= */ true);
210 ASSERT_TRUE(result.isOk());
211 EXPECT_EQ(result, IGnssMeasurement_1_0::GnssMeasurementStatus::SUCCESS);
212
213 IGnssMeasurementCallback_2_0::GnssData lastMeasurement;
214 ASSERT_TRUE(callback->measurement_cbq_.retrieve(lastMeasurement,
215 kFirstGnssMeasurementTimeoutSeconds));
216 EXPECT_EQ(callback->measurement_cbq_.calledCount(), 1);
217 ASSERT_TRUE(lastMeasurement.measurements.size() > 0);
218 for (auto measurement : lastMeasurement.measurements) {
219 // Verify CodeType is valid.
220 ASSERT_NE(measurement.codeType, "");
221
222 // Verify ConstellationType is valid.
223 ASSERT_TRUE(static_cast<uint8_t>(measurement.constellation) >=
224 static_cast<uint8_t>(GnssConstellationType_2_0::UNKNOWN) &&
225 static_cast<uint8_t>(measurement.constellation) <=
226 static_cast<uint8_t>(GnssConstellationType_2_0::IRNSS));
227
228 // Verify State is valid.
229 ASSERT_TRUE(
230 static_cast<uint32_t>(measurement.state) >=
231 static_cast<uint32_t>(IGnssMeasurementCallback_2_0::GnssMeasurementState::
232 STATE_UNKNOWN) &&
233 static_cast<uint32_t>(measurement.state) <
234 (static_cast<uint32_t>(IGnssMeasurementCallback_2_0::GnssMeasurementState::
235 STATE_2ND_CODE_LOCK)
236 << 1));
237 }
238
239 iGnssMeasurement->close();
240 }
241
242 /*
243 * TestAGnssExtension:
244 * Gets the AGnssExtension and verifies that it returns an actual extension.
245 *
246 * If IAGnss interface is supported, then the GNSS HAL 2.0 implementation must support
247 * @2.0::IAGnss interface due to the deprecation of framework network API methods needed
248 * to support the @1.0::IAGnss interface.
249 */
TEST_P(GnssHalTest,TestAGnssExtension)250 TEST_P(GnssHalTest, TestAGnssExtension) {
251 auto agnss_2_0 = gnss_hal_->getExtensionAGnss_2_0();
252 ASSERT_TRUE(agnss_2_0.isOk());
253 sp<IAGnss_2_0> iAGnss_2_0 = agnss_2_0;
254 if (iAGnss_2_0 == nullptr) {
255 // Verify IAGnss 1.0 is not supported.
256 auto agnss_1_0 = gnss_hal_->getExtensionAGnss();
257 ASSERT_TRUE(agnss_1_0.isOk());
258 sp<IAGnss_1_0> iAGnss_1_0 = agnss_1_0;
259 ASSERT_EQ(iAGnss_1_0, nullptr);
260 return;
261 }
262
263 // Set SUPL server host/port
264 auto result =
265 iAGnss_2_0->setServer(IAGnssCallback_2_0::AGnssType::SUPL, "supl.google.com", 7275);
266 ASSERT_TRUE(result.isOk());
267 EXPECT_TRUE(result);
268 }
269
270 /*
271 * TestGnssNiExtension_Deprecation:
272 * Gets the @1.0::IGnssNi extension and verifies that it is a nullptr.
273 */
TEST_P(GnssHalTest,TestGnssNiExtension_Deprecation)274 TEST_P(GnssHalTest, TestGnssNiExtension_Deprecation) {
275 // Verify IGnssNi 1.0 is not supported.
276 auto gnssNi = gnss_hal_->getExtensionGnssNi();
277 ASSERT_TRUE(!gnssNi.isOk() || ((sp<IGnssNi>)gnssNi) == nullptr);
278 }
279
280 /*
281 * TestGnssVisibilityControlExtension:
282 * Gets the GnssVisibilityControlExtension and if it is not null, verifies that it supports
283 * the gnss.visibility_control@1.0::IGnssVisibilityControl interface by invoking a method.
284 */
TEST_P(GnssHalTest,TestGnssVisibilityControlExtension)285 TEST_P(GnssHalTest, TestGnssVisibilityControlExtension) {
286 auto gnssVisibilityControl = gnss_hal_->getExtensionVisibilityControl();
287 ASSERT_TRUE(gnssVisibilityControl.isOk());
288 sp<IGnssVisibilityControl> iGnssVisibilityControl = gnssVisibilityControl;
289 if (iGnssVisibilityControl == nullptr) {
290 return;
291 }
292
293 // Set non-framework proxy apps.
294 hidl_vec<hidl_string> proxyApps{"com.example.ims", "com.example.mdt"};
295 auto result = iGnssVisibilityControl->enableNfwLocationAccess(proxyApps);
296 ASSERT_TRUE(result.isOk());
297 EXPECT_TRUE(result);
298 }
299
300 /*
301 * TestGnssMeasurementCorrectionsCapabilities:
302 * If measurement corrections capability is supported, verifies that the measurement corrections
303 * capabilities are reported and the mandatory LOS_SATS or the EXCESS_PATH_LENGTH
304 * capability flag is set.
305 */
TEST_P(GnssHalTest,TestGnssMeasurementCorrectionsCapabilities)306 TEST_P(GnssHalTest, TestGnssMeasurementCorrectionsCapabilities) {
307 if (!IsGnssHalVersion_2_0()) {
308 ALOGI("Test GnssMeasurementCorrectionsCapabilities skipped. GNSS HAL version is greater "
309 "than 2.0.");
310 return;
311 }
312
313 if (!(gnss_cb_->last_capabilities_ & IGnssCallback::Capabilities::MEASUREMENT_CORRECTIONS)) {
314 return;
315 }
316
317 auto measurementCorrections = gnss_hal_->getExtensionMeasurementCorrections();
318 ASSERT_TRUE(measurementCorrections.isOk());
319 sp<IMeasurementCorrections> iMeasurementCorrections = measurementCorrections;
320 ASSERT_NE(iMeasurementCorrections, nullptr);
321
322 // Setup measurement corrections callback.
323 sp<GnssMeasurementCorrectionsCallback> callback = new GnssMeasurementCorrectionsCallback();
324 iMeasurementCorrections->setCallback(callback);
325
326 const int kMeasurementCorrectionsCapabilitiesTimeoutSeconds = 5;
327 callback->capabilities_cbq_.retrieve(callback->last_capabilities_,
328 kMeasurementCorrectionsCapabilitiesTimeoutSeconds);
329 ASSERT_TRUE(callback->capabilities_cbq_.calledCount() > 0);
330 using Capabilities = IMeasurementCorrectionsCallback::Capabilities;
331 ASSERT_TRUE((callback->last_capabilities_ &
332 (Capabilities::LOS_SATS | Capabilities::EXCESS_PATH_LENGTH)) != 0);
333 }
334
335 /*
336 * TestGnssMeasurementCorrections:
337 * If measurement corrections capability is supported, verifies that it supports the
338 * gnss.measurement_corrections@1.0::IMeasurementCorrections interface by invoking a method.
339 */
TEST_P(GnssHalTest,TestGnssMeasurementCorrections)340 TEST_P(GnssHalTest, TestGnssMeasurementCorrections) {
341 if (!(gnss_cb_->last_capabilities_ & IGnssCallback::Capabilities::MEASUREMENT_CORRECTIONS)) {
342 return;
343 }
344
345 // Verify IMeasurementCorrections is supported.
346 auto measurementCorrections = gnss_hal_->getExtensionMeasurementCorrections();
347 ASSERT_TRUE(measurementCorrections.isOk());
348 sp<IMeasurementCorrections> iMeasurementCorrections = measurementCorrections;
349 ASSERT_NE(iMeasurementCorrections, nullptr);
350
351 sp<GnssMeasurementCorrectionsCallback> callback = new GnssMeasurementCorrectionsCallback();
352 iMeasurementCorrections->setCallback(callback);
353
354 const int kMeasurementCorrectionsCapabilitiesTimeoutSeconds = 5;
355 callback->capabilities_cbq_.retrieve(callback->last_capabilities_,
356 kMeasurementCorrectionsCapabilitiesTimeoutSeconds);
357 ASSERT_TRUE(callback->capabilities_cbq_.calledCount() > 0);
358
359 // Set a mock MeasurementCorrections.
360 auto result = iMeasurementCorrections->setCorrections(Utils::getMockMeasurementCorrections());
361 ASSERT_TRUE(result.isOk());
362 EXPECT_TRUE(result);
363 }
364
365 /*
366 * TestGnssDataElapsedRealtimeFlags:
367 * Sets a GnssMeasurementCallback, waits for a GnssData object, and verifies the flags in member
368 * elapsedRealitme are valid.
369 */
TEST_P(GnssHalTest,TestGnssDataElapsedRealtimeFlags)370 TEST_P(GnssHalTest, TestGnssDataElapsedRealtimeFlags) {
371 const int kFirstGnssMeasurementTimeoutSeconds = 10;
372
373 auto gnssMeasurement = gnss_hal_->getExtensionGnssMeasurement_2_0();
374 if (!gnssMeasurement.isOk()) {
375 return;
376 }
377
378 sp<IGnssMeasurement_2_0> iGnssMeasurement = gnssMeasurement;
379 if (iGnssMeasurement == nullptr) {
380 return;
381 }
382
383 sp<GnssMeasurementCallback> callback = new GnssMeasurementCallback();
384 auto result = iGnssMeasurement->setCallback_2_0(callback, /* enableFullTracking= */ true);
385 ASSERT_TRUE(result.isOk());
386 EXPECT_EQ(result, IGnssMeasurement_1_0::GnssMeasurementStatus::SUCCESS);
387
388 IGnssMeasurementCallback_2_0::GnssData lastMeasurement;
389 ASSERT_TRUE(callback->measurement_cbq_.retrieve(lastMeasurement,
390 kFirstGnssMeasurementTimeoutSeconds));
391 EXPECT_EQ(callback->measurement_cbq_.calledCount(), 1);
392
393 ASSERT_TRUE((int)lastMeasurement.elapsedRealtime.flags <=
394 (int)(ElapsedRealtimeFlags::HAS_TIMESTAMP_NS |
395 ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS));
396
397 // We expect a non-zero timestamp when set.
398 if (lastMeasurement.elapsedRealtime.flags & ElapsedRealtimeFlags::HAS_TIMESTAMP_NS) {
399 ASSERT_TRUE(lastMeasurement.elapsedRealtime.timestampNs != 0);
400 }
401
402 iGnssMeasurement->close();
403 }
404
TEST_P(GnssHalTest,TestGnssLocationElapsedRealtime)405 TEST_P(GnssHalTest, TestGnssLocationElapsedRealtime) {
406 StartAndCheckFirstLocation(/* strict= */ true,
407 /* min_interval_msec= */ 1000,
408 /* low_power_mode= */ false);
409
410 ASSERT_TRUE((int)gnss_cb_->last_location_.elapsedRealtime.flags <=
411 (int)(ElapsedRealtimeFlags::HAS_TIMESTAMP_NS |
412 ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS));
413
414 // We expect a non-zero timestamp when set.
415 if (gnss_cb_->last_location_.elapsedRealtime.flags & ElapsedRealtimeFlags::HAS_TIMESTAMP_NS) {
416 ASSERT_TRUE(gnss_cb_->last_location_.elapsedRealtime.timestampNs != 0);
417 }
418
419 StopAndClearLocations();
420 }
421
422 // This test only verify that injectBestLocation_2_0 does not crash.
TEST_P(GnssHalTest,TestInjectBestLocation_2_0)423 TEST_P(GnssHalTest, TestInjectBestLocation_2_0) {
424 StartAndCheckFirstLocation(/* strict= */ true,
425 /* min_interval_msec= */ 1000,
426 /* low_power_mode= */ false);
427 gnss_hal_->injectBestLocation_2_0(gnss_cb_->last_location_);
428 StopAndClearLocations();
429 }
430
431 /*
432 * TestGnssBatchingExtension:
433 * Gets the @2.0::IGnssBatching extension and verifies that it doesn't return an error. Support
434 * for this interface is optional.
435 */
TEST_P(GnssHalTest,TestGnssBatchingExtension)436 TEST_P(GnssHalTest, TestGnssBatchingExtension) {
437 auto gnssBatching_2_0 = gnss_hal_->getExtensionGnssBatching_2_0();
438 ASSERT_TRUE(gnssBatching_2_0.isOk());
439 }
440
441 /*
442 * GetLocationLowPower:
443 * Turns on location, waits for at least 5 locations allowing max of LOCATION_TIMEOUT_SUBSEQUENT_SEC
444 * between one location and the next. Also ensure that MIN_INTERVAL_MSEC is respected by waiting
445 * NO_LOCATION_PERIOD_SEC and verfiy that no location is received. Also perform validity checks on
446 * each received location.
447 */
TEST_P(GnssHalTest,GetLocationLowPower)448 TEST_P(GnssHalTest, GetLocationLowPower) {
449 if (!(gnss_cb_->last_capabilities_ & IGnssCallback::Capabilities::LOW_POWER_MODE)) {
450 ALOGI("Test GetLocationLowPower skipped. LOW_POWER_MODE capability not supported.");
451 return;
452 }
453
454 const int kMinIntervalMsec = 5000;
455 const int kLocationTimeoutSubsequentSec = (kMinIntervalMsec / 1000) * 2;
456 const int kNoLocationPeriodSec = (kMinIntervalMsec / 1000) / 2;
457 const int kLocationsToCheck = 5;
458 const bool kLowPowerMode = true;
459
460 // Warmup period - VTS doesn't have AGPS access via GnssLocationProvider
461 gnss_cb_->location_cbq_.reset();
462 StartAndCheckLocations(kLocationsToCheck);
463 StopAndClearLocations();
464 gnss_cb_->location_cbq_.reset();
465
466 // Start of Low Power Mode test
467 // Don't expect true - as without AGPS access
468 if (!StartAndCheckFirstLocation(/* strict= */ false,
469 /* min_interval_msec= */ kMinIntervalMsec,
470 /* low_power_mode= */ kLowPowerMode)) {
471 ALOGW("GetLocationLowPower test - no first low power location received.");
472 }
473
474 for (int i = 1; i < kLocationsToCheck; i++) {
475 // Verify that kMinIntervalMsec is respected by waiting kNoLocationPeriodSec and
476 // ensure that no location is received yet
477
478 gnss_cb_->location_cbq_.retrieve(gnss_cb_->last_location_, kNoLocationPeriodSec);
479 const int location_called_count = gnss_cb_->location_cbq_.calledCount();
480
481 // Tolerate (ignore) one extra location right after the first one
482 // to handle startup edge case scheduling limitations in some implementations
483 if ((i == 1) && (location_called_count == 2)) {
484 CheckLocation(gnss_cb_->last_location_, true);
485 continue; // restart the quiet wait period after this too-fast location
486 }
487 EXPECT_LE(location_called_count, i);
488 if (location_called_count != i) {
489 ALOGW("GetLocationLowPower test - too many locations received. %d vs. %d expected ",
490 location_called_count, i);
491 }
492
493 if (!gnss_cb_->location_cbq_.retrieve(
494 gnss_cb_->last_location_,
495 kLocationTimeoutSubsequentSec - kNoLocationPeriodSec)) {
496 ALOGW("GetLocationLowPower test - timeout awaiting location %d", i);
497 } else {
498 CheckLocation(gnss_cb_->last_location_, true);
499 }
500 }
501
502 StopAndClearLocations();
503 }
504
505 /*
506 * FindStrongFrequentNonGpsSource:
507 *
508 * Search through a GnssSvStatus list for the strongest non-GPS satellite observed enough times
509 *
510 * returns the strongest source,
511 * or a source with constellation == UNKNOWN if none are found sufficient times
512 */
FindStrongFrequentNonGpsSource(const std::list<hidl_vec<IGnssCallback_2_0::GnssSvInfo>> & sv_info_lists,const int min_observations)513 IGnssConfiguration_1_1::BlacklistedSource FindStrongFrequentNonGpsSource(
514 const std::list<hidl_vec<IGnssCallback_2_0::GnssSvInfo>>& sv_info_lists,
515 const int min_observations) {
516 struct ComparableBlacklistedSource {
517 IGnssConfiguration_1_1::BlacklistedSource id;
518
519 ComparableBlacklistedSource() {
520 id.constellation = GnssConstellationType_1_0::UNKNOWN;
521 id.svid = 0;
522 }
523
524 bool operator<(const ComparableBlacklistedSource& compare) const {
525 return ((id.svid < compare.id.svid) || ((id.svid == compare.id.svid) &&
526 (id.constellation < compare.id.constellation)));
527 }
528 };
529
530 struct SignalCounts {
531 int observations;
532 float max_cn0_dbhz;
533 };
534
535 std::map<ComparableBlacklistedSource, SignalCounts> mapSignals;
536
537 for (const auto& sv_info_list : sv_info_lists) {
538 for (IGnssCallback_2_0::GnssSvInfo sv_info : sv_info_list) {
539 if ((sv_info.v1_0.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX) &&
540 (sv_info.constellation != GnssConstellationType_2_0::IRNSS) &&
541 (sv_info.constellation != GnssConstellationType_2_0::GPS)) {
542 ComparableBlacklistedSource source;
543 source.id.svid = sv_info.v1_0.svid;
544 source.id.constellation = Utils::mapConstellationType(sv_info.constellation);
545
546 const auto& itSignal = mapSignals.find(source);
547 if (itSignal == mapSignals.end()) {
548 SignalCounts counts;
549 counts.observations = 1;
550 counts.max_cn0_dbhz = sv_info.v1_0.cN0Dbhz;
551 mapSignals.insert(
552 std::pair<ComparableBlacklistedSource, SignalCounts>(source, counts));
553 } else {
554 itSignal->second.observations++;
555 if (itSignal->second.max_cn0_dbhz < sv_info.v1_0.cN0Dbhz) {
556 itSignal->second.max_cn0_dbhz = sv_info.v1_0.cN0Dbhz;
557 }
558 }
559 }
560 }
561 }
562
563 float max_cn0_dbhz_with_sufficient_count = 0.;
564 int total_observation_count = 0;
565 int blacklisted_source_count_observation = 0;
566
567 ComparableBlacklistedSource source_to_blacklist; // initializes to zero = UNKNOWN constellation
568 for (auto const& pairSignal : mapSignals) {
569 total_observation_count += pairSignal.second.observations;
570 if ((pairSignal.second.observations >= min_observations) &&
571 (pairSignal.second.max_cn0_dbhz > max_cn0_dbhz_with_sufficient_count)) {
572 source_to_blacklist = pairSignal.first;
573 blacklisted_source_count_observation = pairSignal.second.observations;
574 max_cn0_dbhz_with_sufficient_count = pairSignal.second.max_cn0_dbhz;
575 }
576 }
577 ALOGD("Among %d observations, chose svid %d, constellation %d, "
578 "with %d observations at %.1f max CNo",
579 total_observation_count, source_to_blacklist.id.svid,
580 (int)source_to_blacklist.id.constellation, blacklisted_source_count_observation,
581 max_cn0_dbhz_with_sufficient_count);
582
583 return source_to_blacklist.id;
584 }
585
586 /*
587 * BlacklistIndividualSatellites:
588 *
589 * 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding
590 * GnssStatus for common satellites (strongest and one other.)
591 * 2a & b) Turns off location, and blacklists common satellites.
592 * 3) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding
593 * GnssStatus does not use those satellites.
594 * 4a & b) Turns off location, and send in empty blacklist.
595 * 5a) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding
596 * GnssStatus does re-use at least the previously strongest satellite
597 * 5b) Retry a few times, in case GNSS search strategy takes a while to reacquire even the
598 * formerly strongest satellite
599 */
TEST_P(GnssHalTest,BlacklistIndividualSatellites)600 TEST_P(GnssHalTest, BlacklistIndividualSatellites) {
601 if (!IsGnssHalVersion_2_0()) {
602 ALOGI("Test BlacklistIndividualSatellites skipped. GNSS HAL version is greater than 2.0.");
603 return;
604 }
605
606 if (!(gnss_cb_->last_capabilities_ & IGnssCallback::Capabilities::SATELLITE_BLACKLIST)) {
607 ALOGI("Test BlacklistIndividualSatellites skipped. SATELLITE_BLACKLIST capability"
608 " not supported.");
609 return;
610 }
611
612 const int kLocationsToAwait = 3;
613 const int kRetriesToUnBlacklist = 10;
614
615 gnss_cb_->location_cbq_.reset();
616 StartAndCheckLocations(kLocationsToAwait);
617 int location_called_count = gnss_cb_->location_cbq_.calledCount();
618
619 // Tolerate 1 less sv status to handle edge cases in reporting.
620 int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
621 EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
622 ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations (%d received)",
623 sv_info_list_cbq_size, kLocationsToAwait, location_called_count);
624
625 /*
626 * Identify strongest SV seen at least kLocationsToAwait -1 times
627 * Why -1? To avoid test flakiness in case of (plausible) slight flakiness in strongest signal
628 * observability (one epoch RF null)
629 */
630
631 const int kGnssSvStatusTimeout = 2;
632 std::list<hidl_vec<IGnssCallback_2_0::GnssSvInfo>> sv_info_lists;
633 int count = gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_lists, sv_info_list_cbq_size,
634 kGnssSvStatusTimeout);
635 ASSERT_EQ(count, sv_info_list_cbq_size);
636
637 IGnssConfiguration_1_1::BlacklistedSource source_to_blacklist =
638 FindStrongFrequentNonGpsSource(sv_info_lists, kLocationsToAwait - 1);
639
640 if (source_to_blacklist.constellation == GnssConstellationType_1_0::UNKNOWN) {
641 // Cannot find a non-GPS satellite. Let the test pass.
642 return;
643 }
644
645 // Stop locations, blacklist the common SV
646 StopAndClearLocations();
647
648 auto gnss_configuration_hal_return = gnss_hal_->getExtensionGnssConfiguration_1_1();
649 ASSERT_TRUE(gnss_configuration_hal_return.isOk());
650 sp<IGnssConfiguration_1_1> gnss_configuration_hal = gnss_configuration_hal_return;
651 ASSERT_NE(gnss_configuration_hal, nullptr);
652
653 hidl_vec<IGnssConfiguration_1_1::BlacklistedSource> sources;
654 sources.resize(1);
655 sources[0] = source_to_blacklist;
656
657 auto result = gnss_configuration_hal->setBlacklist(sources);
658 ASSERT_TRUE(result.isOk());
659 EXPECT_TRUE(result);
660
661 // retry and ensure satellite not used
662 gnss_cb_->sv_info_list_cbq_.reset();
663
664 gnss_cb_->location_cbq_.reset();
665 StartAndCheckLocations(kLocationsToAwait);
666
667 // early exit if test is being run with insufficient signal
668 location_called_count = gnss_cb_->location_cbq_.calledCount();
669 if (location_called_count == 0) {
670 ALOGE("0 Gnss locations received - ensure sufficient signal and retry");
671 }
672 ASSERT_TRUE(location_called_count > 0);
673
674 // Tolerate 1 less sv status to handle edge cases in reporting.
675 sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
676 EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
677 ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations (%d received)",
678 sv_info_list_cbq_size, kLocationsToAwait, location_called_count);
679 for (int i = 0; i < sv_info_list_cbq_size; ++i) {
680 hidl_vec<IGnssCallback_2_0::GnssSvInfo> sv_info_list;
681 gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_list, kGnssSvStatusTimeout);
682 for (IGnssCallback_2_0::GnssSvInfo sv_info : sv_info_list) {
683 auto constellation = Utils::mapConstellationType(sv_info.constellation);
684 EXPECT_FALSE((sv_info.v1_0.svid == source_to_blacklist.svid) &&
685 (constellation == source_to_blacklist.constellation) &&
686 (sv_info.v1_0.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX));
687 }
688 }
689
690 // clear blacklist and restart - this time updating the blacklist while location is still on
691 sources.resize(0);
692
693 result = gnss_configuration_hal->setBlacklist(sources);
694 ASSERT_TRUE(result.isOk());
695 EXPECT_TRUE(result);
696
697 bool strongest_sv_is_reobserved = false;
698 // do several loops awaiting a few locations, allowing non-immediate reacquisition strategies
699 int unblacklist_loops_remaining = kRetriesToUnBlacklist;
700 while (!strongest_sv_is_reobserved && (unblacklist_loops_remaining-- > 0)) {
701 StopAndClearLocations();
702 gnss_cb_->sv_info_list_cbq_.reset();
703
704 gnss_cb_->location_cbq_.reset();
705 StartAndCheckLocations(kLocationsToAwait);
706
707 // early exit loop if test is being run with insufficient signal
708 location_called_count = gnss_cb_->location_cbq_.calledCount();
709 if (location_called_count == 0) {
710 ALOGE("0 Gnss locations received - ensure sufficient signal and retry");
711 }
712 ASSERT_TRUE(location_called_count > 0);
713
714 // Tolerate 1 less sv status to handle edge cases in reporting.
715 sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
716 EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
717 ALOGD("Clear blacklist, observed %d GnssSvStatus, while awaiting %d Locations"
718 ", tries remaining %d",
719 sv_info_list_cbq_size, kLocationsToAwait, unblacklist_loops_remaining);
720
721 for (int i = 0; i < sv_info_list_cbq_size; ++i) {
722 hidl_vec<IGnssCallback_2_0::GnssSvInfo> sv_info_list;
723 gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_list, kGnssSvStatusTimeout);
724 for (IGnssCallback_2_0::GnssSvInfo sv_info : sv_info_list) {
725 auto constellation = Utils::mapConstellationType(sv_info.constellation);
726 if ((sv_info.v1_0.svid == source_to_blacklist.svid) &&
727 (constellation == source_to_blacklist.constellation) &&
728 (sv_info.v1_0.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX)) {
729 strongest_sv_is_reobserved = true;
730 break;
731 }
732 }
733 if (strongest_sv_is_reobserved) break;
734 }
735 }
736 EXPECT_TRUE(strongest_sv_is_reobserved);
737 StopAndClearLocations();
738 }
739
740 /*
741 * BlacklistConstellationWithLocationOff:
742 *
743 * 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding
744 * GnssStatus for any non-GPS constellations.
745 * 2a & b) Turns off location, and blacklist first non-GPS constellations.
746 * 3) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding
747 * GnssStatus does not use any constellation but GPS.
748 * 4a & b) Clean up by turning off location, and send in empty blacklist.
749 */
TEST_P(GnssHalTest,BlacklistConstellationWithLocationOff)750 TEST_P(GnssHalTest, BlacklistConstellationWithLocationOff) {
751 if (!IsGnssHalVersion_2_0()) {
752 ALOGI("Test BlacklistConstellation skipped. GNSS HAL version is greater than 2.0.");
753 return;
754 }
755 if (!(gnss_cb_->last_capabilities_ & IGnssCallback::Capabilities::SATELLITE_BLACKLIST)) {
756 ALOGI("Test BlacklistConstellation skipped. SATELLITE_BLACKLIST capability not supported.");
757 return;
758 }
759
760 const int kLocationsToAwait = 3;
761
762 // Find first non-GPS constellation to blacklist
763 GnssConstellationType_1_0 constellation_to_blacklist = startLocationAndGetNonGpsConstellation();
764
765 // Turns off location
766 StopAndClearLocations();
767
768 IGnssConfiguration_1_1::BlacklistedSource source_to_blacklist;
769 source_to_blacklist.constellation = constellation_to_blacklist;
770 source_to_blacklist.svid = 0; // documented wildcard for all satellites in this constellation
771
772 auto gnss_configuration_hal_return = gnss_hal_->getExtensionGnssConfiguration_1_1();
773 ASSERT_TRUE(gnss_configuration_hal_return.isOk());
774 sp<IGnssConfiguration_1_1> gnss_configuration_hal = gnss_configuration_hal_return;
775 ASSERT_NE(gnss_configuration_hal, nullptr);
776
777 hidl_vec<IGnssConfiguration_1_1::BlacklistedSource> sources;
778 sources.resize(1);
779 sources[0] = source_to_blacklist;
780
781 // setBlacklist when location is off.
782 auto result = gnss_configuration_hal->setBlacklist(sources);
783 ASSERT_TRUE(result.isOk());
784 EXPECT_TRUE(result);
785
786 // retry and ensure constellation not used
787 gnss_cb_->sv_info_list_cbq_.reset();
788
789 gnss_cb_->location_cbq_.reset();
790 StartAndCheckLocations(kLocationsToAwait);
791
792 // Tolerate 1 less sv status to handle edge cases in reporting.
793 int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
794 EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
795 ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations", sv_info_list_cbq_size,
796 kLocationsToAwait);
797 const int kGnssSvStatusTimeout = 2;
798 for (int i = 0; i < sv_info_list_cbq_size; ++i) {
799 hidl_vec<IGnssCallback_2_0::GnssSvInfo> sv_info_list;
800 gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_list, kGnssSvStatusTimeout);
801 for (IGnssCallback_2_0::GnssSvInfo sv_info : sv_info_list) {
802 auto constellation = Utils::mapConstellationType(sv_info.constellation);
803 EXPECT_FALSE((constellation == source_to_blacklist.constellation) &&
804 (sv_info.v1_0.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX));
805 }
806 }
807
808 // clean up
809 StopAndClearLocations();
810 sources.resize(0);
811 result = gnss_configuration_hal->setBlacklist(sources);
812 ASSERT_TRUE(result.isOk());
813 EXPECT_TRUE(result);
814 }
815
816 /*
817 * BlacklistConstellationWithLocationOn:
818 *
819 * 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding
820 * GnssStatus for any non-GPS constellations.
821 * 2a & b) Blacklist first non-GPS constellations, and turns off location.
822 * 3) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding
823 * GnssStatus does not use any constellation but GPS.
824 * 4a & b) Clean up by turning off location, and send in empty blacklist.
825 */
TEST_P(GnssHalTest,BlacklistConstellationWithLocationOn)826 TEST_P(GnssHalTest, BlacklistConstellationWithLocationOn) {
827 if (!IsGnssHalVersion_2_0()) {
828 ALOGI("Test BlacklistConstellation skipped. GNSS HAL version is greater than 2.0.");
829 return;
830 }
831
832 if (!(gnss_cb_->last_capabilities_ & IGnssCallback::Capabilities::SATELLITE_BLACKLIST)) {
833 ALOGI("Test BlacklistConstellation skipped. SATELLITE_BLACKLIST capability not supported.");
834 return;
835 }
836
837 const int kLocationsToAwait = 3;
838
839 // Find first non-GPS constellation to blacklist
840 GnssConstellationType_1_0 constellation_to_blacklist = startLocationAndGetNonGpsConstellation();
841
842 IGnssConfiguration_1_1::BlacklistedSource source_to_blacklist;
843 source_to_blacklist.constellation = constellation_to_blacklist;
844 source_to_blacklist.svid = 0; // documented wildcard for all satellites in this constellation
845
846 auto gnss_configuration_hal_return = gnss_hal_->getExtensionGnssConfiguration_1_1();
847 ASSERT_TRUE(gnss_configuration_hal_return.isOk());
848 sp<IGnssConfiguration_1_1> gnss_configuration_hal = gnss_configuration_hal_return;
849 ASSERT_NE(gnss_configuration_hal, nullptr);
850
851 hidl_vec<IGnssConfiguration_1_1::BlacklistedSource> sources;
852 sources.resize(1);
853 sources[0] = source_to_blacklist;
854
855 // setBlacklist when location is on.
856 auto result = gnss_configuration_hal->setBlacklist(sources);
857 ASSERT_TRUE(result.isOk());
858 EXPECT_TRUE(result);
859
860 // Turns off location
861 StopAndClearLocations();
862
863 // retry and ensure constellation not used
864 gnss_cb_->sv_info_list_cbq_.reset();
865
866 gnss_cb_->location_cbq_.reset();
867 StartAndCheckLocations(kLocationsToAwait);
868
869 // Tolerate 1 less sv status to handle edge cases in reporting.
870 int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
871 EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
872 ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations", sv_info_list_cbq_size,
873 kLocationsToAwait);
874 const int kGnssSvStatusTimeout = 2;
875 for (int i = 0; i < sv_info_list_cbq_size; ++i) {
876 hidl_vec<IGnssCallback_2_0::GnssSvInfo> sv_info_list;
877 gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_list, kGnssSvStatusTimeout);
878 for (IGnssCallback_2_0::GnssSvInfo sv_info : sv_info_list) {
879 auto constellation = Utils::mapConstellationType(sv_info.constellation);
880 EXPECT_FALSE((constellation == source_to_blacklist.constellation) &&
881 (sv_info.v1_0.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX));
882 }
883 }
884
885 // clean up
886 StopAndClearLocations();
887 sources.resize(0);
888 result = gnss_configuration_hal->setBlacklist(sources);
889 ASSERT_TRUE(result.isOk());
890 EXPECT_TRUE(result);
891 }
892