• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 
21 #include <VtsHalHidlTargetTestBase.h>
22 
23 #include <android/hardware/gnss/1.1/IGnssConfiguration.h>
24 
25 using android::hardware::hidl_vec;
26 
27 using android::hardware::gnss::V1_0::GnssConstellationType;
28 using android::hardware::gnss::V1_0::GnssLocation;
29 using android::hardware::gnss::V1_0::IGnssDebug;
30 using android::hardware::gnss::V1_1::IGnssConfiguration;
31 using android::hardware::gnss::V1_1::IGnssMeasurement;
32 
33 /*
34  * SetupTeardownCreateCleanup:
35  * Requests the gnss HAL then calls cleanup
36  *
37  * Empty test fixture to verify basic Setup & Teardown
38  */
TEST_F(GnssHalTest,SetupTeardownCreateCleanup)39 TEST_F(GnssHalTest, SetupTeardownCreateCleanup) {}
40 
41 /*
42  * TestGnssMeasurementCallback:
43  * Gets the GnssMeasurementExtension and verify that it returns an actual extension.
44  */
TEST_F(GnssHalTest,TestGnssMeasurementCallback)45 TEST_F(GnssHalTest, TestGnssMeasurementCallback) {
46     auto gnssMeasurement = gnss_hal_->getExtensionGnssMeasurement_1_1();
47     ASSERT_TRUE(gnssMeasurement.isOk());
48     if (last_capabilities_ & IGnssCallback::Capabilities::MEASUREMENTS) {
49         sp<IGnssMeasurement> iGnssMeas = gnssMeasurement;
50         EXPECT_NE(iGnssMeas, nullptr);
51     }
52 }
53 
54 /*
55  * GetLocationLowPower:
56  * Turns on location, waits for at least 5 locations allowing max of LOCATION_TIMEOUT_SUBSEQUENT_SEC
57  * between one location and the next. Also ensure that MIN_INTERVAL_MSEC is respected by waiting
58  * NO_LOCATION_PERIOD_SEC and verfiy that no location is received. Also perform validity checks on
59  * each received location.
60  */
TEST_F(GnssHalTest,GetLocationLowPower)61 TEST_F(GnssHalTest, GetLocationLowPower) {
62     const int kMinIntervalMsec = 5000;
63     const int kLocationTimeoutSubsequentSec = (kMinIntervalMsec / 1000) * 2;
64     const int kNoLocationPeriodSec = (kMinIntervalMsec / 1000) / 2;
65     const int kLocationsToCheck = 5;
66     const bool kLowPowerMode = true;
67 
68     // Warmup period - VTS doesn't have AGPS access via GnssLocationProvider
69     StartAndCheckLocations(5);
70     StopAndClearLocations();
71 
72     // Start of Low Power Mode test
73     SetPositionMode(kMinIntervalMsec, kLowPowerMode);
74 
75     // Don't expect true - as without AGPS access
76     if (!StartAndCheckFirstLocation()) {
77         ALOGW("GetLocationLowPower test - no first low power location received.");
78     }
79 
80     for (int i = 1; i < kLocationsToCheck; i++) {
81         // Verify that kMinIntervalMsec is respected by waiting kNoLocationPeriodSec and
82         // ensure that no location is received yet
83 
84         wait(kNoLocationPeriodSec);
85         // Tolerate (ignore) one extra location right after the first one
86         // to handle startup edge case scheduling limitations in some implementations
87         if ((i == 1) && (location_called_count_ == 2)) {
88             CheckLocation(last_location_, true);
89             continue;  // restart the quiet wait period after this too-fast location
90         }
91         EXPECT_LE(location_called_count_, i);
92         if (location_called_count_ != i) {
93             ALOGW("GetLocationLowPower test - not enough locations received. %d vs. %d expected ",
94                   location_called_count_, i);
95         }
96 
97         if (std::cv_status::no_timeout !=
98             wait(kLocationTimeoutSubsequentSec - kNoLocationPeriodSec)) {
99             ALOGW("GetLocationLowPower test - timeout awaiting location %d", i);
100         } else {
101             CheckLocation(last_location_, true);
102         }
103     }
104 
105     StopAndClearLocations();
106 }
107 
108 /*
109  * FindStrongFrequentNonGpsSource:
110  *
111  * Search through a GnssSvStatus list for the strongest non-GPS satellite observed enough times
112  *
113  * returns the strongest source,
114  *         or a source with constellation == UNKNOWN if none are found sufficient times
115  */
116 
FindStrongFrequentNonGpsSource(const list<IGnssCallback::GnssSvStatus> list_gnss_sv_status,const int min_observations)117 IGnssConfiguration::BlacklistedSource FindStrongFrequentNonGpsSource(
118     const list<IGnssCallback::GnssSvStatus> list_gnss_sv_status, const int min_observations) {
119     struct ComparableBlacklistedSource {
120         IGnssConfiguration::BlacklistedSource id;
121 
122         ComparableBlacklistedSource() {
123             id.constellation = GnssConstellationType::UNKNOWN;
124             id.svid = 0;
125         }
126 
127         bool operator<(const ComparableBlacklistedSource& compare) const {
128             return ((id.svid < compare.id.svid) || ((id.svid == compare.id.svid) &&
129                                                     (id.constellation < compare.id.constellation)));
130         }
131     };
132 
133     struct SignalCounts {
134         int observations;
135         float max_cn0_dbhz;
136     };
137 
138     std::map<ComparableBlacklistedSource, SignalCounts> mapSignals;
139 
140     for (const auto& gnss_sv_status : list_gnss_sv_status) {
141         for (uint32_t iSv = 0; iSv < gnss_sv_status.numSvs; iSv++) {
142             const auto& gnss_sv = gnss_sv_status.gnssSvList[iSv];
143             if ((gnss_sv.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX) &&
144                 (gnss_sv.constellation != GnssConstellationType::GPS)) {
145                 ComparableBlacklistedSource source;
146                 source.id.svid = gnss_sv.svid;
147                 source.id.constellation = gnss_sv.constellation;
148 
149                 const auto& itSignal = mapSignals.find(source);
150                 if (itSignal == mapSignals.end()) {
151                     SignalCounts counts;
152                     counts.observations = 1;
153                     counts.max_cn0_dbhz = gnss_sv.cN0Dbhz;
154                     mapSignals.insert(
155                         std::pair<ComparableBlacklistedSource, SignalCounts>(source, counts));
156                 } else {
157                     itSignal->second.observations++;
158                     if (itSignal->second.max_cn0_dbhz < gnss_sv.cN0Dbhz) {
159                         itSignal->second.max_cn0_dbhz = gnss_sv.cN0Dbhz;
160                     }
161                 }
162             }
163         }
164     }
165 
166     float max_cn0_dbhz_with_sufficient_count = 0.;
167     int total_observation_count = 0;
168     int blacklisted_source_count_observation = 0;
169 
170     ComparableBlacklistedSource source_to_blacklist;  // initializes to zero = UNKNOWN constellation
171     for (auto const& pairSignal : mapSignals) {
172         total_observation_count += pairSignal.second.observations;
173         if ((pairSignal.second.observations >= min_observations) &&
174             (pairSignal.second.max_cn0_dbhz > max_cn0_dbhz_with_sufficient_count)) {
175             source_to_blacklist = pairSignal.first;
176             blacklisted_source_count_observation = pairSignal.second.observations;
177             max_cn0_dbhz_with_sufficient_count = pairSignal.second.max_cn0_dbhz;
178         }
179     }
180     ALOGD(
181         "Among %d observations, chose svid %d, constellation %d, "
182         "with %d observations at %.1f max CNo",
183         total_observation_count, source_to_blacklist.id.svid,
184         (int)source_to_blacklist.id.constellation, blacklisted_source_count_observation,
185         max_cn0_dbhz_with_sufficient_count);
186 
187     return source_to_blacklist.id;
188 }
189 
190 /*
191  * BlacklistIndividualSatellites:
192  *
193  * 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding
194  * GnssStatus for common satellites (strongest and one other.)
195  * 2a & b) Turns off location, and blacklists common satellites.
196  * 3) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding
197  * GnssStatus does not use those satellites.
198  * 4a & b) Turns off location, and send in empty blacklist.
199  * 5a) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding
200  * GnssStatus does re-use at least the previously strongest satellite
201  * 5b) Retry a few times, in case GNSS search strategy takes a while to reacquire even the
202  * formerly strongest satellite
203  */
TEST_F(GnssHalTest,BlacklistIndividualSatellites)204 TEST_F(GnssHalTest, BlacklistIndividualSatellites) {
205     const int kLocationsToAwait = 3;
206     const int kRetriesToUnBlacklist = 10;
207 
208     StartAndCheckLocations(kLocationsToAwait);
209 
210     // Tolerate 1 less sv status to handle edge cases in reporting.
211     EXPECT_GE((int)list_gnss_sv_status_.size() + 1, kLocationsToAwait);
212     ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations (%d received)",
213           (int)list_gnss_sv_status_.size(), kLocationsToAwait, location_called_count_);
214 
215     /*
216      * Identify strongest SV seen at least kLocationsToAwait -1 times
217      * Why -1?  To avoid test flakiness in case of (plausible) slight flakiness in strongest signal
218      * observability (one epoch RF null)
219      */
220 
221     IGnssConfiguration::BlacklistedSource source_to_blacklist =
222         FindStrongFrequentNonGpsSource(list_gnss_sv_status_, kLocationsToAwait - 1);
223 
224     if (source_to_blacklist.constellation == GnssConstellationType::UNKNOWN) {
225         // Cannot find a non-GPS satellite. Let the test pass.
226         return;
227     }
228 
229     // Stop locations, blacklist the common SV
230     StopAndClearLocations();
231 
232     auto gnss_configuration_hal_return = gnss_hal_->getExtensionGnssConfiguration_1_1();
233     ASSERT_TRUE(gnss_configuration_hal_return.isOk());
234     sp<IGnssConfiguration> gnss_configuration_hal = gnss_configuration_hal_return;
235     ASSERT_NE(gnss_configuration_hal, nullptr);
236 
237     hidl_vec<IGnssConfiguration::BlacklistedSource> sources;
238     sources.resize(1);
239     sources[0] = source_to_blacklist;
240 
241     auto result = gnss_configuration_hal->setBlacklist(sources);
242     ASSERT_TRUE(result.isOk());
243     EXPECT_TRUE(result);
244 
245     // retry and ensure satellite not used
246     list_gnss_sv_status_.clear();
247 
248     StartAndCheckLocations(kLocationsToAwait);
249 
250     // early exit if test is being run with insufficient signal
251     if (location_called_count_ == 0) {
252         ALOGE("0 Gnss locations received - ensure sufficient signal and retry");
253     }
254     ASSERT_TRUE(location_called_count_ > 0);
255 
256     // Tolerate 1 less sv status to handle edge cases in reporting.
257     EXPECT_GE((int)list_gnss_sv_status_.size() + 1, kLocationsToAwait);
258     ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations (%d received)",
259           (int)list_gnss_sv_status_.size(), kLocationsToAwait, location_called_count_);
260     for (const auto& gnss_sv_status : list_gnss_sv_status_) {
261         for (uint32_t iSv = 0; iSv < gnss_sv_status.numSvs; iSv++) {
262             const auto& gnss_sv = gnss_sv_status.gnssSvList[iSv];
263             EXPECT_FALSE((gnss_sv.svid == source_to_blacklist.svid) &&
264                          (gnss_sv.constellation == source_to_blacklist.constellation) &&
265                          (gnss_sv.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX));
266         }
267     }
268 
269     // clear blacklist and restart - this time updating the blacklist while location is still on
270     sources.resize(0);
271 
272     result = gnss_configuration_hal->setBlacklist(sources);
273     ASSERT_TRUE(result.isOk());
274     EXPECT_TRUE(result);
275 
276     bool strongest_sv_is_reobserved = false;
277     // do several loops awaiting a few locations, allowing non-immediate reacquisition strategies
278     int unblacklist_loops_remaining = kRetriesToUnBlacklist;
279     while (!strongest_sv_is_reobserved && (unblacklist_loops_remaining-- > 0)) {
280         StopAndClearLocations();
281         list_gnss_sv_status_.clear();
282 
283         StartAndCheckLocations(kLocationsToAwait);
284 
285         // early exit loop if test is being run with insufficient signal
286         if (location_called_count_ == 0) {
287             ALOGE("0 Gnss locations received - ensure sufficient signal and retry");
288         }
289         ASSERT_TRUE(location_called_count_ > 0);
290 
291         // Tolerate 1 less sv status to handle edge cases in reporting.
292         EXPECT_GE((int)list_gnss_sv_status_.size() + 1, kLocationsToAwait);
293         ALOGD(
294             "Clear blacklist, observed %d GnssSvStatus, while awaiting %d Locations"
295             ", tries remaining %d",
296             (int)list_gnss_sv_status_.size(), kLocationsToAwait, unblacklist_loops_remaining);
297 
298         for (const auto& gnss_sv_status : list_gnss_sv_status_) {
299             for (uint32_t iSv = 0; iSv < gnss_sv_status.numSvs; iSv++) {
300                 const auto& gnss_sv = gnss_sv_status.gnssSvList[iSv];
301                 if ((gnss_sv.svid == source_to_blacklist.svid) &&
302                     (gnss_sv.constellation == source_to_blacklist.constellation) &&
303                     (gnss_sv.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX)) {
304                     strongest_sv_is_reobserved = true;
305                     break;
306                 }
307             }
308             if (strongest_sv_is_reobserved) break;
309         }
310     }
311     EXPECT_TRUE(strongest_sv_is_reobserved);
312     StopAndClearLocations();
313 }
314 
315 /*
316  * BlacklistConstellation:
317  *
318  * 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding
319  * GnssStatus for any non-GPS constellations.
320  * 2a & b) Turns off location, and blacklist first non-GPS constellations.
321  * 3) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding
322  * GnssStatus does not use any constellation but GPS.
323  * 4a & b) Clean up by turning off location, and send in empty blacklist.
324  */
TEST_F(GnssHalTest,BlacklistConstellation)325 TEST_F(GnssHalTest, BlacklistConstellation) {
326     const int kLocationsToAwait = 3;
327 
328     StartAndCheckLocations(kLocationsToAwait);
329 
330     // Tolerate 1 less sv status to handle edge cases in reporting.
331     EXPECT_GE((int)list_gnss_sv_status_.size() + 1, kLocationsToAwait);
332     ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations (%d received)",
333           (int)list_gnss_sv_status_.size(), kLocationsToAwait, location_called_count_);
334 
335     // Find first non-GPS constellation to blacklist
336     GnssConstellationType constellation_to_blacklist = GnssConstellationType::UNKNOWN;
337     for (const auto& gnss_sv_status : list_gnss_sv_status_) {
338         for (uint32_t iSv = 0; iSv < gnss_sv_status.numSvs; iSv++) {
339             const auto& gnss_sv = gnss_sv_status.gnssSvList[iSv];
340             if ((gnss_sv.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX) &&
341                 (gnss_sv.constellation != GnssConstellationType::UNKNOWN) &&
342                 (gnss_sv.constellation != GnssConstellationType::GPS)) {
343                 // found a non-GPS constellation
344                 constellation_to_blacklist = gnss_sv.constellation;
345                 break;
346             }
347         }
348         if (constellation_to_blacklist != GnssConstellationType::UNKNOWN) {
349             break;
350         }
351     }
352 
353     if (constellation_to_blacklist == GnssConstellationType::UNKNOWN) {
354         ALOGI("No non-GPS constellations found, constellation blacklist test less effective.");
355         // Proceed functionally to blacklist something.
356         constellation_to_blacklist = GnssConstellationType::GLONASS;
357     }
358     IGnssConfiguration::BlacklistedSource source_to_blacklist;
359     source_to_blacklist.constellation = constellation_to_blacklist;
360     source_to_blacklist.svid = 0;  // documented wildcard for all satellites in this constellation
361 
362     auto gnss_configuration_hal_return = gnss_hal_->getExtensionGnssConfiguration_1_1();
363     ASSERT_TRUE(gnss_configuration_hal_return.isOk());
364     sp<IGnssConfiguration> gnss_configuration_hal = gnss_configuration_hal_return;
365     ASSERT_NE(gnss_configuration_hal, nullptr);
366 
367     hidl_vec<IGnssConfiguration::BlacklistedSource> sources;
368     sources.resize(1);
369     sources[0] = source_to_blacklist;
370 
371     auto result = gnss_configuration_hal->setBlacklist(sources);
372     ASSERT_TRUE(result.isOk());
373     EXPECT_TRUE(result);
374 
375     // retry and ensure constellation not used
376     list_gnss_sv_status_.clear();
377 
378     location_called_count_ = 0;
379     StartAndCheckLocations(kLocationsToAwait);
380 
381     // Tolerate 1 less sv status to handle edge cases in reporting.
382     EXPECT_GE((int)list_gnss_sv_status_.size() + 1, kLocationsToAwait);
383     ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations", (int)list_gnss_sv_status_.size(),
384           kLocationsToAwait);
385     for (const auto& gnss_sv_status : list_gnss_sv_status_) {
386         for (uint32_t iSv = 0; iSv < gnss_sv_status.numSvs; iSv++) {
387             const auto& gnss_sv = gnss_sv_status.gnssSvList[iSv];
388             EXPECT_FALSE((gnss_sv.constellation == source_to_blacklist.constellation) &&
389                          (gnss_sv.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX));
390         }
391     }
392 
393     // clean up
394     StopAndClearLocations();
395     sources.resize(0);
396     result = gnss_configuration_hal->setBlacklist(sources);
397     ASSERT_TRUE(result.isOk());
398     EXPECT_TRUE(result);
399 }
400 
401 /*
402  * InjectBestLocation
403  *
404  * Ensure successfully injecting a location.
405  */
TEST_F(GnssHalTest,InjectBestLocation)406 TEST_F(GnssHalTest, InjectBestLocation) {
407     StartAndCheckLocations(1);
408     GnssLocation gnssLocation = last_location_;
409     CheckLocation(gnssLocation, true);
410 
411     auto result = gnss_hal_->injectBestLocation(gnssLocation);
412 
413     ASSERT_TRUE(result.isOk());
414     EXPECT_TRUE(result);
415 
416     auto resultVoid = gnss_hal_->deleteAidingData(IGnss::GnssAidingData::DELETE_POSITION);
417 
418     ASSERT_TRUE(resultVoid.isOk());
419 }
420 
421 /*
422  * GnssDebugValuesSanityTest:
423  * Ensures that GnssDebug values make sense.
424  */
TEST_F(GnssHalTest,GnssDebugValuesSanityTest)425 TEST_F(GnssHalTest, GnssDebugValuesSanityTest) {
426     auto gnssDebug = gnss_hal_->getExtensionGnssDebug();
427     ASSERT_TRUE(gnssDebug.isOk());
428     if (info_called_count_ > 0 && last_info_.yearOfHw >= 2017) {
429         sp<IGnssDebug> iGnssDebug = gnssDebug;
430         EXPECT_NE(iGnssDebug, nullptr);
431 
432         IGnssDebug::DebugData data;
433         iGnssDebug->getDebugData(
434             [&data](const IGnssDebug::DebugData& debugData) { data = debugData; });
435 
436         if (data.position.valid) {
437             EXPECT_GE(data.position.latitudeDegrees, -90);
438             EXPECT_LE(data.position.latitudeDegrees, 90);
439 
440             EXPECT_GE(data.position.longitudeDegrees, -180);
441             EXPECT_LE(data.position.longitudeDegrees, 180);
442 
443             EXPECT_GE(data.position.altitudeMeters, -1000);  // Dead Sea: -414m
444             EXPECT_LE(data.position.altitudeMeters, 20000);  // Mount Everest: 8850m
445 
446             EXPECT_GE(data.position.speedMetersPerSec, 0);
447             EXPECT_LE(data.position.speedMetersPerSec, 600);
448 
449             EXPECT_GE(data.position.bearingDegrees, -360);
450             EXPECT_LE(data.position.bearingDegrees, 360);
451 
452             EXPECT_GT(data.position.horizontalAccuracyMeters, 0);
453             EXPECT_LE(data.position.horizontalAccuracyMeters, 20000000);
454 
455             EXPECT_GT(data.position.verticalAccuracyMeters, 0);
456             EXPECT_LE(data.position.verticalAccuracyMeters, 20000);
457 
458             EXPECT_GT(data.position.speedAccuracyMetersPerSecond, 0);
459             EXPECT_LE(data.position.speedAccuracyMetersPerSecond, 500);
460 
461             EXPECT_GT(data.position.bearingAccuracyDegrees, 0);
462             EXPECT_LE(data.position.bearingAccuracyDegrees, 180);
463 
464             EXPECT_GE(data.position.ageSeconds, 0);
465         }
466 
467         EXPECT_GE(data.time.timeEstimate, 1483228800000);  // Jan 01 2017 00:00:00 GMT.
468 
469         EXPECT_GT(data.time.timeUncertaintyNs, 0);
470 
471         EXPECT_GT(data.time.frequencyUncertaintyNsPerSec, 0);
472         EXPECT_LE(data.time.frequencyUncertaintyNsPerSec, 2.0e5);  // 200 ppm
473     }
474 }
475