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 ebb5d0bdff..aa514da38c 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 @@ -37,4 +37,11 @@ parcelable GnssData { android.hardware.gnss.GnssMeasurement[] measurements; android.hardware.gnss.GnssClock clock; android.hardware.gnss.ElapsedRealtime elapsedRealtime; + @nullable android.hardware.gnss.GnssData.GnssAgc[] gnssAgcs; + @VintfStability + parcelable GnssAgc { + double agcLevelDb; + android.hardware.gnss.GnssConstellationType constellation = android.hardware.gnss.GnssConstellationType.UNKNOWN; + long carrierFrequencyHz; + } } diff --git a/gnss/aidl/android/hardware/gnss/GnssData.aidl b/gnss/aidl/android/hardware/gnss/GnssData.aidl index ed30c989f8..204eb65e6b 100644 --- a/gnss/aidl/android/hardware/gnss/GnssData.aidl +++ b/gnss/aidl/android/hardware/gnss/GnssData.aidl @@ -18,6 +18,7 @@ package android.hardware.gnss; import android.hardware.gnss.ElapsedRealtime; import android.hardware.gnss.GnssClock; +import android.hardware.gnss.GnssConstellationType; import android.hardware.gnss.GnssMeasurement; /** @@ -41,4 +42,55 @@ parcelable GnssData { * clock. */ ElapsedRealtime elapsedRealtime; -} \ No newline at end of file + + /** + * Represents a reading of GNSS AGC value of a constellation type and a frequency band. + */ + @VintfStability + parcelable GnssAgc { + /** + * Automatic gain control (AGC) level. AGC acts as a variable gain amplifier adjusting the + * power of the incoming signal. The AGC level may be used to indicate potential + * interference. Higher gain (and/or lower input power) must be output as a positive number. + * Hence in cases of strong jamming, in the band of this signal, this value must go more + * negative. This value must be consistent given the same level of the incoming signal + * power. + * + * Note: Different hardware designs (e.g. antenna, pre-amplification, or other RF HW + * components) may also affect the typical output of this value on any given hardware design + * in an open sky test - the important aspect of this output is that changes in this value + * are indicative of changes on input signal power in the frequency band for this + * measurement. + */ + double agcLevelDb; + + /** + * Constellation type of the SV that transmits the signal. + */ + GnssConstellationType constellation = GnssConstellationType.UNKNOWN; + + /** + * Carrier frequency of the signal tracked, for example it can be the + * GPS central frequency for L1 = 1575.45 MHz, or L2 = 1227.60 MHz, L5 = + * 1176.45 MHz, varying GLO channels, etc. If the field is not set, it + * is the primary common use central frequency, e.g. L1 = 1575.45 MHz + * for GPS. + * + * For an L1, L5 receiver tracking a satellite on L1 and L5 at the same + * time, two raw measurement structs must be reported for this same + * satellite, in one of the measurement structs, all the values related + * to L1 must be filled, and in the other all of the values related to + * L5 must be filled. + */ + long carrierFrequencyHz; + } + + /** + * The array of GNSS AGC values. + * + * This field must be reported when the GNSS measurement engine is running, even when the + * GnssMeasurement or GnssClock fields are not reported yet. E.g., when a GNSS signal is too + * weak to be acquired, the AGC value must still be reported. + */ + @nullable GnssAgc[] gnssAgcs; +} diff --git a/gnss/aidl/vts/gnss_hal_test_cases.cpp b/gnss/aidl/vts/gnss_hal_test_cases.cpp index 9acef8bed0..eec50b0a13 100644 --- a/gnss/aidl/vts/gnss_hal_test_cases.cpp +++ b/gnss/aidl/vts/gnss_hal_test_cases.cpp @@ -966,3 +966,46 @@ TEST_P(GnssHalTest, TestGnssMeasurementSetCallbackWithOptions) { 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. + */ +TEST_P(GnssHalTest, TestGnssAgcInGnssMeasurement) { + if (aidl_gnss_hal_->getInterfaceVersion() == 1) { + return; + } + const int kFirstGnssMeasurementTimeoutSeconds = 10; + const int kNumMeasurementEvents = 15; + + sp iGnssMeasurement; + auto status = aidl_gnss_hal_->getExtensionGnssMeasurement(&iGnssMeasurement); + ASSERT_TRUE(status.isOk()); + ASSERT_TRUE(iGnssMeasurement != nullptr); + + auto callback = sp::make(); + status = iGnssMeasurement->setCallback(callback, /* enableFullTracking= */ false, + /* enableCorrVecOutputs */ false); + 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); + + ASSERT_TRUE(lastMeasurement.gnssAgcs.has_value()); + for (const auto& gnssAgc : lastMeasurement.gnssAgcs.value()) { + ASSERT_TRUE(gnssAgc.has_value()); + ASSERT_TRUE(gnssAgc.value().carrierFrequencyHz >= 0); + } + } + + status = iGnssMeasurement->close(); + ASSERT_TRUE(status.isOk()); +} diff --git a/gnss/common/utils/default/Utils.cpp b/gnss/common/utils/default/Utils.cpp index 563c6d5d21..1ff84eb9a5 100644 --- a/gnss/common/utils/default/Utils.cpp +++ b/gnss/common/utils/default/Utils.cpp @@ -38,6 +38,7 @@ using GnssSvInfo = aidl::android::hardware::gnss::IGnssCallback::GnssSvInfo; using GnssSvFlags = aidl::android::hardware::gnss::IGnssCallback::GnssSvFlags; using GnssSvFlagsV1_0 = V1_0::IGnssCallback::GnssSvFlags; +using GnssAgc = aidl::android::hardware::gnss::GnssData::GnssAgc; using GnssMeasurementFlagsV1_0 = V1_0::IGnssMeasurementCallback::GnssMeasurementFlags; using GnssMeasurementFlagsV2_1 = V2_1::IGnssMeasurementCallback::GnssMeasurementFlags; using GnssMeasurementStateV2_0 = V2_0::IGnssMeasurementCallback::GnssMeasurementState; @@ -231,8 +232,23 @@ GnssData Utils::getMockMeasurement(const bool enableCorrVecOutputs) { measurement.flags |= GnssMeasurement::HAS_CORRELATION_VECTOR; } - GnssData gnssData = { - .measurements = {measurement}, .clock = clock, .elapsedRealtime = timestamp}; + GnssAgc gnssAgc1 = { + .agcLevelDb = 3.5, + .constellation = GnssConstellationType::GLONASS, + .carrierFrequencyHz = (int64_t)kGloG1FreqHz, + }; + + GnssAgc gnssAgc2 = { + .agcLevelDb = -5.1, + .constellation = GnssConstellationType::GPS, + .carrierFrequencyHz = (int64_t)kGpsL1FreqHz, + }; + + GnssData gnssData = {.measurements = {measurement}, + .clock = clock, + .elapsedRealtime = timestamp, + .gnssAgcs = std::make_optional(std::vector( + {std::make_optional(gnssAgc1), std::make_optional(gnssAgc2)}))}; return gnssData; }