diff options
author | Yu-Han Yang <yuhany@google.com> | 2022-04-27 09:57:01 -0700 |
---|---|---|
committer | Yu-Han Yang <yuhany@google.com> | 2022-05-11 20:28:03 +0000 |
commit | 19a32b627098fdec92cee2eeb41dffdc4921fb93 (patch) | |
tree | 39c0bb066b5aede7b0b6c060c701d1a7731faa91 | |
parent | dd890b58457734d44e4e2af87fb1343d2348689e (diff) |
Add VTS tests for measurementInterval, stopSvStatus, and stopNmea
Bug: 206670536
Test: atest VtsHalGnssTargetTest
Change-Id: Id597c772fbe63789cb394b2aa14faeb755196f64
-rw-r--r-- | gnss/aidl/default/Gnss.cpp | 69 | ||||
-rw-r--r-- | gnss/aidl/default/Gnss.h | 6 | ||||
-rw-r--r-- | gnss/aidl/default/GnssMeasurementInterface.cpp | 73 | ||||
-rw-r--r-- | gnss/aidl/default/GnssMeasurementInterface.h | 11 | ||||
-rw-r--r-- | gnss/aidl/default/GnssNavigationMessageInterface.cpp | 37 | ||||
-rw-r--r-- | gnss/aidl/default/GnssNavigationMessageInterface.h | 5 | ||||
-rw-r--r-- | gnss/aidl/vts/GnssCallbackAidl.cpp | 5 | ||||
-rw-r--r-- | gnss/aidl/vts/GnssCallbackAidl.h | 6 | ||||
-rw-r--r-- | gnss/aidl/vts/GnssMeasurementCallbackAidl.cpp | 6 | ||||
-rw-r--r-- | gnss/aidl/vts/gnss_hal_test.cpp | 175 | ||||
-rw-r--r-- | gnss/aidl/vts/gnss_hal_test.h | 19 | ||||
-rw-r--r-- | gnss/aidl/vts/gnss_hal_test_cases.cpp | 248 | ||||
-rw-r--r-- | gnss/common/utils/default/include/Utils.h | 25 |
13 files changed, 527 insertions, 158 deletions
diff --git a/gnss/aidl/default/Gnss.cpp b/gnss/aidl/default/Gnss.cpp index 7855b5196a..cf2c90d359 100644 --- a/gnss/aidl/default/Gnss.cpp +++ b/gnss/aidl/default/Gnss.cpp @@ -19,6 +19,7 @@ #include "Gnss.h" #include <inttypes.h> #include <log/log.h> +#include <utils/Timers.h> #include "AGnss.h" #include "AGnssRil.h" #include "DeviceFileReader.h" @@ -28,7 +29,6 @@ #include "GnssConfiguration.h" #include "GnssDebug.h" #include "GnssGeofence.h" -#include "GnssMeasurementInterface.h" #include "GnssNavigationMessageInterface.h" #include "GnssPsds.h" #include "GnssVisibilityControl.h" @@ -95,6 +95,9 @@ ScopedAStatus Gnss::start() { } mIsActive = true; + mThreadBlocker.reset(); + // notify measurement engine to update measurement interval + mGnssMeasurementInterface->setLocationEnabled(true); this->reportGnssStatusValue(IGnssCallback::GnssStatusValue::SESSION_BEGIN); mThread = std::thread([this]() { this->reportSvStatus(); @@ -102,8 +105,12 @@ ScopedAStatus Gnss::start() { std::this_thread::sleep_for(std::chrono::milliseconds(TTFF_MILLIS)); mFirstFixReceived = true; } - while (mIsActive == true) { + do { + if (!mIsActive) { + break; + } this->reportSvStatus(); + this->reportNmea(); auto currentLocation = getLocationFromHW(); mGnssPowerIndication->notePowerConsumption(); @@ -113,12 +120,29 @@ ScopedAStatus Gnss::start() { const auto location = Utils::getMockLocation(); this->reportLocation(location); } - std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMs)); - } + } while (mIsActive && mThreadBlocker.wait_for(std::chrono::milliseconds(mMinIntervalMs))); }); return ScopedAStatus::ok(); } +ScopedAStatus Gnss::stop() { + ALOGD("stop"); + mIsActive = false; + mGnssMeasurementInterface->setLocationEnabled(false); + this->reportGnssStatusValue(IGnssCallback::GnssStatusValue::SESSION_END); + mThreadBlocker.notify(); + if (mThread.joinable()) { + mThread.join(); + } + return ScopedAStatus::ok(); +} + +ScopedAStatus Gnss::close() { + ALOGD("close"); + sGnssCallback = nullptr; + return ScopedAStatus::ok(); +} + void Gnss::reportLocation(const GnssLocation& location) const { std::unique_lock<std::mutex> lock(mMutex); if (sGnssCallback == nullptr) { @@ -153,7 +177,6 @@ void Gnss::reportSvStatus(const std::vector<GnssSvInfo>& svInfoList) const { std::vector<GnssSvInfo> Gnss::filterBlocklistedSatellites( std::vector<GnssSvInfo> gnssSvInfoList) const { - ALOGD("filterBlocklistedSatellites"); for (uint32_t i = 0; i < gnssSvInfoList.size(); i++) { if (mGnssConfiguration->isBlocklisted(gnssSvInfoList[i])) { gnssSvInfoList[i].svFlag &= ~(uint32_t)IGnssCallback::GnssSvFlags::USED_IN_FIX; @@ -174,14 +197,19 @@ void Gnss::reportGnssStatusValue(const IGnssCallback::GnssStatusValue gnssStatus } } -ScopedAStatus Gnss::stop() { - ALOGD("stop"); - mIsActive = false; - this->reportGnssStatusValue(IGnssCallback::GnssStatusValue::SESSION_END); - if (mThread.joinable()) { - mThread.join(); +void Gnss::reportNmea() const { + if (mIsNmeaActive) { + std::unique_lock<std::mutex> lock(mMutex); + if (sGnssCallback == nullptr) { + ALOGE("%s: sGnssCallback is null.", __func__); + return; + } + nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); + auto status = sGnssCallback->gnssNmeaCb(now, "$TEST,0,1,2,3,4,5"); + if (!status.isOk()) { + ALOGE("%s: Unable to invoke callback", __func__); + } } - return ScopedAStatus::ok(); } ScopedAStatus Gnss::startSvStatus() { @@ -197,16 +225,12 @@ ScopedAStatus Gnss::stopSvStatus() { } ScopedAStatus Gnss::startNmea() { ALOGD("startNmea"); + mIsNmeaActive = true; return ScopedAStatus::ok(); } ScopedAStatus Gnss::stopNmea() { ALOGD("stopNmea"); - return ScopedAStatus::ok(); -} - -ScopedAStatus Gnss::close() { - ALOGD("close"); - sGnssCallback = nullptr; + mIsNmeaActive = false; return ScopedAStatus::ok(); } @@ -249,7 +273,8 @@ ScopedAStatus Gnss::deleteAidingData(GnssAidingData aidingDataFlags) { ScopedAStatus Gnss::setPositionMode(const PositionModeOptions& options) { ALOGD("setPositionMode. minIntervalMs:%d, lowPowerMode:%d", options.minIntervalMs, (int)options.lowPowerMode); - mMinIntervalMs = options.minIntervalMs; + mMinIntervalMs = std::max(1000, options.minIntervalMs); + mGnssMeasurementInterface->setLocationInterval(mMinIntervalMs); return ScopedAStatus::ok(); } @@ -283,8 +308,10 @@ ScopedAStatus Gnss::getExtensionGnssPowerIndication( ScopedAStatus Gnss::getExtensionGnssMeasurement( std::shared_ptr<IGnssMeasurementInterface>* iGnssMeasurement) { ALOGD("getExtensionGnssMeasurement"); - - *iGnssMeasurement = SharedRefBase::make<GnssMeasurementInterface>(); + if (mGnssMeasurementInterface == nullptr) { + mGnssMeasurementInterface = SharedRefBase::make<GnssMeasurementInterface>(); + } + *iGnssMeasurement = mGnssMeasurementInterface; return ScopedAStatus::ok(); } diff --git a/gnss/aidl/default/Gnss.h b/gnss/aidl/default/Gnss.h index 1489b4b5e2..df10fc856b 100644 --- a/gnss/aidl/default/Gnss.h +++ b/gnss/aidl/default/Gnss.h @@ -32,7 +32,9 @@ #include <mutex> #include <thread> #include "GnssConfiguration.h" +#include "GnssMeasurementInterface.h" #include "GnssPowerIndication.h" +#include "Utils.h" namespace aidl::android::hardware::gnss { @@ -84,6 +86,7 @@ class Gnss : public BnGnss { std::shared_ptr<GnssConfiguration> mGnssConfiguration; std::shared_ptr<GnssPowerIndication> mGnssPowerIndication; + std::shared_ptr<GnssMeasurementInterface> mGnssMeasurementInterface; private: void reportLocation(const GnssLocation&) const; @@ -93,14 +96,17 @@ class Gnss : public BnGnss { std::vector<IGnssCallback::GnssSvInfo> gnssSvInfoList) const; void reportGnssStatusValue(const IGnssCallback::GnssStatusValue gnssStatusValue) const; std::unique_ptr<GnssLocation> getLocationFromHW(); + void reportNmea() const; static std::shared_ptr<IGnssCallback> sGnssCallback; std::atomic<long> mMinIntervalMs; std::atomic<bool> mIsActive; std::atomic<bool> mIsSvStatusActive; + std::atomic<bool> mIsNmeaActive; std::atomic<bool> mFirstFixReceived; std::thread mThread; + ::android::hardware::gnss::common::ThreadBlocker mThreadBlocker; mutable std::mutex mMutex; }; diff --git a/gnss/aidl/default/GnssMeasurementInterface.cpp b/gnss/aidl/default/GnssMeasurementInterface.cpp index 2c7241b82e..606de07367 100644 --- a/gnss/aidl/default/GnssMeasurementInterface.cpp +++ b/gnss/aidl/default/GnssMeasurementInterface.cpp @@ -33,10 +33,11 @@ using DeviceFileReader = ::android::hardware::gnss::common::DeviceFileReader; std::shared_ptr<IGnssMeasurementCallback> GnssMeasurementInterface::sCallback = nullptr; -GnssMeasurementInterface::GnssMeasurementInterface() : mMinIntervalMillis(1000) {} +GnssMeasurementInterface::GnssMeasurementInterface() + : mIntervalMs(1000), mLocationIntervalMs(1000), mFutures(std::vector<std::future<void>>()) {} GnssMeasurementInterface::~GnssMeasurementInterface() { - stop(); + waitForStoppingThreads(); } ndk::ScopedAStatus GnssMeasurementInterface::setCallback( @@ -44,8 +45,10 @@ ndk::ScopedAStatus GnssMeasurementInterface::setCallback( const bool enableCorrVecOutputs) { ALOGD("setCallback: enableFullTracking: %d enableCorrVecOutputs: %d", (int)enableFullTracking, (int)enableCorrVecOutputs); - std::unique_lock<std::mutex> lock(mMutex); - sCallback = callback; + { + std::unique_lock<std::mutex> lock(mMutex); + sCallback = callback; + } if (mIsActive) { ALOGW("GnssMeasurement callback already set. Resetting the callback..."); @@ -60,14 +63,16 @@ ndk::ScopedAStatus GnssMeasurementInterface::setCallbackWithOptions( const std::shared_ptr<IGnssMeasurementCallback>& callback, const Options& options) { ALOGD("setCallbackWithOptions: fullTracking:%d, corrVec:%d, intervalMs:%d", (int)options.enableFullTracking, (int)options.enableCorrVecOutputs, options.intervalMs); - std::unique_lock<std::mutex> lock(mMutex); - sCallback = callback; + { + std::unique_lock<std::mutex> lock(mMutex); + sCallback = callback; + } if (mIsActive) { ALOGW("GnssMeasurement callback already set. Resetting the callback..."); stop(); } - mMinIntervalMillis = options.intervalMs; + mIntervalMs = std::max(options.intervalMs, 1000); start(options.enableCorrVecOutputs); return ndk::ScopedAStatus::ok(); @@ -75,18 +80,35 @@ ndk::ScopedAStatus GnssMeasurementInterface::setCallbackWithOptions( ndk::ScopedAStatus GnssMeasurementInterface::close() { ALOGD("close"); - stop(); - std::unique_lock<std::mutex> lock(mMutex); - sCallback = nullptr; - mMinIntervalMillis = 1000; + if (mIsActive) { + stop(); + } + { + std::unique_lock<std::mutex> lock(mMutex); + sCallback = nullptr; + } + mIntervalMs = 1000; return ndk::ScopedAStatus::ok(); } void GnssMeasurementInterface::start(const bool enableCorrVecOutputs) { ALOGD("start"); + + if (mIsActive) { + ALOGD("restarting since measurement has started"); + stop(); + } + // Wait for stopping previous thread. + waitForStoppingThreads(); + mIsActive = true; + mThreadBlocker.reset(); mThread = std::thread([this, enableCorrVecOutputs]() { - while (mIsActive == true) { + int intervalMs; + do { + if (!mIsActive) { + break; + } std::string rawMeasurementStr = ""; if (ReplayUtils::hasGnssDeviceFile() && ReplayUtils::isGnssRawMeasurement( @@ -103,15 +125,19 @@ void GnssMeasurementInterface::start(const bool enableCorrVecOutputs) { auto measurement = Utils::getMockMeasurement(enableCorrVecOutputs); this->reportMeasurement(measurement); } - std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMillis)); - } + intervalMs = + (mLocationEnabled) ? std::min(mLocationIntervalMs, mIntervalMs) : mIntervalMs; + } while (mIsActive && mThreadBlocker.wait_for(std::chrono::milliseconds(intervalMs))); }); - mThread.detach(); } void GnssMeasurementInterface::stop() { ALOGD("stop"); mIsActive = false; + mThreadBlocker.notify(); + if (mThread.joinable()) { + mFutures.push_back(std::async(std::launch::async, [this] { mThread.join(); })); + } } void GnssMeasurementInterface::reportMeasurement(const GnssData& data) { @@ -128,4 +154,21 @@ void GnssMeasurementInterface::reportMeasurement(const GnssData& data) { callbackCopy->gnssMeasurementCb(data); } +void GnssMeasurementInterface::setLocationInterval(const int intervalMs) { + mLocationIntervalMs = intervalMs; +} + +void GnssMeasurementInterface::setLocationEnabled(const bool enabled) { + mLocationEnabled = enabled; +} + +void GnssMeasurementInterface::waitForStoppingThreads() { + for (auto& future : mFutures) { + ALOGD("Stopping previous thread."); + future.wait(); + ALOGD("Done stopping thread."); + } + mFutures.clear(); +} + } // namespace aidl::android::hardware::gnss diff --git a/gnss/aidl/default/GnssMeasurementInterface.h b/gnss/aidl/default/GnssMeasurementInterface.h index bf77806acb..bb08027568 100644 --- a/gnss/aidl/default/GnssMeasurementInterface.h +++ b/gnss/aidl/default/GnssMeasurementInterface.h @@ -19,8 +19,10 @@ #include <aidl/android/hardware/gnss/BnGnssMeasurementCallback.h> #include <aidl/android/hardware/gnss/BnGnssMeasurementInterface.h> #include <atomic> +#include <future> #include <mutex> #include <thread> +#include "Utils.h" namespace aidl::android::hardware::gnss { @@ -35,15 +37,22 @@ struct GnssMeasurementInterface : public BnGnssMeasurementInterface { ndk::ScopedAStatus setCallbackWithOptions( const std::shared_ptr<IGnssMeasurementCallback>& callback, const Options& options) override; + void setLocationInterval(const int intervalMs); + void setLocationEnabled(const bool enabled); private: void start(const bool enableCorrVecOutputs); void stop(); void reportMeasurement(const GnssData&); + void waitForStoppingThreads(); - std::atomic<long> mMinIntervalMillis; + std::atomic<long> mIntervalMs; + std::atomic<long> mLocationIntervalMs; std::atomic<bool> mIsActive; + std::atomic<bool> mLocationEnabled; std::thread mThread; + std::vector<std::future<void>> mFutures; + ::android::hardware::gnss::common::ThreadBlocker mThreadBlocker; // Guarded by mMutex static std::shared_ptr<IGnssMeasurementCallback> sCallback; diff --git a/gnss/aidl/default/GnssNavigationMessageInterface.cpp b/gnss/aidl/default/GnssNavigationMessageInterface.cpp index 4bc859d35f..75b962452a 100644 --- a/gnss/aidl/default/GnssNavigationMessageInterface.cpp +++ b/gnss/aidl/default/GnssNavigationMessageInterface.cpp @@ -32,7 +32,7 @@ std::shared_ptr<IGnssNavigationMessageCallback> GnssNavigationMessageInterface:: GnssNavigationMessageInterface::GnssNavigationMessageInterface() : mMinIntervalMillis(1000) {} GnssNavigationMessageInterface::~GnssNavigationMessageInterface() { - stop(); + waitForStoppingThreads(); } ndk::ScopedAStatus GnssNavigationMessageInterface::setCallback( @@ -46,7 +46,9 @@ ndk::ScopedAStatus GnssNavigationMessageInterface::setCallback( ndk::ScopedAStatus GnssNavigationMessageInterface::close() { ALOGD("close"); - stop(); + if (mIsActive) { + stop(); + } std::unique_lock<std::mutex> lock(mMutex); sCallback = nullptr; return ndk::ScopedAStatus::ok(); @@ -54,9 +56,20 @@ ndk::ScopedAStatus GnssNavigationMessageInterface::close() { void GnssNavigationMessageInterface::start() { ALOGD("start"); + + if (mIsActive) { + ALOGD("restarting since nav msg has started"); + stop(); + } + // Wait for stopping previous thread. + waitForStoppingThreads(); + mIsActive = true; mThread = std::thread([this]() { - while (mIsActive == true) { + do { + if (!mIsActive) { + break; + } GnssNavigationMessage message = { .svid = 19, .type = GnssNavigationMessageType::GPS_L1CA, @@ -66,15 +79,18 @@ void GnssNavigationMessageInterface::start() { .data = std::vector<uint8_t>(40, 0xF9), }; this->reportMessage(message); - std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMillis)); - } + } while (mIsActive && + mThreadBlocker.wait_for(std::chrono::milliseconds(mMinIntervalMillis))); }); - mThread.detach(); } void GnssNavigationMessageInterface::stop() { ALOGD("stop"); mIsActive = false; + mThreadBlocker.notify(); + if (mThread.joinable()) { + mFutures.push_back(std::async(std::launch::async, [this] { mThread.join(); })); + } } void GnssNavigationMessageInterface::reportMessage(const GnssNavigationMessage& message) { @@ -91,4 +107,13 @@ void GnssNavigationMessageInterface::reportMessage(const GnssNavigationMessage& callbackCopy->gnssNavigationMessageCb(message); } +void GnssNavigationMessageInterface::waitForStoppingThreads() { + for (auto& future : mFutures) { + ALOGD("Stopping previous thread."); + future.wait(); + ALOGD("Done stopping thread."); + } + mFutures.clear(); +} + } // namespace aidl::android::hardware::gnss diff --git a/gnss/aidl/default/GnssNavigationMessageInterface.h b/gnss/aidl/default/GnssNavigationMessageInterface.h index 600b23ab0a..b3353480f4 100644 --- a/gnss/aidl/default/GnssNavigationMessageInterface.h +++ b/gnss/aidl/default/GnssNavigationMessageInterface.h @@ -18,7 +18,9 @@ #include <aidl/android/hardware/gnss/BnGnssNavigationMessageInterface.h> #include <atomic> +#include <future> #include <thread> +#include "Utils.h" namespace aidl::android::hardware::gnss { @@ -34,10 +36,13 @@ struct GnssNavigationMessageInterface : public BnGnssNavigationMessageInterface void start(); void stop(); void reportMessage(const IGnssNavigationMessageCallback::GnssNavigationMessage& message); + void waitForStoppingThreads(); std::atomic<long> mMinIntervalMillis; std::atomic<bool> mIsActive; std::thread mThread; + std::vector<std::future<void>> mFutures; + ::android::hardware::gnss::common::ThreadBlocker mThreadBlocker; // Guarded by mMutex static std::shared_ptr<IGnssNavigationMessageCallback> sCallback; diff --git a/gnss/aidl/vts/GnssCallbackAidl.cpp b/gnss/aidl/vts/GnssCallbackAidl.cpp index 77a2506820..2f6128b6d2 100644 --- a/gnss/aidl/vts/GnssCallbackAidl.cpp +++ b/gnss/aidl/vts/GnssCallbackAidl.cpp @@ -31,7 +31,7 @@ Status GnssCallbackAidl::gnssSetCapabilitiesCb(const int capabilities) { } Status GnssCallbackAidl::gnssStatusCb(const GnssStatusValue /* status */) { - ALOGI("gnssSvStatusCb"); + ALOGI("gnssStatusCb"); return Status::ok(); } @@ -47,7 +47,8 @@ Status GnssCallbackAidl::gnssLocationCb(const GnssLocation& location) { return Status::ok(); } -Status GnssCallbackAidl::gnssNmeaCb(const int64_t /* timestamp */, const std::string& /* nmea */) { +Status GnssCallbackAidl::gnssNmeaCb(const int64_t timestamp, const std::string& nmea) { + nmea_cbq_.store(std::make_pair(timestamp, nmea)); return Status::ok(); } diff --git a/gnss/aidl/vts/GnssCallbackAidl.h b/gnss/aidl/vts/GnssCallbackAidl.h index 209728df7f..a9495ba3c2 100644 --- a/gnss/aidl/vts/GnssCallbackAidl.h +++ b/gnss/aidl/vts/GnssCallbackAidl.h @@ -17,6 +17,7 @@ #pragma once #include <android/hardware/gnss/BnGnssCallback.h> +#include <utility> #include "GnssCallbackEventQueue.h" /* Callback class for data & Event. */ @@ -26,7 +27,8 @@ class GnssCallbackAidl : public android::hardware::gnss::BnGnssCallback { : capabilities_cbq_("capabilities"), info_cbq_("system_info"), location_cbq_("location"), - sv_info_list_cbq_("sv_info"){}; + sv_info_list_cbq_("sv_info"), + nmea_cbq_("nmea"){}; ~GnssCallbackAidl(){}; android::binder::Status gnssSetCapabilitiesCb(const int capabilities) override; @@ -55,4 +57,6 @@ class GnssCallbackAidl : public android::hardware::gnss::BnGnssCallback { android::hardware::gnss::common::GnssCallbackEventQueue< std::vector<android::hardware::gnss::IGnssCallback::GnssSvInfo>> sv_info_list_cbq_; + android::hardware::gnss::common::GnssCallbackEventQueue<std::pair<int64_t, std::string>> + nmea_cbq_; };
\ No newline at end of file diff --git a/gnss/aidl/vts/GnssMeasurementCallbackAidl.cpp b/gnss/aidl/vts/GnssMeasurementCallbackAidl.cpp index c4fad7fb35..a553954a97 100644 --- a/gnss/aidl/vts/GnssMeasurementCallbackAidl.cpp +++ b/gnss/aidl/vts/GnssMeasurementCallbackAidl.cpp @@ -24,12 +24,10 @@ using android::hardware::gnss::GnssData; android::binder::Status GnssMeasurementCallbackAidl::gnssMeasurementCb(const GnssData& gnssData) { ALOGI("gnssMeasurementCb"); - ALOGI("elapsedRealtime: flags = %d, timestampNs: %" PRId64 ", timeUncertaintyNs=%lf", + ALOGV("elapsedRealtime: flags = 0x%X, timestampNs: %" PRId64 ", timeUncertaintyNs=%lf", gnssData.elapsedRealtime.flags, gnssData.elapsedRealtime.timestampNs, gnssData.elapsedRealtime.timeUncertaintyNs); - for (const auto& measurement : gnssData.measurements) { - ALOGI("measurement.receivedSvTimeInNs=%" PRId64, measurement.receivedSvTimeInNs); - } + gnss_data_cbq_.store(gnssData); return android::binder::Status::ok(); } diff --git a/gnss/aidl/vts/gnss_hal_test.cpp b/gnss/aidl/vts/gnss_hal_test.cpp index f184f8132d..407ac0cad8 100644 --- a/gnss/aidl/vts/gnss_hal_test.cpp +++ b/gnss/aidl/vts/gnss_hal_test.cpp @@ -18,15 +18,50 @@ #include "gnss_hal_test.h" #include <hidl/ServiceManagement.h> +#include <algorithm> +#include <cmath> #include "Utils.h" +using android::hardware::gnss::GnssClock; using android::hardware::gnss::GnssConstellationType; +using android::hardware::gnss::GnssData; using android::hardware::gnss::GnssLocation; +using android::hardware::gnss::GnssMeasurement; using android::hardware::gnss::IGnss; using android::hardware::gnss::IGnssCallback; +using android::hardware::gnss::IGnssMeasurementInterface; using android::hardware::gnss::common::Utils; using GnssConstellationTypeV2_0 = android::hardware::gnss::V2_0::GnssConstellationType; +namespace { +// The difference between the mean of the received intervals and the requested interval should not +// be larger mInterval * ALLOWED_MEAN_ERROR_RATIO +constexpr double ALLOWED_MEAN_ERROR_RATIO = 0.25; + +// The standard deviation computed for the deltas should not be bigger +// than mInterval * ALLOWED_STDEV_ERROR_RATIO or MIN_STDEV_MS, whichever is higher. +constexpr double ALLOWED_STDEV_ERROR_RATIO = 0.50; +constexpr double MIN_STDEV_MS = 1000; + +double computeMean(std::vector<int>& deltas) { + long accumulator = 0; + for (auto& d : deltas) { + accumulator += d; + } + return accumulator / deltas.size(); +} + +double computeStdev(double mean, std::vector<int>& deltas) { + double accumulator = 0; + for (auto& d : deltas) { + double diff = d - mean; + accumulator += diff * diff; + } + return std::sqrt(accumulator / (deltas.size() - 1)); +} + +} // anonymous namespace + void GnssHalTest::SetUp() { // Get AIDL handle aidl_gnss_hal_ = android::waitForDeclaredService<IGnssAidl>(String16(GetParam().c_str())); @@ -97,20 +132,26 @@ void GnssHalTest::SetPositionMode(const int min_interval_msec, const bool low_po ASSERT_TRUE(status.isOk()); } -bool GnssHalTest::StartAndCheckFirstLocation(const int min_interval_msec, - const bool low_power_mode) { +bool GnssHalTest::StartAndCheckFirstLocation(const int min_interval_msec, const bool low_power_mode, + const bool start_sv_status, const bool start_nmea) { if (aidl_gnss_hal_->getInterfaceVersion() <= 1) { // Invoke the super method. return GnssHalTestTemplate<IGnss_V2_1>::StartAndCheckFirstLocation(min_interval_msec, low_power_mode); } - SetPositionMode(min_interval_msec, low_power_mode); + auto status = aidl_gnss_hal_->start(); EXPECT_TRUE(status.isOk()); - status = aidl_gnss_hal_->startSvStatus(); - EXPECT_TRUE(status.isOk()); + if (start_sv_status) { + status = aidl_gnss_hal_->startSvStatus(); + EXPECT_TRUE(status.isOk()); + } + if (start_nmea) { + status = aidl_gnss_hal_->startNmea(); + EXPECT_TRUE(status.isOk()); + } /* * GnssLocationProvider support of AGPS SUPL & XtraDownloader is not available in VTS, @@ -131,6 +172,12 @@ bool GnssHalTest::StartAndCheckFirstLocation(const int min_interval_msec, return false; } +bool GnssHalTest::StartAndCheckFirstLocation(const int min_interval_msec, + const bool low_power_mode) { + return StartAndCheckFirstLocation(min_interval_msec, low_power_mode, + /* start_sv_status= */ true, /* start_nmea= */ true); +} + void GnssHalTest::StopAndClearLocations() { ALOGD("StopAndClearLocations"); if (aidl_gnss_hal_->getInterfaceVersion() <= 1) { @@ -139,6 +186,8 @@ void GnssHalTest::StopAndClearLocations() { } auto status = aidl_gnss_hal_->stopSvStatus(); EXPECT_TRUE(status.isOk()); + status = aidl_gnss_hal_->stopNmea(); + EXPECT_TRUE(status.isOk()); status = aidl_gnss_hal_->stop(); EXPECT_TRUE(status.isOk()); @@ -153,7 +202,8 @@ void GnssHalTest::StopAndClearLocations() { aidl_gnss_cb_->location_cbq_.reset(); } -void GnssHalTest::StartAndCheckLocations(int count) { +void GnssHalTest::StartAndCheckLocations(const int count, const bool start_sv_status, + const bool start_nmea) { if (aidl_gnss_hal_->getInterfaceVersion() <= 1) { // Invoke the super method. return GnssHalTestTemplate<IGnss_V2_1>::StartAndCheckLocations(count); @@ -162,7 +212,8 @@ void GnssHalTest::StartAndCheckLocations(int count) { const int kLocationTimeoutSubsequentSec = 2; const bool kLowPowerMode = false; - EXPECT_TRUE(StartAndCheckFirstLocation(kMinIntervalMsec, kLowPowerMode)); + EXPECT_TRUE(StartAndCheckFirstLocation(kMinIntervalMsec, kLowPowerMode, start_sv_status, + start_nmea)); for (int i = 1; i < count; i++) { EXPECT_TRUE(aidl_gnss_cb_->location_cbq_.retrieve(aidl_gnss_cb_->last_location_, @@ -177,6 +228,10 @@ void GnssHalTest::StartAndCheckLocations(int count) { } } +void GnssHalTest::StartAndCheckLocations(const int count) { + StartAndCheckLocations(count, /* start_sv_status= */ true, /* start_nmea= */ true); +} + std::list<std::vector<IGnssCallback::GnssSvInfo>> GnssHalTest::convertToAidl( const std::list<hidl_vec<IGnssCallback_2_1::GnssSvInfo>>& sv_info_list) { std::list<std::vector<IGnssCallback::GnssSvInfo>> aidl_sv_info_list; @@ -313,3 +368,109 @@ GnssConstellationType GnssHalTest::startLocationAndGetNonGpsConstellation( return constellation_to_blocklist; } + +void GnssHalTest::checkGnssMeasurementClockFields(const GnssData& measurement) { + Utils::checkElapsedRealtime(measurement.elapsedRealtime); + ASSERT_TRUE(measurement.clock.gnssClockFlags >= 0 && + measurement.clock.gnssClockFlags <= + (GnssClock::HAS_LEAP_SECOND | GnssClock::HAS_TIME_UNCERTAINTY | + GnssClock::HAS_FULL_BIAS | GnssClock::HAS_BIAS | + GnssClock::HAS_BIAS_UNCERTAINTY | GnssClock::HAS_DRIFT | + GnssClock::HAS_DRIFT_UNCERTAINTY)); +} + +void GnssHalTest::checkGnssMeasurementFlags(const GnssMeasurement& measurement) { + ASSERT_TRUE(measurement.flags >= 0 && + measurement.flags <= + (GnssMeasurement::HAS_SNR | GnssMeasurement::HAS_CARRIER_FREQUENCY | + GnssMeasurement::HAS_CARRIER_CYCLES | GnssMeasurement::HAS_CARRIER_PHASE | + GnssMeasurement::HAS_CARRIER_PHASE_UNCERTAINTY | + GnssMeasurement::HAS_AUTOMATIC_GAIN_CONTROL | + GnssMeasurement::HAS_FULL_ISB | GnssMeasurement::HAS_FULL_ISB_UNCERTAINTY | + GnssMeasurement::HAS_SATELLITE_ISB | + GnssMeasurement::HAS_SATELLITE_ISB_UNCERTAINTY | + GnssMeasurement::HAS_SATELLITE_PVT | + GnssMeasurement::HAS_CORRELATION_VECTOR)); +} + +void GnssHalTest::checkGnssMeasurementFields(const GnssMeasurement& measurement, + const GnssData& data) { + checkGnssMeasurementFlags(measurement); + // Verify CodeType is valid. + ASSERT_NE(measurement.signalType.codeType, ""); + // Verify basebandCn0DbHz is valid. + ASSERT_TRUE(measurement.basebandCN0DbHz > 0.0 && measurement.basebandCN0DbHz <= 65.0); + + if (((measurement.flags & GnssMeasurement::HAS_FULL_ISB) > 0) && + ((measurement.flags & GnssMeasurement::HAS_FULL_ISB_UNCERTAINTY) > 0) && + ((measurement.flags & GnssMeasurement::HAS_SATELLITE_ISB) > 0) && + ((measurement.flags & GnssMeasurement::HAS_SATELLITE_ISB_UNCERTAINTY) > 0)) { + GnssConstellationType referenceConstellation = + data.clock.referenceSignalTypeForIsb.constellation; + double carrierFrequencyHz = data.clock.referenceSignalTypeForIsb.carrierFrequencyHz; + std::string codeType = data.clock.referenceSignalTypeForIsb.codeType; + + ASSERT_TRUE(referenceConstellation >= GnssConstellationType::UNKNOWN && + referenceConstellation <= GnssConstellationType::IRNSS); + ASSERT_TRUE(carrierFrequencyHz > 0); + ASSERT_NE(codeType, ""); + + ASSERT_TRUE(std::abs(measurement.fullInterSignalBiasNs) < 1.0e6); + ASSERT_TRUE(measurement.fullInterSignalBiasUncertaintyNs >= 0); + ASSERT_TRUE(std::abs(measurement.satelliteInterSignalBiasNs) < 1.0e6); + ASSERT_TRUE(measurement.satelliteInterSignalBiasUncertaintyNs >= 0); + } +} + +void GnssHalTest::startMeasurementWithInterval( + int intervalMs, const sp<IGnssMeasurementInterface>& iGnssMeasurement, + sp<GnssMeasurementCallbackAidl>& callback) { + ALOGD("Start requesting measurement at interval of %d millis.", intervalMs); + IGnssMeasurementInterface::Options options; + options.intervalMs = intervalMs; + auto status = iGnssMeasurement->setCallbackWithOptions(callback, options); + ASSERT_TRUE(status.isOk()); +} + +void GnssHalTest::collectMeasurementIntervals(const sp<GnssMeasurementCallbackAidl>& callback, + const int numMeasurementEvents, + const int timeoutSeconds, + std::vector<int>& deltasMs) { + int64_t lastElapsedRealtimeMillis = 0; + for (int i = 0; i < numMeasurementEvents; i++) { + GnssData lastGnssData; + ASSERT_TRUE(callback->gnss_data_cbq_.retrieve(lastGnssData, timeoutSeconds)); + EXPECT_EQ(callback->gnss_data_cbq_.calledCount(), i + 1); + ASSERT_TRUE(lastGnssData.measurements.size() > 0); + + // Validity check GnssData fields + checkGnssMeasurementClockFields(lastGnssData); + for (const auto& measurement : lastGnssData.measurements) { + checkGnssMeasurementFields(measurement, lastGnssData); + } + + long currentElapsedRealtimeMillis = lastGnssData.elapsedRealtime.timestampNs * 1e-6; + if (lastElapsedRealtimeMillis != 0) { + deltasMs.push_back(currentElapsedRealtimeMillis - lastElapsedRealtimeMillis); + } + lastElapsedRealtimeMillis = currentElapsedRealtimeMillis; + } +} + +void GnssHalTest::assertMeanAndStdev(int intervalMs, std::vector<int>& deltasMs) { + double mean = computeMean(deltasMs); + double stdev = computeStdev(mean, deltasMs); + EXPECT_TRUE(std::abs(mean - intervalMs) <= intervalMs * ALLOWED_MEAN_ERROR_RATIO) + << "Test failed, because the mean of intervals is " << mean + << " millis. The test requires that abs(" << mean << " - " << intervalMs + << ") <= " << intervalMs * ALLOWED_MEAN_ERROR_RATIO + << " millis, when the requested interval is " << intervalMs << " millis."; + + double maxStdev = std::max(MIN_STDEV_MS, intervalMs * ALLOWED_STDEV_ERROR_RATIO); + EXPECT_TRUE(stdev <= maxStdev) + << "Test failed, because the stdev of intervals is " << stdev + << " millis, which must be <= " << maxStdev + << " millis, when the requested interval is " << intervalMs << " millis."; + ALOGD("Mean of interval deltas in millis: %.1lf", mean); + ALOGD("Stdev of interval deltas in millis: %.1lf", stdev); +} diff --git a/gnss/aidl/vts/gnss_hal_test.h b/gnss/aidl/vts/gnss_hal_test.h index d479af3445..645fc824e0 100644 --- a/gnss/aidl/vts/gnss_hal_test.h +++ b/gnss/aidl/vts/gnss_hal_test.h @@ -25,6 +25,7 @@ #include <android/hardware/gnss/2.1/IGnss.h> #include "GnssBatchingCallback.h" #include "GnssCallbackAidl.h" +#include "GnssMeasurementCallbackAidl.h" #include "v2_1/gnss_hal_test_template.h" using IGnss_V2_1 = android::hardware::gnss::V2_1::IGnss; @@ -68,8 +69,11 @@ class GnssHalTest : public android::hardware::gnss::common::GnssHalTestTemplate< const bool check_speed); void SetPositionMode(const int min_interval_msec, const bool low_power_mode); bool StartAndCheckFirstLocation(const int min_interval_msec, const bool low_power_mode); + bool StartAndCheckFirstLocation(const int min_interval_msec, const bool low_power_mode, + const bool start_sv_status, const bool start_nmea); void StopAndClearLocations(); - void StartAndCheckLocations(int count); + void StartAndCheckLocations(const int count); + void StartAndCheckLocations(const int count, const bool start_sv_status, const bool start_nmea); android::hardware::gnss::GnssConstellationType startLocationAndGetNonGpsConstellation( const int locations_to_await, const int gnss_sv_info_list_timeout); @@ -85,6 +89,19 @@ class GnssHalTest : public android::hardware::gnss::common::GnssHalTestTemplate< sv_info_list, const int min_observations); + void checkGnssMeasurementClockFields(const android::hardware::gnss::GnssData& measurement); + void checkGnssMeasurementFlags(const android::hardware::gnss::GnssMeasurement& measurement); + void checkGnssMeasurementFields(const android::hardware::gnss::GnssMeasurement& measurement, + const android::hardware::gnss::GnssData& data); + void startMeasurementWithInterval( + int intervalMillis, + const sp<android::hardware::gnss::IGnssMeasurementInterface>& iMeasurement, + sp<GnssMeasurementCallbackAidl>& callback); + void collectMeasurementIntervals(const sp<GnssMeasurementCallbackAidl>& callback, + const int numMeasurementEvents, const int timeoutSeconds, + std::vector<int>& deltaMs); + void assertMeanAndStdev(int intervalMillis, std::vector<int>& deltasMillis); + sp<IGnssAidl> aidl_gnss_hal_; sp<GnssCallbackAidl> aidl_gnss_cb_; // Primary callback interface }; diff --git a/gnss/aidl/vts/gnss_hal_test_cases.cpp b/gnss/aidl/vts/gnss_hal_test_cases.cpp index 54946fb64f..f926c40884 100644 --- a/gnss/aidl/vts/gnss_hal_test_cases.cpp +++ b/gnss/aidl/vts/gnss_hal_test_cases.cpp @@ -28,7 +28,9 @@ #include <android/hardware/gnss/measurement_corrections/IMeasurementCorrectionsInterface.h> #include <android/hardware/gnss/visibility_control/IGnssVisibilityControl.h> #include <cutils/properties.h> +#include <utils/SystemClock.h> #include <cmath> +#include <utility> #include "AGnssCallbackAidl.h" #include "AGnssRilCallbackAidl.h" #include "GnssAntennaInfoCallbackAidl.h" @@ -376,58 +378,6 @@ void CheckSatellitePvt(const SatellitePvt& satellitePvt, const int interfaceVers } } -void CheckGnssMeasurementClockFields(const GnssData& measurement) { - Utils::checkElapsedRealtime(measurement.elapsedRealtime); - ASSERT_TRUE(measurement.clock.gnssClockFlags >= 0 && - measurement.clock.gnssClockFlags <= - (GnssClock::HAS_LEAP_SECOND | GnssClock::HAS_TIME_UNCERTAINTY | - GnssClock::HAS_FULL_BIAS | GnssClock::HAS_BIAS | - GnssClock::HAS_BIAS_UNCERTAINTY | GnssClock::HAS_DRIFT | - GnssClock::HAS_DRIFT_UNCERTAINTY)); -} - -void CheckGnssMeasurementFlags(const GnssMeasurement& measurement) { - ASSERT_TRUE(measurement.flags >= 0 && - measurement.flags <= - (GnssMeasurement::HAS_SNR | GnssMeasurement::HAS_CARRIER_FREQUENCY | - GnssMeasurement::HAS_CARRIER_CYCLES | GnssMeasurement::HAS_CARRIER_PHASE | - GnssMeasurement::HAS_CARRIER_PHASE_UNCERTAINTY | - GnssMeasurement::HAS_AUTOMATIC_GAIN_CONTROL | - GnssMeasurement::HAS_FULL_ISB | GnssMeasurement::HAS_FULL_ISB_UNCERTAINTY | - GnssMeasurement::HAS_SATELLITE_ISB | - GnssMeasurement::HAS_SATELLITE_ISB_UNCERTAINTY | - GnssMeasurement::HAS_SATELLITE_PVT | - GnssMeasurement::HAS_CORRELATION_VECTOR)); -} - -void CheckGnssMeasurementFields(const GnssMeasurement& measurement, const GnssData& data) { - CheckGnssMeasurementFlags(measurement); - // Verify CodeType is valid. - ASSERT_NE(measurement.signalType.codeType, ""); - // Verify basebandCn0DbHz is valid. - ASSERT_TRUE(measurement.basebandCN0DbHz > 0.0 && measurement.basebandCN0DbHz <= 65.0); - - if (((measurement.flags & GnssMeasurement::HAS_FULL_ISB) > 0) && - ((measurement.flags & GnssMeasurement::HAS_FULL_ISB_UNCERTAINTY) > 0) && - ((measurement.flags & GnssMeasurement::HAS_SATELLITE_ISB) > 0) && - ((measurement.flags & GnssMeasurement::HAS_SATELLITE_ISB_UNCERTAINTY) > 0)) { - GnssConstellationType referenceConstellation = - data.clock.referenceSignalTypeForIsb.constellation; - double carrierFrequencyHz = data.clock.referenceSignalTypeForIsb.carrierFrequencyHz; - std::string codeType = data.clock.referenceSignalTypeForIsb.codeType; - - ASSERT_TRUE(referenceConstellation >= GnssConstellationType::UNKNOWN && - referenceConstellation <= GnssConstellationType::IRNSS); - ASSERT_TRUE(carrierFrequencyHz > 0); - ASSERT_NE(codeType, ""); - - ASSERT_TRUE(std::abs(measurement.fullInterSignalBiasNs) < 1.0e6); - ASSERT_TRUE(measurement.fullInterSignalBiasUncertaintyNs >= 0); - ASSERT_TRUE(std::abs(measurement.satelliteInterSignalBiasNs) < 1.0e6); - ASSERT_TRUE(measurement.satelliteInterSignalBiasUncertaintyNs >= 0); - } -} - /* * TestGnssMeasurementExtensionAndSatellitePvt: * 1. Gets the GnssMeasurementExtension and verifies that it returns a non-null extension. @@ -465,10 +415,10 @@ TEST_P(GnssHalTest, TestGnssMeasurementExtensionAndSatellitePvt) { ASSERT_TRUE(lastMeasurement.measurements.size() > 0); // Validity check GnssData fields - CheckGnssMeasurementClockFields(lastMeasurement); + checkGnssMeasurementClockFields(lastMeasurement); for (const auto& measurement : lastMeasurement.measurements) { - CheckGnssMeasurementFields(measurement, lastMeasurement); + checkGnssMeasurementFields(measurement, lastMeasurement); if (measurement.flags & GnssMeasurement::HAS_SATELLITE_PVT && kIsSatellitePvtSupported == true) { ALOGD("Found a measurement with SatellitePvt"); @@ -525,10 +475,10 @@ TEST_P(GnssHalTest, TestCorrelationVector) { ASSERT_TRUE(lastMeasurement.measurements.size() > 0); // Validity check GnssData fields - CheckGnssMeasurementClockFields(lastMeasurement); + checkGnssMeasurementClockFields(lastMeasurement); for (const auto& measurement : lastMeasurement.measurements) { - CheckGnssMeasurementFields(measurement, lastMeasurement); + checkGnssMeasurementFields(measurement, lastMeasurement); if (measurement.flags & GnssMeasurement::HAS_CORRELATION_VECTOR) { correlationVectorFound = true; ASSERT_TRUE(measurement.correlationVectors.size() > 0); @@ -1242,48 +1192,6 @@ TEST_P(GnssHalTest, TestGnssVisibilityControlExtension) { } /* - * TestGnssMeasurementSetCallbackWithOptions: - * 1. Gets the GnssMeasurementExtension and verifies that it returns a non-null extension. - * 2. Sets a GnssMeasurementCallback with intervalMillis option, waits for measurements reported, - * and verifies mandatory fields are valid. - */ -TEST_P(GnssHalTest, TestGnssMeasurementSetCallbackWithOptions) { - if (aidl_gnss_hal_->getInterfaceVersion() <= 1) { - return; - } - const int kFirstGnssMeasurementTimeoutSeconds = 10; - const int kNumMeasurementEvents = 5; - - sp<IGnssMeasurementInterface> iGnssMeasurement; - auto status = aidl_gnss_hal_->getExtensionGnssMeasurement(&iGnssMeasurement); - ASSERT_TRUE(status.isOk()); - ASSERT_TRUE(iGnssMeasurement != nullptr); - - auto callback = sp<GnssMeasurementCallbackAidl>::make(); - IGnssMeasurementInterface::Options options; - options.intervalMs = 2000; - status = iGnssMeasurement->setCallbackWithOptions(callback, options); - ASSERT_TRUE(status.isOk()); - - for (int i = 0; i < kNumMeasurementEvents; i++) { - GnssData lastMeasurement; - ASSERT_TRUE(callback->gnss_data_cbq_.retrieve(lastMeasurement, - kFirstGnssMeasurementTimeoutSeconds)); - EXPECT_EQ(callback->gnss_data_cbq_.calledCount(), i + 1); - ASSERT_TRUE(lastMeasurement.measurements.size() > 0); - - // Validity check GnssData fields - CheckGnssMeasurementClockFields(lastMeasurement); - for (const auto& measurement : lastMeasurement.measurements) { - CheckGnssMeasurementFields(measurement, lastMeasurement); - } - } - - status = iGnssMeasurement->close(); - ASSERT_TRUE(status.isOk()); -} - -/* * TestGnssAgcInGnssMeasurement: * 1. Gets the GnssMeasurementExtension and verifies that it returns a non-null extension. * 2. Sets a GnssMeasurementCallback, waits for a measurement. @@ -1293,7 +1201,7 @@ TEST_P(GnssHalTest, TestGnssAgcInGnssMeasurement) { return; } const int kFirstGnssMeasurementTimeoutSeconds = 10; - const int kNumMeasurementEvents = 15; + const int kNumMeasurementEvents = 5; sp<IGnssMeasurementInterface> iGnssMeasurement; auto status = aidl_gnss_hal_->getExtensionGnssMeasurement(&iGnssMeasurement); @@ -1313,7 +1221,7 @@ TEST_P(GnssHalTest, TestGnssAgcInGnssMeasurement) { ASSERT_TRUE(lastMeasurement.measurements.size() > 0); // Validity check GnssData fields - CheckGnssMeasurementClockFields(lastMeasurement); + checkGnssMeasurementClockFields(lastMeasurement); ASSERT_TRUE(lastMeasurement.gnssAgcs.size() > 0); for (const auto& gnssAgc : lastMeasurement.gnssAgcs) { @@ -1444,3 +1352,143 @@ TEST_P(GnssHalTest, TestGnssMeasurementCorrections) { Utils::getMockMeasurementCorrections_aidl()); ASSERT_TRUE(status.isOk()); } + +/* + * TestStopSvStatusAndNmea: + * 1. Call stopSvStatus and stopNmea. + * 2. Start location and verify that + * - no SvStatus is received. + * - no Nmea is received. + */ +TEST_P(GnssHalTest, TestStopSvStatusAndNmea) { + if (aidl_gnss_hal_->getInterfaceVersion() <= 1) { + return; + } + auto status = aidl_gnss_hal_->stopSvStatus(); + EXPECT_TRUE(status.isOk()); + status = aidl_gnss_hal_->stopNmea(); + EXPECT_TRUE(status.isOk()); + + int kLocationsToAwait = 5; + aidl_gnss_cb_->location_cbq_.reset(); + aidl_gnss_cb_->sv_info_list_cbq_.reset(); + aidl_gnss_cb_->nmea_cbq_.reset(); + StartAndCheckLocations(/* count= */ kLocationsToAwait, + /* start_sv_status= */ false, /* start_nmea= */ false); + int location_called_count = aidl_gnss_cb_->location_cbq_.calledCount(); + ALOGD("Observed %d GnssSvStatus, and %d Nmea while awaiting %d locations (%d received)", + aidl_gnss_cb_->sv_info_list_cbq_.size(), aidl_gnss_cb_->nmea_cbq_.size(), + kLocationsToAwait, location_called_count); + + // Ensure that no SvStatus & no Nmea is received. + EXPECT_EQ(aidl_gnss_cb_->sv_info_list_cbq_.size(), 0); + EXPECT_EQ(aidl_gnss_cb_->nmea_cbq_.size(), 0); + + StopAndClearLocations(); +} + +/* + * TestGnssMeasurementIntervals_WithoutLocation: + * 1. start measurement with interval + * 2. verify that the received measurement intervals have expected mean and stdev + */ +TEST_P(GnssHalTest, TestGnssMeasurementIntervals_WithoutLocation) { + if (aidl_gnss_hal_->getInterfaceVersion() <= 1) { + return; + } + + std::vector<int> intervals({2000, 4000}); + std::vector<int> numEvents({10, 5}); + + sp<IGnssMeasurementInterface> iGnssMeasurement; + auto status = aidl_gnss_hal_->getExtensionGnssMeasurement(&iGnssMeasurement); + ASSERT_TRUE(status.isOk()); + ASSERT_TRUE(iGnssMeasurement != nullptr); + + ALOGD("TestGnssMeasurementIntervals_WithoutLocation"); + for (int i = 0; i < intervals.size(); i++) { + auto callback = sp<GnssMeasurementCallbackAidl>::make(); + startMeasurementWithInterval(intervals[i], iGnssMeasurement, callback); + + std::vector<int> deltas; + collectMeasurementIntervals(callback, numEvents[i], /* timeoutSeconds= */ 10, deltas); + + status = iGnssMeasurement->close(); + ASSERT_TRUE(status.isOk()); + + assertMeanAndStdev(intervals[i], deltas); + } +} + +/* + * TestGnssMeasurementIntervals_LocationOnBeforeMeasurement: + * 1. start measurement with interval + * 2. verify that the received measurement intervals have expected mean and stdev + */ +TEST_P(GnssHalTest, TestGnssMeasurementIntervals_LocationOnBeforeMeasurement) { + if (aidl_gnss_hal_->getInterfaceVersion() <= 1) { + return; + } + + std::vector<int> intervals({2000}); + + sp<IGnssMeasurementInterface> iGnssMeasurement; + auto status = aidl_gnss_hal_->getExtensionGnssMeasurement(&iGnssMeasurement); + ASSERT_TRUE(status.isOk()); + ASSERT_TRUE(iGnssMeasurement != nullptr); + + int locationIntervalMs = 1000; + + // Start location first and then start measurement + ALOGD("TestGnssMeasurementIntervals_LocationOnBeforeMeasurement"); + StartAndCheckFirstLocation(locationIntervalMs, /* lowPowerMode= */ false); + for (auto& intervalMs : intervals) { + auto callback = sp<GnssMeasurementCallbackAidl>::make(); + startMeasurementWithInterval(intervalMs, iGnssMeasurement, callback); + + std::vector<int> deltas; + collectMeasurementIntervals(callback, /*numEvents=*/10, /*timeoutSeconds=*/10, deltas); + + status = iGnssMeasurement->close(); + ASSERT_TRUE(status.isOk()); + + assertMeanAndStdev(locationIntervalMs, deltas); + } + StopAndClearLocations(); +} + +/* + * TestGnssMeasurementIntervals: + * 1. start measurement with interval + * 2. verify that the received measurement intervals have expected mean and stdev + */ +TEST_P(GnssHalTest, TestGnssMeasurementIntervals_LocationOnAfterMeasurement) { + if (aidl_gnss_hal_->getInterfaceVersion() <= 1) { + return; + } + + std::vector<int> intervals({2000}); + + sp<IGnssMeasurementInterface> iGnssMeasurement; + auto status = aidl_gnss_hal_->getExtensionGnssMeasurement(&iGnssMeasurement); + ASSERT_TRUE(status.isOk()); + ASSERT_TRUE(iGnssMeasurement != nullptr); + + int locationIntervalMs = 1000; + // Start location first and then start measurement + ALOGD("TestGnssMeasurementIntervals_LocationOnAfterMeasurement"); + for (auto& intervalMs : intervals) { + auto callback = sp<GnssMeasurementCallbackAidl>::make(); + startMeasurementWithInterval(intervalMs, iGnssMeasurement, callback); + + StartAndCheckFirstLocation(locationIntervalMs, /* lowPowerMode= */ false); + std::vector<int> deltas; + collectMeasurementIntervals(callback, /*numEvents=*/10, /*timeoutSeconds=*/10, deltas); + + StopAndClearLocations(); + status = iGnssMeasurement->close(); + ASSERT_TRUE(status.isOk()); + + assertMeanAndStdev(locationIntervalMs, deltas); + } +} diff --git a/gnss/common/utils/default/include/Utils.h b/gnss/common/utils/default/include/Utils.h index 7065a6fb00..ad8f539248 100644 --- a/gnss/common/utils/default/include/Utils.h +++ b/gnss/common/utils/default/include/Utils.h @@ -56,6 +56,31 @@ struct Utils { static hidl_vec<V2_1::IGnssAntennaInfoCallback::GnssAntennaInfo> getMockAntennaInfos(); }; +struct ThreadBlocker { + // returns false if unblocked: + template <class R, class P> + bool wait_for(std::chrono::duration<R, P> const& time) { + std::unique_lock<std::mutex> lock(m); + return !cv.wait_for(lock, time, [&] { return terminate; }); + } + + void notify() { + std::unique_lock<std::mutex> lock(m); + terminate = true; + cv.notify_all(); + } + + void reset() { + std::unique_lock<std::mutex> lock(m); + terminate = false; + } + + private: + std::condition_variable cv; + std::mutex m; + bool terminate = false; +}; + } // namespace common } // namespace gnss } // namespace hardware |