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