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