• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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