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