1 /*
2 * Copyright (C) 2019 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 #pragma once
18
19 #include "GnssCallbackEventQueue.h"
20 #include "Utils.h"
21 #include "v2_1/GnssCallback.h"
22
23 #include <gtest/gtest.h>
24 #include <chrono>
25
26 #define TIMEOUT_SEC 2 // for basic commands/responses
27
28 namespace android::hardware::gnss::common {
29
30 // The main test class for GNSS HAL.
31 template <class T_IGnss>
32 class GnssHalTestTemplate : public testing::TestWithParam<std::string> {
33 public:
34 virtual void SetUp() override;
35
36 virtual void TearDown() override;
37
38 /* Callback class for GnssMeasurement. */
39 class GnssMeasurementCallback : public V2_1::IGnssMeasurementCallback {
40 public:
41 GnssCallbackEventQueue<V2_1::IGnssMeasurementCallback::GnssData> measurement_cbq_;
42
GnssMeasurementCallback()43 GnssMeasurementCallback() : measurement_cbq_("measurement"){};
44 virtual ~GnssMeasurementCallback() = default;
45
46 // Methods from V1_0::IGnssMeasurementCallback follow.
GnssMeasurementCb(const V1_0::IGnssMeasurementCallback::GnssData &)47 Return<void> GnssMeasurementCb(const V1_0::IGnssMeasurementCallback::GnssData&) override {
48 return Void();
49 }
50
51 // Methods from V1_1::IGnssMeasurementCallback follow.
gnssMeasurementCb(const V1_1::IGnssMeasurementCallback::GnssData &)52 Return<void> gnssMeasurementCb(const V1_1::IGnssMeasurementCallback::GnssData&) override {
53 return Void();
54 }
55
56 // Methods from V2_0::IGnssMeasurementCallback follow.
gnssMeasurementCb_2_0(const V2_0::IGnssMeasurementCallback::GnssData &)57 Return<void> gnssMeasurementCb_2_0(
58 const V2_0::IGnssMeasurementCallback::GnssData&) override {
59 return Void();
60 }
61
62 // Methods from V2_1::IGnssMeasurementCallback follow.
63 Return<void> gnssMeasurementCb_2_1(
64 const V2_1::IGnssMeasurementCallback::GnssData&) override;
65 };
66
67 /* Callback class for GnssMeasurementCorrections. */
68 class GnssMeasurementCorrectionsCallback
69 : public measurement_corrections::V1_0::IMeasurementCorrectionsCallback {
70 public:
71 uint32_t last_capabilities_;
72 GnssCallbackEventQueue<uint32_t> capabilities_cbq_;
73
GnssMeasurementCorrectionsCallback()74 GnssMeasurementCorrectionsCallback() : capabilities_cbq_("capabilities"){};
75 virtual ~GnssMeasurementCorrectionsCallback() = default;
76
77 // Methods from V1_0::IMeasurementCorrectionsCallback follow.
78 Return<void> setCapabilitiesCb(uint32_t capabilities) override;
79 };
80
81 /* Callback class for GnssAntennaInfo. */
82 class GnssAntennaInfoCallback : public V2_1::IGnssAntennaInfoCallback {
83 public:
84 GnssCallbackEventQueue<hidl_vec<V2_1::IGnssAntennaInfoCallback::GnssAntennaInfo>>
85 antenna_info_cbq_;
86
GnssAntennaInfoCallback()87 GnssAntennaInfoCallback() : antenna_info_cbq_("info"){};
88 virtual ~GnssAntennaInfoCallback() = default;
89
90 // Methods from V2_1::GnssAntennaInfoCallback follow.
91 Return<void> gnssAntennaInfoCb(
92 const hidl_vec<V2_1::IGnssAntennaInfoCallback::GnssAntennaInfo>& gnssAntennaInfos);
93 };
94
95 /*
96 * SetUpGnssCallback:
97 * Set GnssCallback and verify the result.
98 */
99 virtual void SetUpGnssCallback();
100
101 /*
102 * StartAndCheckFirstLocation:
103 * Helper function to start location, and check the first one.
104 *
105 * <p> Note this leaves the Location request active, to enable Stop call vs. other call
106 * reordering tests.
107 *
108 * returns true if a location was successfully generated
109 */
110 bool StartAndCheckFirstLocation(const int min_interval_msec, const bool low_power_mode);
111
112 /*
113 * CheckLocation:
114 * Helper function to vet Location fields
115 *
116 * check_speed: true if speed related fields are also verified.
117 */
118 void CheckLocation(const V2_0::GnssLocation& location, const bool check_speed);
119
120 /*
121 * StartAndCheckLocations:
122 * Helper function to collect, and check a number of
123 * normal ~1Hz locations.
124 *
125 * Note this leaves the Location request active, to enable Stop call vs. other call
126 * reordering tests.
127 */
128 void StartAndCheckLocations(int count);
129
130 /*
131 * StopAndClearLocations:
132 * Helper function to stop locations, and clear any remaining notifications
133 */
134 void StopAndClearLocations();
135
136 /*
137 * SetPositionMode:
138 * Helper function to set positioning mode and verify output
139 */
140 void SetPositionMode(const int min_interval_msec, const bool low_power_mode);
141
142 /*
143 * startLocationAndGetNonGpsConstellation:
144 * 1. Start location
145 * 2. Find and return first non-GPS constellation
146 *
147 * Note that location is not stopped in this method. The client should call
148 * StopAndClearLocations() after the call.
149 */
150 V2_0::GnssConstellationType startLocationAndGetNonGpsConstellation(
151 const int locations_to_await, const int gnss_sv_info_list_timeout);
152
153 sp<T_IGnss> gnss_hal_; // GNSS HAL to call into
154 sp<GnssCallback> gnss_cb_; // Primary callback interface
155 };
156
157 using ::android::hardware::gnss::common::Utils;
158
159 // Implementations for the main test class for GNSS HAL
160 template <class T_IGnss>
SetUp()161 void GnssHalTestTemplate<T_IGnss>::SetUp() {
162 gnss_hal_ = T_IGnss::getService(GetParam());
163 ASSERT_NE(gnss_hal_, nullptr);
164
165 SetUpGnssCallback();
166 }
167
168 template <class T_IGnss>
TearDown()169 void GnssHalTestTemplate<T_IGnss>::TearDown() {
170 if (gnss_hal_ != nullptr) {
171 gnss_hal_->cleanup();
172 gnss_hal_ = nullptr;
173 }
174
175 // Set to nullptr to destruct the callback event queues and warn of any unprocessed events.
176 gnss_cb_ = nullptr;
177 }
178
179 template <class T_IGnss>
SetUpGnssCallback()180 void GnssHalTestTemplate<T_IGnss>::SetUpGnssCallback() {
181 gnss_cb_ = new GnssCallback();
182 ASSERT_NE(gnss_cb_, nullptr);
183
184 auto result = gnss_hal_->setCallback_2_1(gnss_cb_);
185 if (!result.isOk()) {
186 ALOGE("result of failed setCallback %s", result.description().c_str());
187 }
188
189 ASSERT_TRUE(result.isOk());
190 ASSERT_TRUE(result);
191
192 /*
193 * All capabilities, name and systemInfo callbacks should trigger
194 */
195 EXPECT_TRUE(gnss_cb_->capabilities_cbq_.retrieve(gnss_cb_->last_capabilities_, TIMEOUT_SEC));
196 EXPECT_TRUE(gnss_cb_->info_cbq_.retrieve(gnss_cb_->last_info_, TIMEOUT_SEC));
197 EXPECT_TRUE(gnss_cb_->name_cbq_.retrieve(gnss_cb_->last_name_, TIMEOUT_SEC));
198
199 EXPECT_EQ(gnss_cb_->capabilities_cbq_.calledCount(), 1);
200 EXPECT_EQ(gnss_cb_->info_cbq_.calledCount(), 1);
201 EXPECT_EQ(gnss_cb_->name_cbq_.calledCount(), 1);
202 }
203
204 template <class T_IGnss>
StopAndClearLocations()205 void GnssHalTestTemplate<T_IGnss>::StopAndClearLocations() {
206 const auto result = gnss_hal_->stop();
207
208 EXPECT_TRUE(result.isOk());
209 EXPECT_TRUE(result);
210
211 /*
212 * Clear notify/waiting counter, allowing up till the timeout after
213 * the last reply for final startup messages to arrive (esp. system
214 * info.)
215 */
216 while (gnss_cb_->location_cbq_.retrieve(gnss_cb_->last_location_, TIMEOUT_SEC)) {
217 }
218 gnss_cb_->location_cbq_.reset();
219 }
220
221 template <class T_IGnss>
SetPositionMode(const int min_interval_msec,const bool low_power_mode)222 void GnssHalTestTemplate<T_IGnss>::SetPositionMode(const int min_interval_msec,
223 const bool low_power_mode) {
224 const int kPreferredAccuracy = 0; // Ideally perfect (matches GnssLocationProvider)
225 const int kPreferredTimeMsec = 0; // Ideally immediate
226
227 const auto result = gnss_hal_->setPositionMode_1_1(
228 T_IGnss::GnssPositionMode::MS_BASED,
229 T_IGnss::GnssPositionRecurrence::RECURRENCE_PERIODIC, min_interval_msec,
230 kPreferredAccuracy, kPreferredTimeMsec, low_power_mode);
231
232 ASSERT_TRUE(result.isOk());
233 EXPECT_TRUE(result);
234 }
235
236 template <class T_IGnss>
StartAndCheckFirstLocation(const int min_interval_msec,const bool low_power_mode)237 bool GnssHalTestTemplate<T_IGnss>::StartAndCheckFirstLocation(const int min_interval_msec,
238 const bool low_power_mode) {
239 SetPositionMode(min_interval_msec, low_power_mode);
240 const auto result = gnss_hal_->start();
241
242 EXPECT_TRUE(result.isOk());
243 EXPECT_TRUE(result);
244
245 /*
246 * GnssLocationProvider support of AGPS SUPL & XtraDownloader is not available in VTS,
247 * so allow time to demodulate ephemeris over the air.
248 */
249 const int kFirstGnssLocationTimeoutSeconds = 75;
250
251 EXPECT_TRUE(gnss_cb_->location_cbq_.retrieve(gnss_cb_->last_location_,
252 kFirstGnssLocationTimeoutSeconds));
253 int locationCalledCount = gnss_cb_->location_cbq_.calledCount();
254 EXPECT_EQ(locationCalledCount, 1);
255
256 if (locationCalledCount > 0) {
257 // don't require speed on first fix
258 CheckLocation(gnss_cb_->last_location_, false);
259 return true;
260 }
261 return false;
262 }
263
264 template <class T_IGnss>
CheckLocation(const V2_0::GnssLocation & location,bool check_speed)265 void GnssHalTestTemplate<T_IGnss>::CheckLocation(const V2_0::GnssLocation& location,
266 bool check_speed) {
267 const bool check_more_accuracies =
268 (gnss_cb_->info_cbq_.calledCount() > 0 && gnss_cb_->last_info_.yearOfHw >= 2017);
269
270 Utils::checkLocation(location.v1_0, check_speed, check_more_accuracies);
271 }
272
273 template <class T_IGnss>
StartAndCheckLocations(int count)274 void GnssHalTestTemplate<T_IGnss>::StartAndCheckLocations(int count) {
275 const int kMinIntervalMsec = 500;
276 const int kLocationTimeoutSubsequentSec = 2;
277 const bool kLowPowerMode = false;
278
279 EXPECT_TRUE(StartAndCheckFirstLocation(kMinIntervalMsec, kLowPowerMode));
280
281 for (int i = 1; i < count; i++) {
282 EXPECT_TRUE(gnss_cb_->location_cbq_.retrieve(gnss_cb_->last_location_,
283 kLocationTimeoutSubsequentSec));
284 int locationCalledCount = gnss_cb_->location_cbq_.calledCount();
285 EXPECT_EQ(locationCalledCount, i + 1);
286 // Don't cause confusion by checking details if no location yet
287 if (locationCalledCount > 0) {
288 // Should be more than 1 location by now, but if not, still don't check first fix speed
289 CheckLocation(gnss_cb_->last_location_, locationCalledCount > 1);
290 }
291 }
292 }
293
294 template <class T_IGnss>
startLocationAndGetNonGpsConstellation(const int locations_to_await,const int gnss_sv_info_list_timeout)295 V2_0::GnssConstellationType GnssHalTestTemplate<T_IGnss>::startLocationAndGetNonGpsConstellation(
296 const int locations_to_await, const int gnss_sv_info_list_timeout) {
297 gnss_cb_->location_cbq_.reset();
298 StartAndCheckLocations(locations_to_await);
299 const int location_called_count = gnss_cb_->location_cbq_.calledCount();
300
301 // Tolerate 1 less sv status to handle edge cases in reporting.
302 int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
303 EXPECT_GE(sv_info_list_cbq_size + 1, locations_to_await);
304 ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations (%d received)",
305 sv_info_list_cbq_size, locations_to_await, location_called_count);
306
307 // Find first non-GPS constellation to blacklist
308 V2_0::GnssConstellationType constellation_to_blacklist = V2_0::GnssConstellationType::UNKNOWN;
309 for (int i = 0; i < sv_info_list_cbq_size; ++i) {
310 hidl_vec<V2_1::IGnssCallback::GnssSvInfo> sv_info_vec;
311 gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, gnss_sv_info_list_timeout);
312 for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
313 const auto& gnss_sv = sv_info_vec[iSv];
314 if ((gnss_sv.v2_0.v1_0.svFlag & V1_0::IGnssCallback::GnssSvFlags::USED_IN_FIX) &&
315 (gnss_sv.v2_0.constellation != V2_0::GnssConstellationType::UNKNOWN) &&
316 (gnss_sv.v2_0.constellation != V2_0::GnssConstellationType::GPS)) {
317 // found a non-GPS constellation
318 constellation_to_blacklist = gnss_sv.v2_0.constellation;
319 break;
320 }
321 }
322 if (constellation_to_blacklist != V2_0::GnssConstellationType::UNKNOWN) {
323 break;
324 }
325 }
326
327 if (constellation_to_blacklist == V2_0::GnssConstellationType::UNKNOWN) {
328 ALOGI("No non-GPS constellations found, constellation blacklist test less effective.");
329 // Proceed functionally to blacklist something.
330 constellation_to_blacklist = V2_0::GnssConstellationType::GLONASS;
331 }
332
333 return constellation_to_blacklist;
334 }
335
336 template <class T_IGnss>
gnssMeasurementCb_2_1(const V2_1::IGnssMeasurementCallback::GnssData & data)337 Return<void> GnssHalTestTemplate<T_IGnss>::GnssMeasurementCallback::gnssMeasurementCb_2_1(
338 const V2_1::IGnssMeasurementCallback::GnssData& data) {
339 ALOGD("GnssMeasurement v2.1 received. Size = %d", (int)data.measurements.size());
340 measurement_cbq_.store(data);
341 return Void();
342 }
343
344 template <class T_IGnss>
setCapabilitiesCb(uint32_t capabilities)345 Return<void> GnssHalTestTemplate<T_IGnss>::GnssMeasurementCorrectionsCallback::setCapabilitiesCb(
346 uint32_t capabilities) {
347 ALOGI("GnssMeasurementCorrectionsCallback capabilities received %d", capabilities);
348 capabilities_cbq_.store(capabilities);
349 return Void();
350 }
351
352 template <class T_IGnss>
gnssAntennaInfoCb(const hidl_vec<V2_1::IGnssAntennaInfoCallback::GnssAntennaInfo> & gnssAntennaInfos)353 Return<void> GnssHalTestTemplate<T_IGnss>::GnssAntennaInfoCallback::gnssAntennaInfoCb(
354 const hidl_vec<V2_1::IGnssAntennaInfoCallback::GnssAntennaInfo>& gnssAntennaInfos) {
355 ALOGD("GnssAntennaInfo v2.1 received. Size = %d", (int)gnssAntennaInfos.size());
356 antenna_info_cbq_.store(gnssAntennaInfos);
357 return Void();
358 }
359
360 } // namespace android::hardware::gnss::common
361