diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssData.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssData.aidl index 31426f0507..54e3b2165e 100644 --- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssData.aidl +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssData.aidl @@ -39,6 +39,7 @@ parcelable GnssData { android.hardware.gnss.GnssClock clock; android.hardware.gnss.ElapsedRealtime elapsedRealtime; android.hardware.gnss.GnssData.GnssAgc[] gnssAgcs = {}; + boolean isFullTracking; @VintfStability parcelable GnssAgc { double agcLevelDb; diff --git a/gnss/aidl/android/hardware/gnss/GnssData.aidl b/gnss/aidl/android/hardware/gnss/GnssData.aidl index 075a0391e2..492ba3113a 100644 --- a/gnss/aidl/android/hardware/gnss/GnssData.aidl +++ b/gnss/aidl/android/hardware/gnss/GnssData.aidl @@ -99,4 +99,15 @@ parcelable GnssData { * weak to be acquired, the AGC value must still be reported. */ GnssAgc[] gnssAgcs = {}; + + /** + * True indicates that the GNSS chipset switches off duty cycling. In such mode, no clock + * discontinuities are expected and, when supported, carrier phase should be continuous in good + * signal conditions. All non-blocklisted, healthy constellations, satellites and frequency + * bands must be tracked and reported in this mode. + * + * False indicates that the GNSS chipset optimizes power via duty cycling, constellations and + * frequency limits, etc. + */ + boolean isFullTracking; } diff --git a/gnss/aidl/default/Gnss.cpp b/gnss/aidl/default/Gnss.cpp index 8d3fc39fff..23d799919b 100644 --- a/gnss/aidl/default/Gnss.cpp +++ b/gnss/aidl/default/Gnss.cpp @@ -76,12 +76,12 @@ ScopedAStatus Gnss::setCallback(const std::shared_ptr& callback) } GnssSignalType signalType1 = { .constellation = GnssConstellationType::GPS, - .carrierFrequencyHz = 1.59975e+09, + .carrierFrequencyHz = 1.57542e+09, .codeType = GnssSignalType::CODE_TYPE_C, }; GnssSignalType signalType2 = { .constellation = GnssConstellationType::GLONASS, - .carrierFrequencyHz = 1.59975e+09, + .carrierFrequencyHz = 1.5980625e+09, .codeType = GnssSignalType::CODE_TYPE_C, }; status = sGnssCallback->gnssSetSignalTypeCapabilitiesCb( diff --git a/gnss/aidl/default/GnssMeasurementInterface.cpp b/gnss/aidl/default/GnssMeasurementInterface.cpp index 606de07367..90056ce617 100644 --- a/gnss/aidl/default/GnssMeasurementInterface.cpp +++ b/gnss/aidl/default/GnssMeasurementInterface.cpp @@ -54,7 +54,7 @@ ndk::ScopedAStatus GnssMeasurementInterface::setCallback( ALOGW("GnssMeasurement callback already set. Resetting the callback..."); stop(); } - start(enableCorrVecOutputs); + start(enableCorrVecOutputs, enableFullTracking); return ndk::ScopedAStatus::ok(); } @@ -73,7 +73,7 @@ ndk::ScopedAStatus GnssMeasurementInterface::setCallbackWithOptions( stop(); } mIntervalMs = std::max(options.intervalMs, 1000); - start(options.enableCorrVecOutputs); + start(options.enableCorrVecOutputs, options.enableFullTracking); return ndk::ScopedAStatus::ok(); } @@ -91,7 +91,8 @@ ndk::ScopedAStatus GnssMeasurementInterface::close() { return ndk::ScopedAStatus::ok(); } -void GnssMeasurementInterface::start(const bool enableCorrVecOutputs) { +void GnssMeasurementInterface::start(const bool enableCorrVecOutputs, + const bool enableFullTracking) { ALOGD("start"); if (mIsActive) { @@ -103,7 +104,7 @@ void GnssMeasurementInterface::start(const bool enableCorrVecOutputs) { mIsActive = true; mThreadBlocker.reset(); - mThread = std::thread([this, enableCorrVecOutputs]() { + mThread = std::thread([this, enableCorrVecOutputs, enableFullTracking]() { int intervalMs; do { if (!mIsActive) { @@ -122,7 +123,8 @@ void GnssMeasurementInterface::start(const bool enableCorrVecOutputs) { this->reportMeasurement(*measurement); } } else { - auto measurement = Utils::getMockMeasurement(enableCorrVecOutputs); + auto measurement = + Utils::getMockMeasurement(enableCorrVecOutputs, enableFullTracking); this->reportMeasurement(measurement); } intervalMs = diff --git a/gnss/aidl/default/GnssMeasurementInterface.h b/gnss/aidl/default/GnssMeasurementInterface.h index bb08027568..d2737e5206 100644 --- a/gnss/aidl/default/GnssMeasurementInterface.h +++ b/gnss/aidl/default/GnssMeasurementInterface.h @@ -41,7 +41,7 @@ struct GnssMeasurementInterface : public BnGnssMeasurementInterface { void setLocationEnabled(const bool enabled); private: - void start(const bool enableCorrVecOutputs); + void start(const bool enableCorrVecOutputs, const bool enableFullTracking); void stop(); void reportMeasurement(const GnssData&); void waitForStoppingThreads(); diff --git a/gnss/aidl/vts/GnssMeasurementCallbackAidl.cpp b/gnss/aidl/vts/GnssMeasurementCallbackAidl.cpp index a553954a97..0d15b2ad51 100644 --- a/gnss/aidl/vts/GnssMeasurementCallbackAidl.cpp +++ b/gnss/aidl/vts/GnssMeasurementCallbackAidl.cpp @@ -24,9 +24,11 @@ using android::hardware::gnss::GnssData; android::binder::Status GnssMeasurementCallbackAidl::gnssMeasurementCb(const GnssData& gnssData) { ALOGI("gnssMeasurementCb"); - ALOGV("elapsedRealtime: flags = 0x%X, timestampNs: %" PRId64 ", timeUncertaintyNs=%lf", + ALOGV("elapsedRealtime: flags = 0x%X, timestampNs: %" PRId64 + ", timeUncertaintyNs=%lf" + " isFullTracking=%s", gnssData.elapsedRealtime.flags, gnssData.elapsedRealtime.timestampNs, - gnssData.elapsedRealtime.timeUncertaintyNs); + gnssData.elapsedRealtime.timeUncertaintyNs, gnssData.isFullTracking ? "true" : "false"); 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 91cd9175bc..b4f2b773f3 100644 --- a/gnss/aidl/vts/gnss_hal_test.cpp +++ b/gnss/aidl/vts/gnss_hal_test.cpp @@ -477,6 +477,26 @@ void GnssHalTest::collectMeasurementIntervals(const sp& callback, + const int numMeasurementEvents, const int timeoutSeconds, + const bool isFullTracking) { + 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); + if (aidl_gnss_hal_->getInterfaceVersion() >= 3) { + EXPECT_EQ(lastGnssData.isFullTracking, isFullTracking); + } + for (const auto& measurement : lastGnssData.measurements) { + checkGnssMeasurementFields(measurement, lastGnssData); + } + } +} + void GnssHalTest::assertMeanAndStdev(int intervalMs, std::vector& deltasMs) { double mean = computeMean(deltasMs); double stdev = computeStdev(mean, deltasMs); diff --git a/gnss/aidl/vts/gnss_hal_test.h b/gnss/aidl/vts/gnss_hal_test.h index c49c1b9204..470294ca31 100644 --- a/gnss/aidl/vts/gnss_hal_test.h +++ b/gnss/aidl/vts/gnss_hal_test.h @@ -101,6 +101,9 @@ class GnssHalTest : public android::hardware::gnss::common::GnssHalTestTemplate< void collectMeasurementIntervals(const sp& callback, const int numMeasurementEvents, const int timeoutSeconds, std::vector& deltaMs); + void checkGnssDataFields(const sp& callback, + const int numMeasurementEvents, const int timeoutSeconds, + const bool isFullTracking); void assertMeanAndStdev(int intervalMillis, std::vector& deltasMillis); sp aidl_gnss_hal_; diff --git a/gnss/aidl/vts/gnss_hal_test_cases.cpp b/gnss/aidl/vts/gnss_hal_test_cases.cpp index 7c0a4df6d5..31cef150e3 100644 --- a/gnss/aidl/vts/gnss_hal_test_cases.cpp +++ b/gnss/aidl/vts/gnss_hal_test_cases.cpp @@ -173,6 +173,7 @@ TEST_P(GnssHalTest, InjectSeedLocation) { * GnssCapabilities: * 1. Verifies that GNSS hardware supports measurement capabilities. * 2. Verifies that GNSS hardware supports Scheduling capabilities. + * 3. Verifies that GNSS hardware supports non-empty signal type capabilities. */ TEST_P(GnssHalTest, GnssCapabilites) { if (aidl_gnss_hal_->getInterfaceVersion() <= 1) { @@ -182,6 +183,10 @@ TEST_P(GnssHalTest, GnssCapabilites) { EXPECT_TRUE(aidl_gnss_cb_->last_capabilities_ & IGnssCallback::CAPABILITY_MEASUREMENTS); } EXPECT_TRUE(aidl_gnss_cb_->last_capabilities_ & IGnssCallback::CAPABILITY_SCHEDULING); + if (aidl_gnss_hal_->getInterfaceVersion() <= 2) { + return; + } + EXPECT_FALSE(aidl_gnss_cb_->last_signal_type_capabilities.empty()); } /* @@ -1466,7 +1471,7 @@ TEST_P(GnssHalTest, TestGnssMeasurementIntervals_LocationOnBeforeMeasurement) { /* * TestGnssMeasurementIntervals: * 1. start measurement with interval - * 2. verify that the received measurement intervals have expected mean and stdev + * 2. verify that the received measurement intervals have expected mean and stddev */ TEST_P(GnssHalTest, TestGnssMeasurementIntervals_LocationOnAfterMeasurement) { if (aidl_gnss_hal_->getInterfaceVersion() <= 1) { @@ -1499,11 +1504,17 @@ TEST_P(GnssHalTest, TestGnssMeasurementIntervals_LocationOnAfterMeasurement) { } } +/* + * TestGnssMeasurementSetCallback + * 1. Start measurement with 20s interval. Expect the first measurement received in 10s. + * 2. Start measurement with 1s interval and wait for 5 measurements. + * 3. Verify the received measurement intervals have expected mean and stddev. + */ TEST_P(GnssHalTest, TestGnssMeasurementSetCallback) { if (aidl_gnss_hal_->getInterfaceVersion() <= 2) { return; } - + const int kFirstGnssMeasurementTimeoutSeconds = 10; sp iGnssMeasurement; auto status = aidl_gnss_hal_->getExtensionGnssMeasurement(&iGnssMeasurement); ASSERT_TRUE(status.isOk()); @@ -1515,12 +1526,14 @@ TEST_P(GnssHalTest, TestGnssMeasurementSetCallback) { // setCallback at 20s interval and wait for 1 measurement startMeasurementWithInterval(20000, iGnssMeasurement, callback); - collectMeasurementIntervals(callback, /* numEvents= */ 1, /* timeoutSeconds= */ 10, deltas); + collectMeasurementIntervals(callback, /* numEvents= */ 1, kFirstGnssMeasurementTimeoutSeconds, + deltas); // setCallback at 1s interval and wait for 5 measurements callback->gnss_data_cbq_.reset(); startMeasurementWithInterval(1000, iGnssMeasurement, callback); - collectMeasurementIntervals(callback, /* numEvents= */ 5, /* timeoutSeconds= */ 10, deltas); + collectMeasurementIntervals(callback, /* numEvents= */ 5, kFirstGnssMeasurementTimeoutSeconds, + deltas); // verify the measurements were received at 1Hz assertMeanAndStdev(1000, deltas); @@ -1528,3 +1541,43 @@ TEST_P(GnssHalTest, TestGnssMeasurementSetCallback) { status = iGnssMeasurement->close(); ASSERT_TRUE(status.isOk()); } + +/* + * TestGnssMeasurementIsFullTracking + * 1. Start measurement with enableFullTracking=true. Verify the received measurements have + * isFullTracking=true. + * 2. Start measurement with enableFullTracking = false. Verify the received measurements have + * isFullTracking=false. + * 3. Do step 1 again. + */ +TEST_P(GnssHalTest, TestGnssMeasurementIsFullTracking) { + // GnssData.isFullTracking is added in the interface version 3 + if (aidl_gnss_hal_->getInterfaceVersion() <= 2) { + return; + } + const int kFirstGnssMeasurementTimeoutSeconds = 10; + const int kNumMeasurementEvents = 5; + std::vector isFullTrackingList({true, false, true}); + + sp iGnssMeasurement; + auto status = aidl_gnss_hal_->getExtensionGnssMeasurement(&iGnssMeasurement); + ASSERT_TRUE(status.isOk()); + ASSERT_TRUE(iGnssMeasurement != nullptr); + + ALOGD("TestGnssMeasurementIsFullTracking"); + auto callback = sp::make(); + IGnssMeasurementInterface::Options options; + options.intervalMs = 1000; + + for (auto isFullTracking : isFullTrackingList) { + options.enableFullTracking = isFullTracking; + + callback->gnss_data_cbq_.reset(); + auto status = iGnssMeasurement->setCallbackWithOptions(callback, options); + checkGnssDataFields(callback, kNumMeasurementEvents, kFirstGnssMeasurementTimeoutSeconds, + isFullTracking); + } + + status = iGnssMeasurement->close(); + ASSERT_TRUE(status.isOk()); +} diff --git a/gnss/common/utils/default/Utils.cpp b/gnss/common/utils/default/Utils.cpp index 4de49f376c..ad351f82c9 100644 --- a/gnss/common/utils/default/Utils.cpp +++ b/gnss/common/utils/default/Utils.cpp @@ -147,7 +147,7 @@ GnssDataV2_0 Utils::getMockMeasurementV2_0() { return gnssData; } -GnssData Utils::getMockMeasurement(const bool enableCorrVecOutputs) { +GnssData Utils::getMockMeasurement(const bool enableCorrVecOutputs, const bool enableFullTracking) { aidl::android::hardware::gnss::GnssSignalType signalType = { .constellation = GnssConstellationType::GLONASS, .carrierFrequencyHz = 1.59975e+09, @@ -258,7 +258,8 @@ GnssData Utils::getMockMeasurement(const bool enableCorrVecOutputs) { GnssData gnssData = {.measurements = {measurement}, .clock = clock, .elapsedRealtime = timestamp, - .gnssAgcs = std::vector({gnssAgc1, gnssAgc2})}; + .gnssAgcs = std::vector({gnssAgc1, gnssAgc2}), + .isFullTracking = enableFullTracking}; return gnssData; } diff --git a/gnss/common/utils/default/include/Utils.h b/gnss/common/utils/default/include/Utils.h index ad8f539248..9be4a195d7 100644 --- a/gnss/common/utils/default/include/Utils.h +++ b/gnss/common/utils/default/include/Utils.h @@ -32,7 +32,7 @@ namespace common { struct Utils { static aidl::android::hardware::gnss::GnssData getMockMeasurement( - const bool enableCorrVecOutputs); + const bool enableCorrVecOutputs, const bool enableFullTracking); static V2_0::IGnssMeasurementCallback::GnssData getMockMeasurementV2_0(); static V2_1::IGnssMeasurementCallback::GnssData getMockMeasurementV2_1();