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 <android/hidl/manager/1.2/IServiceManager.h>
20 #include <hidl/ServiceManagement.h>
21
22 #include <gnss_hal_test.h>
23 #include <chrono>
24 #include "Utils.h"
25
26 using ::android::hardware::hidl_string;
27 using ::android::hardware::hidl_vec;
28
29 using ::android::hardware::gnss::common::Utils;
30
31 // Implementations for the main test class for GNSS HAL
GnssHalTest()32 GnssHalTest::GnssHalTest()
33 : info_called_count_(0),
34 capabilities_called_count_(0),
35 location_called_count_(0),
36 name_called_count_(0),
37 notify_count_(0) {}
38
SetUp()39 void GnssHalTest::SetUp() {
40 gnss_hal_ = ::testing::VtsHalHidlTargetTestBase::getService<IGnss>(
41 GnssHidlEnvironment::Instance()->getServiceName<IGnss>());
42 list_gnss_sv_status_.clear();
43 ASSERT_NE(gnss_hal_, nullptr);
44
45 SetUpGnssCallback();
46 }
47
TearDown()48 void GnssHalTest::TearDown() {
49 if (gnss_hal_ != nullptr) {
50 gnss_hal_->cleanup();
51 }
52 if (notify_count_ > 0) {
53 ALOGW("%d unprocessed callbacks discarded", notify_count_);
54 }
55 }
56
SetUpGnssCallback()57 void GnssHalTest::SetUpGnssCallback() {
58 gnss_cb_ = new GnssCallback(*this);
59 ASSERT_NE(gnss_cb_, nullptr);
60
61 auto result = gnss_hal_->setCallback_1_1(gnss_cb_);
62 if (!result.isOk()) {
63 ALOGE("result of failed setCallback %s", result.description().c_str());
64 }
65
66 ASSERT_TRUE(result.isOk());
67 ASSERT_TRUE(result);
68
69 /*
70 * All capabilities, name and systemInfo callbacks should trigger
71 */
72 EXPECT_EQ(std::cv_status::no_timeout, wait(TIMEOUT_SEC));
73 EXPECT_EQ(std::cv_status::no_timeout, wait(TIMEOUT_SEC));
74 EXPECT_EQ(std::cv_status::no_timeout, wait(TIMEOUT_SEC));
75
76 EXPECT_EQ(capabilities_called_count_, 1);
77 EXPECT_EQ(info_called_count_, 1);
78 EXPECT_EQ(name_called_count_, 1);
79 }
80
StopAndClearLocations()81 void GnssHalTest::StopAndClearLocations() {
82 auto result = gnss_hal_->stop();
83
84 EXPECT_TRUE(result.isOk());
85 EXPECT_TRUE(result);
86
87 /*
88 * Clear notify/waiting counter, allowing up till the timeout after
89 * the last reply for final startup messages to arrive (esp. system
90 * info.)
91 */
92 while (wait(TIMEOUT_SEC) == std::cv_status::no_timeout) {
93 }
94 location_called_count_ = 0;
95 }
96
SetPositionMode(const int min_interval_msec,const bool low_power_mode)97 void GnssHalTest::SetPositionMode(const int min_interval_msec, const bool low_power_mode) {
98 const int kPreferredAccuracy = 0; // Ideally perfect (matches GnssLocationProvider)
99 const int kPreferredTimeMsec = 0; // Ideally immediate
100
101 auto result = gnss_hal_->setPositionMode_1_1(
102 IGnss::GnssPositionMode::MS_BASED, IGnss::GnssPositionRecurrence::RECURRENCE_PERIODIC,
103 min_interval_msec, kPreferredAccuracy, kPreferredTimeMsec, low_power_mode);
104
105 ASSERT_TRUE(result.isOk());
106 EXPECT_TRUE(result);
107 }
108
StartAndCheckFirstLocation()109 bool GnssHalTest::StartAndCheckFirstLocation() {
110 auto result = gnss_hal_->start();
111
112 EXPECT_TRUE(result.isOk());
113 EXPECT_TRUE(result);
114
115 /*
116 * GnssLocationProvider support of AGPS SUPL & XtraDownloader is not available in VTS,
117 * so allow time to demodulate ephemeris over the air.
118 */
119 const int kFirstGnssLocationTimeoutSeconds = 75;
120
121 wait(kFirstGnssLocationTimeoutSeconds);
122 EXPECT_EQ(location_called_count_, 1);
123
124 if (location_called_count_ > 0) {
125 // don't require speed on first fix
126 CheckLocation(last_location_, false);
127 return true;
128 }
129 return false;
130 }
131
CheckLocation(GnssLocation & location,bool check_speed)132 void GnssHalTest::CheckLocation(GnssLocation& location, bool check_speed) {
133 bool check_more_accuracies = (info_called_count_ > 0 && last_info_.yearOfHw >= 2017);
134
135 Utils::checkLocation(location, check_speed, check_more_accuracies);
136 }
137
StartAndCheckLocations(int count)138 void GnssHalTest::StartAndCheckLocations(int count) {
139 const int kMinIntervalMsec = 500;
140 const int kLocationTimeoutSubsequentSec = 2;
141 const bool kLowPowerMode = false;
142
143 SetPositionMode(kMinIntervalMsec, kLowPowerMode);
144
145 EXPECT_TRUE(StartAndCheckFirstLocation());
146
147 for (int i = 1; i < count; i++) {
148 EXPECT_EQ(std::cv_status::no_timeout, wait(kLocationTimeoutSubsequentSec));
149 EXPECT_EQ(location_called_count_, i + 1);
150 // Don't cause confusion by checking details if no location yet
151 if (location_called_count_ > 0) {
152 // Should be more than 1 location by now, but if not, still don't check first fix speed
153 CheckLocation(last_location_, location_called_count_ > 1);
154 }
155 }
156 }
157
IsGnssHalVersion_1_1() const158 bool GnssHalTest::IsGnssHalVersion_1_1() const {
159 using ::android::hidl::manager::V1_2::IServiceManager;
160 sp<IServiceManager> manager = ::android::hardware::defaultServiceManager1_2();
161
162 bool hasGnssHalVersion_1_1 = false;
163 manager->listManifestByInterface(
164 "android.hardware.gnss@1.1::IGnss",
165 [&hasGnssHalVersion_1_1](const hidl_vec<hidl_string>& registered) {
166 ASSERT_EQ(1, registered.size());
167 hasGnssHalVersion_1_1 = true;
168 });
169
170 bool hasGnssHalVersion_2_0 = false;
171 manager->listManifestByInterface(
172 "android.hardware.gnss@2.0::IGnss",
173 [&hasGnssHalVersion_2_0](const hidl_vec<hidl_string>& registered) {
174 hasGnssHalVersion_2_0 = registered.size() != 0;
175 });
176
177 return hasGnssHalVersion_1_1 && !hasGnssHalVersion_2_0;
178 }
179
startLocationAndGetNonGpsConstellation()180 GnssConstellationType GnssHalTest::startLocationAndGetNonGpsConstellation() {
181 const int kLocationsToAwait = 3;
182
183 StartAndCheckLocations(kLocationsToAwait);
184
185 // Tolerate 1 less sv status to handle edge cases in reporting.
186 EXPECT_GE((int)list_gnss_sv_status_.size() + 1, kLocationsToAwait);
187 ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations (%d received)",
188 (int)list_gnss_sv_status_.size(), kLocationsToAwait, location_called_count_);
189
190 // Find first non-GPS constellation
191 GnssConstellationType constellation_to_blacklist = GnssConstellationType::UNKNOWN;
192 for (const auto& gnss_sv_status : list_gnss_sv_status_) {
193 for (uint32_t iSv = 0; iSv < gnss_sv_status.numSvs; iSv++) {
194 const auto& gnss_sv = gnss_sv_status.gnssSvList[iSv];
195 if ((gnss_sv.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX) &&
196 (gnss_sv.constellation != GnssConstellationType::UNKNOWN) &&
197 (gnss_sv.constellation != GnssConstellationType::GPS)) {
198 // found a non-GPS constellation
199 constellation_to_blacklist = gnss_sv.constellation;
200 break;
201 }
202 }
203 if (constellation_to_blacklist != GnssConstellationType::UNKNOWN) {
204 break;
205 }
206 }
207
208 if (constellation_to_blacklist == GnssConstellationType::UNKNOWN) {
209 ALOGI("No non-GPS constellations found, constellation blacklist test less effective.");
210 // Proceed functionally to return something.
211 constellation_to_blacklist = GnssConstellationType::GLONASS;
212 }
213 return constellation_to_blacklist;
214 }
215
notify()216 void GnssHalTest::notify() {
217 std::unique_lock<std::mutex> lock(mtx_);
218 notify_count_++;
219 cv_.notify_one();
220 }
221
wait(int timeout_seconds)222 std::cv_status GnssHalTest::wait(int timeout_seconds) {
223 std::unique_lock<std::mutex> lock(mtx_);
224
225 auto status = std::cv_status::no_timeout;
226 while (notify_count_ == 0) {
227 status = cv_.wait_for(lock, std::chrono::seconds(timeout_seconds));
228 if (status == std::cv_status::timeout) return status;
229 }
230 notify_count_--;
231 return status;
232 }
233
gnssSetSystemInfoCb(const IGnssCallback::GnssSystemInfo & info)234 Return<void> GnssHalTest::GnssCallback::gnssSetSystemInfoCb(
235 const IGnssCallback::GnssSystemInfo& info) {
236 ALOGI("Info received, year %d", info.yearOfHw);
237 parent_.info_called_count_++;
238 parent_.last_info_ = info;
239 parent_.notify();
240 return Void();
241 }
242
gnssSetCapabilitesCb(uint32_t capabilities)243 Return<void> GnssHalTest::GnssCallback::gnssSetCapabilitesCb(uint32_t capabilities) {
244 ALOGI("Capabilities received %d", capabilities);
245 parent_.capabilities_called_count_++;
246 parent_.last_capabilities_ = capabilities;
247 parent_.notify();
248 return Void();
249 }
250
gnssNameCb(const android::hardware::hidl_string & name)251 Return<void> GnssHalTest::GnssCallback::gnssNameCb(const android::hardware::hidl_string& name) {
252 ALOGI("Name received: %s", name.c_str());
253 parent_.name_called_count_++;
254 parent_.last_name_ = name;
255 parent_.notify();
256 return Void();
257 }
258
gnssLocationCb(const GnssLocation & location)259 Return<void> GnssHalTest::GnssCallback::gnssLocationCb(const GnssLocation& location) {
260 ALOGI("Location received");
261 parent_.location_called_count_++;
262 parent_.last_location_ = location;
263 parent_.notify();
264 return Void();
265 }
266
gnssSvStatusCb(const IGnssCallback::GnssSvStatus & svStatus)267 Return<void> GnssHalTest::GnssCallback::gnssSvStatusCb(
268 const IGnssCallback::GnssSvStatus& svStatus) {
269 ALOGI("GnssSvStatus received");
270 parent_.list_gnss_sv_status_.emplace_back(svStatus);
271 return Void();
272 }
273