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 "VtsHalGnssV1_0TargetTest" 18 #include <android/hardware/gnss/1.0/IGnss.h> 19 #include <log/log.h> 20 21 #include <VtsHalHidlTargetTestBase.h> 22 #include <VtsHalHidlTargetTestEnvBase.h> 23 24 #include <chrono> 25 #include <condition_variable> 26 #include <mutex> 27 28 using android::hardware::Return; 29 using android::hardware::Void; 30 31 using android::hardware::gnss::V1_0::GnssLocation; 32 using android::hardware::gnss::V1_0::GnssLocationFlags; 33 using android::hardware::gnss::V1_0::IGnss; 34 using android::hardware::gnss::V1_0::IGnssCallback; 35 using android::hardware::gnss::V1_0::IGnssDebug; 36 using android::hardware::gnss::V1_0::IGnssMeasurement; 37 using android::sp; 38 39 #define TIMEOUT_SEC 2 // for basic commands/responses 40 41 // for command line argument on how strictly to run the test 42 bool sAgpsIsPresent = false; // if SUPL or XTRA assistance available 43 bool sSignalIsWeak = false; // if GNSS signals are weak (e.g. light indoor) 44 45 // Test environment for GNSS HIDL HAL. 46 class GnssHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { 47 public: 48 // get the test environment singleton 49 static GnssHidlEnvironment* Instance() { 50 static GnssHidlEnvironment* instance = new GnssHidlEnvironment; 51 return instance; 52 } 53 54 virtual void registerTestServices() override { registerTestService<IGnss>(); } 55 56 private: 57 GnssHidlEnvironment() {} 58 }; 59 60 // The main test class for GNSS HAL. 61 class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase { 62 public: 63 virtual void SetUp() override { 64 // Clean between tests 65 capabilities_called_count_ = 0; 66 location_called_count_ = 0; 67 info_called_count_ = 0; 68 notify_count_ = 0; 69 70 gnss_hal_ = ::testing::VtsHalHidlTargetTestBase::getService<IGnss>( 71 GnssHidlEnvironment::Instance()->getServiceName<IGnss>()); 72 ASSERT_NE(gnss_hal_, nullptr); 73 74 gnss_cb_ = new GnssCallback(*this); 75 ASSERT_NE(gnss_cb_, nullptr); 76 77 auto result = gnss_hal_->setCallback(gnss_cb_); 78 if (!result.isOk()) { 79 ALOGE("result of failed setCallback %s", result.description().c_str()); 80 } 81 82 ASSERT_TRUE(result.isOk()); 83 ASSERT_TRUE(result); 84 85 /* 86 * At least one callback should trigger - it may be capabilites, or 87 * system info first, so wait again if capabilities not received. 88 */ 89 EXPECT_EQ(std::cv_status::no_timeout, wait(TIMEOUT_SEC)); 90 if (capabilities_called_count_ == 0) { 91 EXPECT_EQ(std::cv_status::no_timeout, wait(TIMEOUT_SEC)); 92 } 93 94 /* 95 * Generally should be 1 capabilites callback - 96 * or possibly 2 in some recovery cases (default cached & refreshed) 97 */ 98 EXPECT_GE(capabilities_called_count_, 1); 99 EXPECT_LE(capabilities_called_count_, 2); 100 101 /* 102 * Clear notify/waiting counter, allowing up till the timeout after 103 * the last reply for final startup messages to arrive (esp. system 104 * info.) 105 */ 106 while (wait(TIMEOUT_SEC) == std::cv_status::no_timeout) { 107 } 108 } 109 110 virtual void TearDown() override { 111 if (gnss_hal_ != nullptr) { 112 gnss_hal_->cleanup(); 113 } 114 if (notify_count_ > 0) { 115 ALOGW("%d unprocessed callbacks discarded", notify_count_); 116 } 117 } 118 119 /* Used as a mechanism to inform the test that a callback has occurred */ 120 inline void notify() { 121 std::unique_lock<std::mutex> lock(mtx_); 122 notify_count_++; 123 cv_.notify_one(); 124 } 125 126 /* Test code calls this function to wait for a callback */ 127 inline std::cv_status wait(int timeoutSeconds) { 128 std::unique_lock<std::mutex> lock(mtx_); 129 130 std::cv_status status = std::cv_status::no_timeout; 131 auto now = std::chrono::system_clock::now(); 132 while (notify_count_ == 0) { 133 status = cv_.wait_until(lock, now + std::chrono::seconds(timeoutSeconds)); 134 if (status == std::cv_status::timeout) return status; 135 } 136 notify_count_--; 137 return status; 138 } 139 140 /* 141 * StartAndGetSingleLocation: 142 * Helper function to get one Location and check fields 143 * 144 * returns true if a location was successfully generated 145 */ 146 bool StartAndGetSingleLocation(bool checkAccuracies) { 147 auto result = gnss_hal_->start(); 148 149 EXPECT_TRUE(result.isOk()); 150 EXPECT_TRUE(result); 151 152 /* 153 * GPS signals initially optional for this test, so don't expect fast fix, 154 * or no timeout, unless signal is present 155 */ 156 int firstGnssLocationTimeoutSeconds = sAgpsIsPresent ? 15 : 45; 157 if (sSignalIsWeak) { 158 // allow more time for weak signals 159 firstGnssLocationTimeoutSeconds += 30; 160 } 161 162 wait(firstGnssLocationTimeoutSeconds); 163 if (sAgpsIsPresent) { 164 EXPECT_EQ(location_called_count_, 1); 165 } 166 if (location_called_count_ > 0) { 167 // don't require speed on first fix 168 CheckLocation(last_location_, checkAccuracies, false); 169 return true; 170 } 171 return false; 172 } 173 174 /* 175 * StopAndClearLocations: 176 * Helper function to stop locations 177 * 178 * returns true if a location was successfully generated 179 */ 180 void StopAndClearLocations() { 181 auto result = gnss_hal_->stop(); 182 183 EXPECT_TRUE(result.isOk()); 184 EXPECT_TRUE(result); 185 186 /* 187 * Clear notify/waiting counter, allowing up till the timeout after 188 * the last reply for final startup messages to arrive (esp. system 189 * info.) 190 */ 191 while (wait(TIMEOUT_SEC) == std::cv_status::no_timeout) { 192 } 193 } 194 195 /* 196 * CheckLocation: 197 * Helper function to vet Location fields 198 */ 199 void CheckLocation(GnssLocation& location, bool checkAccuracies, bool checkSpeed) { 200 EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_LAT_LONG); 201 EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_ALTITUDE); 202 if (checkSpeed) { 203 EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_SPEED); 204 } 205 EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_HORIZONTAL_ACCURACY); 206 // New uncertainties available in O must be provided, 207 // at least when paired with modern hardware (2017+) 208 if (checkAccuracies) { 209 EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_VERTICAL_ACCURACY); 210 if (checkSpeed) { 211 EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_SPEED_ACCURACY); 212 if (location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING) { 213 EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING_ACCURACY); 214 } 215 } 216 } 217 EXPECT_GE(location.latitudeDegrees, -90.0); 218 EXPECT_LE(location.latitudeDegrees, 90.0); 219 EXPECT_GE(location.longitudeDegrees, -180.0); 220 EXPECT_LE(location.longitudeDegrees, 180.0); 221 EXPECT_GE(location.altitudeMeters, -1000.0); 222 EXPECT_LE(location.altitudeMeters, 30000.0); 223 if (checkSpeed) { 224 EXPECT_GE(location.speedMetersPerSec, 0.0); 225 EXPECT_LE(location.speedMetersPerSec, 5.0); // VTS tests are stationary. 226 227 // Non-zero speeds must be reported with an associated bearing 228 if (location.speedMetersPerSec > 0.0) { 229 EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING); 230 } 231 } 232 233 /* 234 * Tolerating some especially high values for accuracy estimate, in case of 235 * first fix with especially poor geometry (happens occasionally) 236 */ 237 EXPECT_GT(location.horizontalAccuracyMeters, 0.0); 238 EXPECT_LE(location.horizontalAccuracyMeters, 250.0); 239 240 /* 241 * Some devices may define bearing as -180 to +180, others as 0 to 360. 242 * Both are okay & understandable. 243 */ 244 if (location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING) { 245 EXPECT_GE(location.bearingDegrees, -180.0); 246 EXPECT_LE(location.bearingDegrees, 360.0); 247 } 248 if (location.gnssLocationFlags & GnssLocationFlags::HAS_VERTICAL_ACCURACY) { 249 EXPECT_GT(location.verticalAccuracyMeters, 0.0); 250 EXPECT_LE(location.verticalAccuracyMeters, 500.0); 251 } 252 if (location.gnssLocationFlags & GnssLocationFlags::HAS_SPEED_ACCURACY) { 253 EXPECT_GT(location.speedAccuracyMetersPerSecond, 0.0); 254 EXPECT_LE(location.speedAccuracyMetersPerSecond, 50.0); 255 } 256 if (location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING_ACCURACY) { 257 EXPECT_GT(location.bearingAccuracyDegrees, 0.0); 258 EXPECT_LE(location.bearingAccuracyDegrees, 360.0); 259 } 260 261 // Check timestamp > 1.48e12 (47 years in msec - 1970->2017+) 262 EXPECT_GT(location.timestamp, 1.48e12); 263 } 264 265 /* Callback class for data & Event. */ 266 class GnssCallback : public IGnssCallback { 267 public: 268 GnssHalTest& parent_; 269 270 GnssCallback(GnssHalTest& parent) : parent_(parent){}; 271 272 virtual ~GnssCallback() = default; 273 274 // Dummy callback handlers 275 Return<void> gnssStatusCb( 276 const IGnssCallback::GnssStatusValue /* status */) override { 277 return Void(); 278 } 279 Return<void> gnssSvStatusCb( 280 const IGnssCallback::GnssSvStatus& /* svStatus */) override { 281 return Void(); 282 } 283 Return<void> gnssNmeaCb( 284 int64_t /* timestamp */, 285 const android::hardware::hidl_string& /* nmea */) override { 286 return Void(); 287 } 288 Return<void> gnssAcquireWakelockCb() override { return Void(); } 289 Return<void> gnssReleaseWakelockCb() override { return Void(); } 290 Return<void> gnssRequestTimeCb() override { return Void(); } 291 292 // Actual (test) callback handlers 293 Return<void> gnssLocationCb(const GnssLocation& location) override { 294 ALOGI("Location received"); 295 parent_.location_called_count_++; 296 parent_.last_location_ = location; 297 parent_.notify(); 298 return Void(); 299 } 300 301 Return<void> gnssSetCapabilitesCb(uint32_t capabilities) override { 302 ALOGI("Capabilities received %d", capabilities); 303 parent_.capabilities_called_count_++; 304 parent_.last_capabilities_ = capabilities; 305 parent_.notify(); 306 return Void(); 307 } 308 309 Return<void> gnssSetSystemInfoCb( 310 const IGnssCallback::GnssSystemInfo& info) override { 311 ALOGI("Info received, year %d", info.yearOfHw); 312 parent_.info_called_count_++; 313 parent_.last_info_ = info; 314 parent_.notify(); 315 return Void(); 316 } 317 }; 318 319 sp<IGnss> gnss_hal_; // GNSS HAL to call into 320 sp<IGnssCallback> gnss_cb_; // Primary callback interface 321 322 /* Count of calls to set the following items, and the latest item (used by 323 * test.) 324 */ 325 int capabilities_called_count_; 326 uint32_t last_capabilities_; 327 328 int location_called_count_; 329 GnssLocation last_location_; 330 331 int info_called_count_; 332 IGnssCallback::GnssSystemInfo last_info_; 333 334 private: 335 std::mutex mtx_; 336 std::condition_variable cv_; 337 int notify_count_; 338 }; 339 340 /* 341 * SetCallbackCapabilitiesCleanup: 342 * Sets up the callback, awaits the capabilities, and calls cleanup 343 * 344 * Since this is just the basic operation of SetUp() and TearDown(), 345 * the function definition is intentionally empty 346 */ 347 TEST_F(GnssHalTest, SetCallbackCapabilitiesCleanup) {} 348 349 /* 350 * GetLocation: 351 * Turns on location, waits 45 second for at least 5 locations, 352 * and checks them for reasonable validity. 353 */ 354 TEST_F(GnssHalTest, GetLocation) { 355 #define MIN_INTERVAL_MSEC 500 356 #define PREFERRED_ACCURACY 0 // Ideally perfect (matches GnssLocationProvider) 357 #define PREFERRED_TIME_MSEC 0 // Ideally immediate 358 359 #define LOCATION_TIMEOUT_SUBSEQUENT_SEC 3 360 #define LOCATIONS_TO_CHECK 5 361 362 bool checkMoreAccuracies = 363 (info_called_count_ > 0 && last_info_.yearOfHw >= 2017); 364 365 auto result = gnss_hal_->setPositionMode( 366 IGnss::GnssPositionMode::MS_BASED, 367 IGnss::GnssPositionRecurrence::RECURRENCE_PERIODIC, MIN_INTERVAL_MSEC, 368 PREFERRED_ACCURACY, PREFERRED_TIME_MSEC); 369 370 ASSERT_TRUE(result.isOk()); 371 EXPECT_TRUE(result); 372 373 /* 374 * GPS signals initially optional for this test, so don't expect no timeout 375 * yet 376 */ 377 bool gotLocation = StartAndGetSingleLocation(checkMoreAccuracies); 378 379 if (gotLocation) { 380 for (int i = 1; i < LOCATIONS_TO_CHECK; i++) { 381 EXPECT_EQ(std::cv_status::no_timeout, wait(LOCATION_TIMEOUT_SUBSEQUENT_SEC)); 382 EXPECT_EQ(location_called_count_, i + 1); 383 CheckLocation(last_location_, checkMoreAccuracies, true); 384 } 385 } 386 387 StopAndClearLocations(); 388 } 389 390 /* 391 * InjectDelete: 392 * Ensures that calls to inject and/or delete information state are handled. 393 */ 394 TEST_F(GnssHalTest, InjectDelete) { 395 // confidently, well north of Alaska 396 auto result = gnss_hal_->injectLocation(80.0, -170.0, 1000.0); 397 398 ASSERT_TRUE(result.isOk()); 399 EXPECT_TRUE(result); 400 401 // fake time, but generally reasonable values (time in Aug. 2018) 402 result = gnss_hal_->injectTime(1534567890123L, 123456L, 10000L); 403 404 ASSERT_TRUE(result.isOk()); 405 EXPECT_TRUE(result); 406 407 auto resultVoid = gnss_hal_->deleteAidingData(IGnss::GnssAidingData::DELETE_ALL); 408 409 ASSERT_TRUE(resultVoid.isOk()); 410 411 // Ensure we can get a good location after a bad injection has been deleted 412 StartAndGetSingleLocation(false); 413 414 StopAndClearLocations(); 415 } 416 417 /* 418 * GetAllExtentions: 419 * Tries getting all optional extensions, and ensures a valid return 420 * null or actual extension, no crash. 421 * Confirms year-based required extensions (Measurement & Debug) are present 422 */ 423 TEST_F(GnssHalTest, GetAllExtensions) { 424 // Basic call-is-handled checks 425 auto gnssXtra = gnss_hal_->getExtensionXtra(); 426 ASSERT_TRUE(gnssXtra.isOk()); 427 428 auto gnssRil = gnss_hal_->getExtensionAGnssRil(); 429 ASSERT_TRUE(gnssRil.isOk()); 430 431 auto gnssAgnss = gnss_hal_->getExtensionAGnss(); 432 ASSERT_TRUE(gnssAgnss.isOk()); 433 434 auto gnssNi = gnss_hal_->getExtensionGnssNi(); 435 ASSERT_TRUE(gnssNi.isOk()); 436 437 auto gnssNavigationMessage = gnss_hal_->getExtensionGnssNavigationMessage(); 438 ASSERT_TRUE(gnssNavigationMessage.isOk()); 439 440 auto gnssConfiguration = gnss_hal_->getExtensionGnssConfiguration(); 441 ASSERT_TRUE(gnssConfiguration.isOk()); 442 443 auto gnssGeofencing = gnss_hal_->getExtensionGnssGeofencing(); 444 ASSERT_TRUE(gnssGeofencing.isOk()); 445 446 auto gnssBatching = gnss_hal_->getExtensionGnssBatching(); 447 ASSERT_TRUE(gnssBatching.isOk()); 448 449 // Verifying, in some cases, that these return actual extensions 450 auto gnssMeasurement = gnss_hal_->getExtensionGnssMeasurement(); 451 ASSERT_TRUE(gnssMeasurement.isOk()); 452 if (last_capabilities_ & IGnssCallback::Capabilities::MEASUREMENTS) { 453 sp<IGnssMeasurement> iGnssMeas = gnssMeasurement; 454 EXPECT_NE(iGnssMeas, nullptr); 455 } 456 457 auto gnssDebug = gnss_hal_->getExtensionGnssDebug(); 458 ASSERT_TRUE(gnssDebug.isOk()); 459 if (info_called_count_ > 0 && last_info_.yearOfHw >= 2017) { 460 sp<IGnssDebug> iGnssDebug = gnssDebug; 461 EXPECT_NE(iGnssDebug, nullptr); 462 } 463 } 464 465 /* 466 * MeasurementCapabilities: 467 * Verifies that modern hardware supports measurement capabilities. 468 */ 469 TEST_F(GnssHalTest, MeasurementCapabilites) { 470 if (info_called_count_ > 0 && last_info_.yearOfHw >= 2016) { 471 EXPECT_TRUE(last_capabilities_ & IGnssCallback::Capabilities::MEASUREMENTS); 472 } 473 } 474 475 int main(int argc, char** argv) { 476 ::testing::AddGlobalTestEnvironment(GnssHidlEnvironment::Instance()); 477 ::testing::InitGoogleTest(&argc, argv); 478 GnssHidlEnvironment::Instance()->init(&argc, argv); 479 /* 480 * These arguments not used by automated VTS testing. 481 * Only for use in manual testing, when wanting to run 482 * stronger tests that require the presence of GPS signal. 483 */ 484 for (int i = 1; i < argc; i++) { 485 if (strcmp(argv[i], "-agps") == 0) { 486 sAgpsIsPresent = true; 487 } else if (strcmp(argv[i], "-weak") == 0) { 488 sSignalIsWeak = true; 489 } 490 } 491 int status = RUN_ALL_TESTS(); 492 ALOGI("Test result = %d", status); 493 return status; 494 } 495