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 "GnssHalTest"
18 
19 #include <gnss_hal_test.h>
20 
21 #include <chrono>
22 
23 // Implementations for the main test class for GNSS HAL
GnssHalTest()24 GnssHalTest::GnssHalTest()
25     : info_called_count_(0),
26       capabilities_called_count_(0),
27       location_called_count_(0),
28       name_called_count_(0),
29       notify_count_(0) {}
30 
SetUp()31 void GnssHalTest::SetUp() {
32     gnss_hal_ = ::testing::VtsHalHidlTargetTestBase::getService<IGnss>(
33         GnssHidlEnvironment::Instance()->getServiceName<IGnss>());
34     list_gnss_sv_status_.clear();
35     ASSERT_NE(gnss_hal_, nullptr);
36 
37     SetUpGnssCallback();
38 }
39 
TearDown()40 void GnssHalTest::TearDown() {
41     if (gnss_hal_ != nullptr) {
42         gnss_hal_->cleanup();
43     }
44     if (notify_count_ > 0) {
45         ALOGW("%d unprocessed callbacks discarded", notify_count_);
46     }
47 }
48 
SetUpGnssCallback()49 void GnssHalTest::SetUpGnssCallback() {
50     gnss_cb_ = new GnssCallback(*this);
51     ASSERT_NE(gnss_cb_, nullptr);
52 
53     auto result = gnss_hal_->setCallback_1_1(gnss_cb_);
54     if (!result.isOk()) {
55         ALOGE("result of failed setCallback %s", result.description().c_str());
56     }
57 
58     ASSERT_TRUE(result.isOk());
59     ASSERT_TRUE(result);
60 
61     /*
62      * All capabilities, name and systemInfo callbacks should trigger
63      */
64     EXPECT_EQ(std::cv_status::no_timeout, wait(TIMEOUT_SEC));
65     EXPECT_EQ(std::cv_status::no_timeout, wait(TIMEOUT_SEC));
66     EXPECT_EQ(std::cv_status::no_timeout, wait(TIMEOUT_SEC));
67 
68     EXPECT_EQ(capabilities_called_count_, 1);
69     EXPECT_EQ(info_called_count_, 1);
70     EXPECT_EQ(name_called_count_, 1);
71 }
72 
StopAndClearLocations()73 void GnssHalTest::StopAndClearLocations() {
74     auto result = gnss_hal_->stop();
75 
76     EXPECT_TRUE(result.isOk());
77     EXPECT_TRUE(result);
78 
79     /*
80      * Clear notify/waiting counter, allowing up till the timeout after
81      * the last reply for final startup messages to arrive (esp. system
82      * info.)
83      */
84     while (wait(TIMEOUT_SEC) == std::cv_status::no_timeout) {
85     }
86 }
87 
SetPositionMode(const int min_interval_msec,const bool low_power_mode)88 void GnssHalTest::SetPositionMode(const int min_interval_msec, const bool low_power_mode) {
89     const int kPreferredAccuracy = 0;  // Ideally perfect (matches GnssLocationProvider)
90     const int kPreferredTimeMsec = 0;  // Ideally immediate
91 
92     auto result = gnss_hal_->setPositionMode_1_1(
93         IGnss::GnssPositionMode::MS_BASED, IGnss::GnssPositionRecurrence::RECURRENCE_PERIODIC,
94         min_interval_msec, kPreferredAccuracy, kPreferredTimeMsec, low_power_mode);
95 
96     ASSERT_TRUE(result.isOk());
97     EXPECT_TRUE(result);
98 }
99 
StartAndGetSingleLocation()100 bool GnssHalTest::StartAndGetSingleLocation() {
101     auto result = gnss_hal_->start();
102 
103     EXPECT_TRUE(result.isOk());
104     EXPECT_TRUE(result);
105 
106     /*
107      * GPS signals initially optional for this test, so don't expect fast fix,
108      * or no timeout, unless signal is present
109      */
110     const int kFirstGnssLocationTimeoutSeconds = 15;
111 
112     wait(kFirstGnssLocationTimeoutSeconds);
113     EXPECT_EQ(location_called_count_, 1);
114 
115     if (location_called_count_ > 0) {
116         // don't require speed on first fix
117         CheckLocation(last_location_, false);
118         return true;
119     }
120     return false;
121 }
122 
CheckLocation(GnssLocation & location,bool check_speed)123 void GnssHalTest::CheckLocation(GnssLocation& location, bool check_speed) {
124     bool check_more_accuracies = (info_called_count_ > 0 && last_info_.yearOfHw >= 2017);
125 
126     EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_LAT_LONG);
127     EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_ALTITUDE);
128     if (check_speed) {
129         EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_SPEED);
130     }
131     EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_HORIZONTAL_ACCURACY);
132     // New uncertainties available in O must be provided,
133     // at least when paired with modern hardware (2017+)
134     if (check_more_accuracies) {
135         EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_VERTICAL_ACCURACY);
136         if (check_speed) {
137             EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_SPEED_ACCURACY);
138             if (location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING) {
139                 EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING_ACCURACY);
140             }
141         }
142     }
143     EXPECT_GE(location.latitudeDegrees, -90.0);
144     EXPECT_LE(location.latitudeDegrees, 90.0);
145     EXPECT_GE(location.longitudeDegrees, -180.0);
146     EXPECT_LE(location.longitudeDegrees, 180.0);
147     EXPECT_GE(location.altitudeMeters, -1000.0);
148     EXPECT_LE(location.altitudeMeters, 30000.0);
149     if (check_speed) {
150         EXPECT_GE(location.speedMetersPerSec, 0.0);
151         EXPECT_LE(location.speedMetersPerSec, 5.0);  // VTS tests are stationary.
152 
153         // Non-zero speeds must be reported with an associated bearing
154         if (location.speedMetersPerSec > 0.0) {
155             EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING);
156         }
157     }
158 
159     /*
160      * Tolerating some especially high values for accuracy estimate, in case of
161      * first fix with especially poor geometry (happens occasionally)
162      */
163     EXPECT_GT(location.horizontalAccuracyMeters, 0.0);
164     EXPECT_LE(location.horizontalAccuracyMeters, 250.0);
165 
166     /*
167      * Some devices may define bearing as -180 to +180, others as 0 to 360.
168      * Both are okay & understandable.
169      */
170     if (location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING) {
171         EXPECT_GE(location.bearingDegrees, -180.0);
172         EXPECT_LE(location.bearingDegrees, 360.0);
173     }
174     if (location.gnssLocationFlags & GnssLocationFlags::HAS_VERTICAL_ACCURACY) {
175         EXPECT_GT(location.verticalAccuracyMeters, 0.0);
176         EXPECT_LE(location.verticalAccuracyMeters, 500.0);
177     }
178     if (location.gnssLocationFlags & GnssLocationFlags::HAS_SPEED_ACCURACY) {
179         EXPECT_GT(location.speedAccuracyMetersPerSecond, 0.0);
180         EXPECT_LE(location.speedAccuracyMetersPerSecond, 50.0);
181     }
182     if (location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING_ACCURACY) {
183         EXPECT_GT(location.bearingAccuracyDegrees, 0.0);
184         EXPECT_LE(location.bearingAccuracyDegrees, 360.0);
185     }
186 
187     // Check timestamp > 1.48e12 (47 years in msec - 1970->2017+)
188     EXPECT_GT(location.timestamp, 1.48e12);
189 }
190 
StartAndCheckLocations(int count)191 void GnssHalTest::StartAndCheckLocations(int count) {
192     const int kMinIntervalMsec = 500;
193     const int kLocationTimeoutSubsequentSec = 2;
194     const bool kLowPowerMode = false;
195 
196     SetPositionMode(kMinIntervalMsec, kLowPowerMode);
197 
198     EXPECT_TRUE(StartAndGetSingleLocation());
199 
200     for (int i = 1; i < count; i++) {
201         EXPECT_EQ(std::cv_status::no_timeout, wait(kLocationTimeoutSubsequentSec));
202         EXPECT_EQ(location_called_count_, i + 1);
203         // Don't cause confusion by checking details if no location yet
204         if (location_called_count_ > 0) {
205             // Should be more than 1 location by now, but if not, still don't check first fix speed
206             CheckLocation(last_location_, location_called_count_ > 1);
207         }
208     }
209 }
210 
notify()211 void GnssHalTest::notify() {
212     std::unique_lock<std::mutex> lock(mtx_);
213     notify_count_++;
214     cv_.notify_one();
215 }
216 
wait(int timeout_seconds)217 std::cv_status GnssHalTest::wait(int timeout_seconds) {
218     std::unique_lock<std::mutex> lock(mtx_);
219 
220     auto status = std::cv_status::no_timeout;
221     while (notify_count_ == 0) {
222         status = cv_.wait_for(lock, std::chrono::seconds(timeout_seconds));
223         if (status == std::cv_status::timeout) return status;
224     }
225     notify_count_--;
226     return status;
227 }
228 
gnssSetSystemInfoCb(const IGnssCallback::GnssSystemInfo & info)229 Return<void> GnssHalTest::GnssCallback::gnssSetSystemInfoCb(
230     const IGnssCallback::GnssSystemInfo& info) {
231     ALOGI("Info received, year %d", info.yearOfHw);
232     parent_.info_called_count_++;
233     parent_.last_info_ = info;
234     parent_.notify();
235     return Void();
236 }
237 
gnssSetCapabilitesCb(uint32_t capabilities)238 Return<void> GnssHalTest::GnssCallback::gnssSetCapabilitesCb(uint32_t capabilities) {
239     ALOGI("Capabilities received %d", capabilities);
240     parent_.capabilities_called_count_++;
241     parent_.last_capabilities_ = capabilities;
242     parent_.notify();
243     return Void();
244 }
245 
gnssNameCb(const android::hardware::hidl_string & name)246 Return<void> GnssHalTest::GnssCallback::gnssNameCb(const android::hardware::hidl_string& name) {
247     ALOGI("Name received: %s", name.c_str());
248     parent_.name_called_count_++;
249     parent_.last_name_ = name;
250     parent_.notify();
251     return Void();
252 }
253 
gnssLocationCb(const GnssLocation & location)254 Return<void> GnssHalTest::GnssCallback::gnssLocationCb(const GnssLocation& location) {
255     ALOGI("Location received");
256     parent_.location_called_count_++;
257     parent_.last_location_ = location;
258     parent_.notify();
259     return Void();
260 }
261 
gnssSvStatusCb(const IGnssCallback::GnssSvStatus & svStatus)262 Return<void> GnssHalTest::GnssCallback::gnssSvStatusCb(
263     const IGnssCallback::GnssSvStatus& svStatus) {
264     ALOGI("GnssSvStatus received");
265     parent_.list_gnss_sv_status_.emplace_back(svStatus);
266     return Void();
267 }
268