Add TestGnssMeasurementCodeType VTS test
- add default implementation to mock reporting measurements.
Bug: 120277977
Fixes: 120277977
Test: atest VtsHalGnssV2_0TargetTest
Change-Id: I881f105874a992327551ef616860d7bd61e4bf83
diff --git a/gnss/2.0/default/Gnss.cpp b/gnss/2.0/default/Gnss.cpp
index 7f1ef9b..886a3a8 100644
--- a/gnss/2.0/default/Gnss.cpp
+++ b/gnss/2.0/default/Gnss.cpp
@@ -19,6 +19,7 @@
#include "Gnss.h"
#include <log/log.h>
#include "AGnssRil.h"
+#include "GnssMeasurement.h"
namespace android {
namespace hardware {
@@ -93,8 +94,8 @@
}
Return<sp<V1_0::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement() {
- // TODO implement
- return sp<V1_0::IGnssMeasurement>{};
+ // Not supported
+ return nullptr;
}
Return<sp<V1_0::IGnssNavigationMessage>> Gnss::getExtensionGnssNavigationMessage() {
@@ -132,7 +133,7 @@
sGnssCallback_1_1 = callback;
- uint32_t capabilities = 0x0;
+ uint32_t capabilities = (uint32_t)V1_0::IGnssCallback::Capabilities::MEASUREMENTS;
auto ret = sGnssCallback_1_1->gnssSetCapabilitesCb(capabilities);
if (!ret.isOk()) {
ALOGE("%s: Unable to invoke callback", __func__);
@@ -167,8 +168,8 @@
}
Return<sp<V1_1::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_1_1() {
- // TODO implement
- return sp<V1_1::IGnssMeasurement>{};
+ ALOGD("Gnss::getExtensionGnssMeasurement_1_1");
+ return new GnssMeasurement();
}
Return<bool> Gnss::injectBestLocation(const V1_0::GnssLocation&) {
@@ -182,8 +183,8 @@
}
Return<sp<V2_0::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_2_0() {
- // TODO implement
- return sp<V2_0::IGnssMeasurement>{};
+ ALOGD("Gnss::getExtensionGnssMeasurement_2_0");
+ return new GnssMeasurement();
}
Return<sp<measurement_corrections::V1_0::IMeasurementCorrections>>
diff --git a/gnss/2.0/default/GnssMeasurement.cpp b/gnss/2.0/default/GnssMeasurement.cpp
index fbcdc12..dc23db3 100644
--- a/gnss/2.0/default/GnssMeasurement.cpp
+++ b/gnss/2.0/default/GnssMeasurement.cpp
@@ -13,8 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#define LOG_TAG "GnssMeasurement"
#include "GnssMeasurement.h"
+#include <log/log.h>
namespace android {
namespace hardware {
@@ -22,6 +24,18 @@
namespace V2_0 {
namespace implementation {
+using GnssConstellationType = V1_0::GnssConstellationType;
+using GnssMeasurementFlags = V1_0::IGnssMeasurementCallback::GnssMeasurementFlags;
+using GnssMeasurementState = V1_0::IGnssMeasurementCallback::GnssMeasurementState;
+
+sp<V2_0::IGnssMeasurementCallback> GnssMeasurement::sCallback = nullptr;
+
+GnssMeasurement::GnssMeasurement() : mMinIntervalMillis(1000) {}
+
+GnssMeasurement::~GnssMeasurement() {
+ stop();
+}
+
// Methods from V1_0::IGnssMeasurement follow.
Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback(
const sp<V1_0::IGnssMeasurementCallback>&) {
@@ -30,7 +44,9 @@
}
Return<void> GnssMeasurement::close() {
- // TODO implement
+ std::unique_lock<std::mutex> lock(mMutex);
+ stop();
+ sCallback = nullptr;
return Void();
}
@@ -43,17 +59,89 @@
// Methods from V2_0::IGnssMeasurement follow.
Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback_2_0(
- const sp<V2_0::IGnssMeasurementCallback>&, bool) {
- // TODO implement
- return V1_0::IGnssMeasurement::GnssMeasurementStatus{};
+ const sp<V2_0::IGnssMeasurementCallback>& callback, bool) {
+ std::unique_lock<std::mutex> lock(mMutex);
+ sCallback = callback;
+
+ if (mIsActive) {
+ ALOGW("GnssMeasurement callback already set. Resetting the callback...");
+ stop();
+ }
+ start();
+
+ return V1_0::IGnssMeasurement::GnssMeasurementStatus::SUCCESS;
}
-// Methods from ::android::hidl::base::V1_0::IBase follow.
+void GnssMeasurement::start() {
+ mIsActive = true;
+ mThread = std::thread([this]() {
+ while (mIsActive == true) {
+ auto measurement = this->getMockMeasurement();
+ this->reportMeasurement(measurement);
-// IGnssMeasurement* HIDL_FETCH_IGnssMeasurement(const char* /* name */) {
-// return new GnssMeasurement();
-//}
-//
+ std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMillis));
+ }
+ });
+}
+
+void GnssMeasurement::stop() {
+ mIsActive = false;
+ if (mThread.joinable()) {
+ mThread.join();
+ }
+}
+
+GnssData GnssMeasurement::getMockMeasurement() {
+ V1_0::IGnssMeasurementCallback::GnssMeasurement measurement_1_0 = {
+ .flags = (uint32_t)GnssMeasurementFlags::HAS_CARRIER_FREQUENCY,
+ .svid = (int16_t)6,
+ .constellation = GnssConstellationType::GLONASS,
+ .timeOffsetNs = 0.0,
+ .state = GnssMeasurementState::STATE_CODE_LOCK | GnssMeasurementState::STATE_BIT_SYNC |
+ GnssMeasurementState::STATE_SUBFRAME_SYNC |
+ GnssMeasurementState::STATE_TOW_DECODED |
+ GnssMeasurementState::STATE_GLO_STRING_SYNC |
+ GnssMeasurementState::STATE_GLO_TOD_DECODED,
+ .receivedSvTimeInNs = 8195997131077,
+ .receivedSvTimeUncertaintyInNs = 15,
+ .cN0DbHz = 30.0,
+ .pseudorangeRateMps = -484.13739013671875,
+ .pseudorangeRateUncertaintyMps = 1.0379999876022339,
+ .accumulatedDeltaRangeState = (uint32_t)
+ V1_0::IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_UNKNOWN,
+ .accumulatedDeltaRangeM = 0.0,
+ .accumulatedDeltaRangeUncertaintyM = 0.0,
+ .carrierFrequencyHz = 1.59975e+09,
+ .multipathIndicator =
+ V1_0::IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_UNKNOWN};
+ V1_1::IGnssMeasurementCallback::GnssMeasurement measurement_1_1 = {.v1_0 = measurement_1_0};
+ V2_0::IGnssMeasurementCallback::GnssMeasurement measurement_2_0 = {
+ .v1_1 = measurement_1_1,
+ .codeType = IGnssMeasurementCallback::GnssMeasurementCodeType::CODE_TYPE_C};
+
+ hidl_vec<IGnssMeasurementCallback::GnssMeasurement> measurements(1);
+ measurements[0] = measurement_2_0;
+ V1_0::IGnssMeasurementCallback::GnssClock clock = {.timeNs = 2713545000000,
+ .fullBiasNs = -1226701900521857520,
+ .biasNs = 0.59689998626708984,
+ .biasUncertaintyNs = 47514.989972114563,
+ .driftNsps = -51.757811607455452,
+ .driftUncertaintyNsps = 310.64968328491528,
+ .hwClockDiscontinuityCount = 1};
+ GnssData gnssData = {.measurements = measurements, .clock = clock};
+ return gnssData;
+}
+
+void GnssMeasurement::reportMeasurement(const GnssData& data) {
+ ALOGD("reportMeasurement()");
+ std::unique_lock<std::mutex> lock(mMutex);
+ if (sCallback == nullptr) {
+ ALOGE("%s: GnssMeasurement::sCallback is null.", __func__);
+ return;
+ }
+ sCallback->gnssMeasurementCb_2_0(data);
+}
+
} // namespace implementation
} // namespace V2_0
} // namespace gnss
diff --git a/gnss/2.0/default/GnssMeasurement.h b/gnss/2.0/default/GnssMeasurement.h
index 8c621bb..c24c00e 100644
--- a/gnss/2.0/default/GnssMeasurement.h
+++ b/gnss/2.0/default/GnssMeasurement.h
@@ -20,6 +20,9 @@
#include <android/hardware/gnss/2.0/IGnssMeasurement.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>
+#include <atomic>
+#include <mutex>
+#include <thread>
namespace android {
namespace hardware {
@@ -35,7 +38,11 @@
using ::android::hardware::Return;
using ::android::hardware::Void;
+using GnssData = V2_0::IGnssMeasurementCallback::GnssData;
+
struct GnssMeasurement : public IGnssMeasurement {
+ GnssMeasurement();
+ ~GnssMeasurement();
// Methods from V1_0::IGnssMeasurement follow.
Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> setCallback(
const sp<V1_0::IGnssMeasurementCallback>& callback) override;
@@ -48,6 +55,18 @@
// Methods from V2_0::IGnssMeasurement follow.
Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> setCallback_2_0(
const sp<V2_0::IGnssMeasurementCallback>& callback, bool enableFullTracking) override;
+
+ private:
+ void start();
+ void stop();
+ GnssData getMockMeasurement();
+ void reportMeasurement(const GnssData&);
+
+ static sp<IGnssMeasurementCallback> sCallback;
+ std::atomic<long> mMinIntervalMillis;
+ std::atomic<bool> mIsActive;
+ std::thread mThread;
+ mutable std::mutex mMutex;
};
} // namespace implementation
diff --git a/gnss/2.0/vts/functional/gnss_hal_test.cpp b/gnss/2.0/vts/functional/gnss_hal_test.cpp
index d7101a0..3a48c9e 100644
--- a/gnss/2.0/vts/functional/gnss_hal_test.cpp
+++ b/gnss/2.0/vts/functional/gnss_hal_test.cpp
@@ -38,6 +38,13 @@
}
void GnssHalTest::TearDown() {
+ // Reset counters
+ info_called_count_ = 0;
+ capabilities_called_count_ = 0;
+ location_called_count_ = 0;
+ name_called_count_ = 0;
+ measurement_called_count_ = 0;
+
if (gnss_hal_ != nullptr) {
gnss_hal_->cleanup();
}
@@ -127,3 +134,12 @@
parent_.list_gnss_sv_status_.emplace_back(svStatus);
return Void();
}
+
+Return<void> GnssHalTest::GnssMeasurementCallback::gnssMeasurementCb_2_0(
+ const IGnssMeasurementCallback_2_0::GnssData& data) {
+ ALOGD("GnssMeasurement received. Size = %d", (int)data.measurements.size());
+ parent_.measurement_called_count_++;
+ parent_.last_measurement_ = data;
+ parent_.notify();
+ return Void();
+}
diff --git a/gnss/2.0/vts/functional/gnss_hal_test.h b/gnss/2.0/vts/functional/gnss_hal_test.h
index 64f3575..5649b45 100644
--- a/gnss/2.0/vts/functional/gnss_hal_test.h
+++ b/gnss/2.0/vts/functional/gnss_hal_test.h
@@ -34,6 +34,9 @@
using android::hardware::gnss::V1_0::GnssLocationFlags;
using android::hardware::gnss::V1_1::IGnssCallback;
using android::hardware::gnss::V2_0::IGnss;
+using IGnssMeasurementCallback_1_0 = android::hardware::gnss::V1_0::IGnssMeasurementCallback;
+using IGnssMeasurementCallback_1_1 = android::hardware::gnss::V1_1::IGnssMeasurementCallback;
+using IGnssMeasurementCallback_2_0 = android::hardware::gnss::V2_0::IGnssMeasurementCallback;
using android::sp;
@@ -100,6 +103,27 @@
Return<void> gnssSvStatusCb(const IGnssCallback::GnssSvStatus& svStatus) override;
};
+ /* Callback class for GnssMeasurement. */
+ class GnssMeasurementCallback : public IGnssMeasurementCallback_2_0 {
+ public:
+ GnssHalTest& parent_;
+ GnssMeasurementCallback(GnssHalTest& parent) : parent_(parent){};
+ virtual ~GnssMeasurementCallback() = default;
+
+ // Methods from V1_0::IGnssMeasurementCallback follow.
+ Return<void> GnssMeasurementCb(const IGnssMeasurementCallback_1_0::GnssData&) override {
+ return Void();
+ }
+
+ // Methods from V1_1::IGnssMeasurementCallback follow.
+ Return<void> gnssMeasurementCb(const IGnssMeasurementCallback_1_1::GnssData&) override {
+ return Void();
+ }
+
+ // Methods from V2_0::IGnssMeasurementCallback follow.
+ Return<void> gnssMeasurementCb_2_0(const IGnssMeasurementCallback_2_0::GnssData&) override;
+ };
+
/*
* SetUpGnssCallback:
* Set GnssCallback and verify the result.
@@ -113,16 +137,19 @@
* test.)
*/
int info_called_count_;
- IGnssCallback::GnssSystemInfo last_info_;
- uint32_t last_capabilities_;
int capabilities_called_count_;
int location_called_count_;
- GnssLocation last_location_;
- list<IGnssCallback::GnssSvStatus> list_gnss_sv_status_;
-
+ int measurement_called_count_;
int name_called_count_;
+
+ IGnssCallback::GnssSystemInfo last_info_;
+ uint32_t last_capabilities_;
+ GnssLocation last_location_;
+ IGnssMeasurementCallback_2_0::GnssData last_measurement_;
android::hardware::hidl_string last_name_;
+ list<IGnssCallback::GnssSvStatus> list_gnss_sv_status_;
+
private:
std::mutex mtx_;
std::condition_variable cv_;
diff --git a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
index 478a4b2..c1f1393 100644
--- a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
@@ -21,9 +21,10 @@
using android::hardware::hidl_vec;
+using IAGnssRil_2_0 = android::hardware::gnss::V2_0::IAGnssRil;
using IGnssMeasurement_2_0 = android::hardware::gnss::V2_0::IGnssMeasurement;
using IGnssMeasurement_1_1 = android::hardware::gnss::V1_1::IGnssMeasurement;
-using IAGnssRil_2_0 = android::hardware::gnss::V2_0::IAGnssRil;
+using IGnssMeasurement_1_0 = android::hardware::gnss::V1_0::IGnssMeasurement;
/*
* SetupTeardownCreateCleanup:
@@ -40,12 +41,17 @@
TEST_F(GnssHalTest, TestGnssMeasurementCallback) {
auto gnssMeasurement_2_0 = gnss_hal_->getExtensionGnssMeasurement_2_0();
auto gnssMeasurement_1_1 = gnss_hal_->getExtensionGnssMeasurement_1_1();
- ASSERT_TRUE(gnssMeasurement_2_0.isOk() || gnssMeasurement_1_1.isOk());
+ auto gnssMeasurement_1_0 = gnss_hal_->getExtensionGnssMeasurement();
+ ASSERT_TRUE(gnssMeasurement_2_0.isOk() || gnssMeasurement_1_1.isOk() ||
+ gnssMeasurement_1_0.isOk());
if (last_capabilities_ & IGnssCallback::Capabilities::MEASUREMENTS) {
sp<IGnssMeasurement_2_0> iGnssMeas_2_0 = gnssMeasurement_2_0;
sp<IGnssMeasurement_1_1> iGnssMeas_1_1 = gnssMeasurement_1_1;
- // Exactly one interface is non-null.
- ASSERT_TRUE((iGnssMeas_1_1 != nullptr) != (iGnssMeas_2_0 != nullptr));
+ sp<IGnssMeasurement_1_0> iGnssMeas_1_0 = gnssMeasurement_1_0;
+ // At least one interface is non-null.
+ int numNonNull = (int)(iGnssMeas_2_0 != nullptr) + (int)(iGnssMeas_1_1 != nullptr) +
+ (int)(iGnssMeas_1_0 != nullptr);
+ ASSERT_TRUE(numNonNull >= 1);
}
}
@@ -90,3 +96,40 @@
ASSERT_TRUE(result.isOk());
EXPECT_TRUE(result);
}
+
+/*
+ * TestGnssMeasurementCodeType:
+ * Sets a GnssMeasurementCallback, waits for a measurement, and verifies the codeType is valid.
+ */
+TEST_F(GnssHalTest, TestGnssMeasurementCodeType) {
+ const int kFirstGnssMeasurementTimeoutSeconds = 10;
+
+ auto gnssMeasurement = gnss_hal_->getExtensionGnssMeasurement_2_0();
+ if (!gnssMeasurement.isOk()) {
+ return;
+ }
+
+ sp<IGnssMeasurement_2_0> iGnssMeasurement = gnssMeasurement;
+ if (iGnssMeasurement == nullptr) {
+ return;
+ }
+
+ sp<IGnssMeasurementCallback_2_0> callback = new GnssMeasurementCallback(*this);
+
+ auto result = iGnssMeasurement->setCallback_2_0(callback, /* enableFullTracking= */ true);
+ ASSERT_TRUE(result.isOk());
+ EXPECT_EQ(result, IGnssMeasurement_1_0::GnssMeasurementStatus::SUCCESS);
+
+ wait(kFirstGnssMeasurementTimeoutSeconds);
+ EXPECT_EQ(measurement_called_count_, 1);
+ ASSERT_TRUE(last_measurement_.measurements.size() > 0);
+ for (auto measurement : last_measurement_.measurements) {
+ ASSERT_TRUE(
+ (int)measurement.codeType >=
+ (int)IGnssMeasurementCallback_2_0::GnssMeasurementCodeType::CODE_TYPE_A &&
+ (int)measurement.codeType <=
+ (int)IGnssMeasurementCallback_2_0::GnssMeasurementCodeType::CODE_TYPE_CODELESS);
+ }
+
+ iGnssMeasurement->close();
+}