gnssMeasurementCb_2_1(const IGnssMeasurementCallback_2_1::GnssData&) override;
+ };
+
+ /*
+ * SetUpGnssCallback:
+ * Set GnssCallback and verify the result.
+ */
+ void SetUpGnssCallback();
+
+ /*
+ * StartAndCheckFirstLocation:
+ * Helper function to start location, and check the first one.
+ *
+ * Note this leaves the Location request active, to enable Stop call vs. other call
+ * reordering tests.
+ *
+ * returns true if a location was successfully generated
+ */
+ bool StartAndCheckFirstLocation();
+
+ /*
+ * CheckLocation:
+ * Helper function to vet Location fields
+ *
+ * check_speed: true if speed related fields are also verified.
+ */
+ void CheckLocation(const GnssLocation_2_0& location, const bool check_speed);
+
+ /*
+ * StartAndCheckLocations:
+ * Helper function to collect, and check a number of
+ * normal ~1Hz locations.
+ *
+ * Note this leaves the Location request active, to enable Stop call vs. other call
+ * reordering tests.
+ */
+ void StartAndCheckLocations(int count);
+
+ /*
+ * StopAndClearLocations:
+ * Helper function to stop locations, and clear any remaining notifications
+ */
+ void StopAndClearLocations();
+
+ /*
+ * SetPositionMode:
+ * Helper function to set positioning mode and verify output
+ */
+ void SetPositionMode(const int min_interval_msec, const bool low_power_mode);
+
+ sp gnss_hal_; // GNSS HAL to call into
+ sp gnss_cb_; // Primary callback interface
+};
+
+#endif // GNSS_HAL_TEST_H_
diff --git a/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp
new file mode 100644
index 0000000000..ef8249b4d0
--- /dev/null
+++ b/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHalTestCases"
+
+#include
+#include "Utils.h"
+
+#include
+
+using android::hardware::hidl_string;
+using android::hardware::hidl_vec;
+
+using android::hardware::gnss::common::Utils;
+
+using IGnssMeasurement_2_1 = android::hardware::gnss::V2_1::IGnssMeasurement;
+using IGnssMeasurement_2_0 = android::hardware::gnss::V2_0::IGnssMeasurement;
+using IGnssMeasurement_1_1 = android::hardware::gnss::V1_1::IGnssMeasurement;
+using IGnssMeasurement_1_0 = android::hardware::gnss::V1_0::IGnssMeasurement;
+
+/*
+ * SetupTeardownCreateCleanup:
+ * Requests the gnss HAL then calls cleanup
+ *
+ * Empty test fixture to verify basic Setup & Teardown
+ */
+TEST_P(GnssHalTest, SetupTeardownCreateCleanup) {}
+
+/*
+ * TestGnssMeasurementExtension:
+ * Gets the GnssMeasurementExtension and verifies that it returns an actual extension.
+ */
+TEST_P(GnssHalTest, TestGnssMeasurementExtension) {
+ auto gnssMeasurement_2_1 = gnss_hal_->getExtensionGnssMeasurement_2_1();
+ auto gnssMeasurement_2_0 = gnss_hal_->getExtensionGnssMeasurement_2_0();
+ auto gnssMeasurement_1_1 = gnss_hal_->getExtensionGnssMeasurement_1_1();
+ auto gnssMeasurement_1_0 = gnss_hal_->getExtensionGnssMeasurement();
+ ASSERT_TRUE(gnssMeasurement_2_1.isOk() && gnssMeasurement_2_0.isOk() &&
+ gnssMeasurement_1_1.isOk() && gnssMeasurement_1_0.isOk());
+ sp iGnssMeas_2_1 = gnssMeasurement_2_1;
+ sp iGnssMeas_2_0 = gnssMeasurement_2_0;
+ sp iGnssMeas_1_1 = gnssMeasurement_1_1;
+ sp iGnssMeas_1_0 = gnssMeasurement_1_0;
+ // At least one interface is non-null.
+ int numNonNull = (int)(iGnssMeas_2_1 != nullptr) + (int)(iGnssMeas_2_0 != nullptr) +
+ (int)(iGnssMeas_1_1 != nullptr) + (int)(iGnssMeas_1_0 != nullptr);
+ ASSERT_TRUE(numNonNull >= 1);
+}
+
+/*
+ * TestGnssMeasurementFields:
+ * Sets a GnssMeasurementCallback, waits for a measurement, and verifies
+ * 1. basebandCN0DbHz is valid
+ */
+TEST_P(GnssHalTest, TestGnssMeasurementFields) {
+ const int kFirstGnssMeasurementTimeoutSeconds = 10;
+
+ auto gnssMeasurement = gnss_hal_->getExtensionGnssMeasurement_2_1();
+ ASSERT_TRUE(gnssMeasurement.isOk());
+
+ // Skip test if GnssMeasurement v2.1 is not supported
+ sp iGnssMeasurement = gnssMeasurement;
+ if (iGnssMeasurement == nullptr) {
+ return;
+ }
+
+ sp callback = new GnssMeasurementCallback();
+ auto result = iGnssMeasurement->setCallback_2_1(callback, /* enableFullTracking= */ true);
+ ASSERT_TRUE(result.isOk());
+ EXPECT_EQ(result, IGnssMeasurement_1_0::GnssMeasurementStatus::SUCCESS);
+
+ IGnssMeasurementCallback_2_1::GnssData lastMeasurement;
+ ASSERT_TRUE(callback->measurement_cbq_.retrieve(lastMeasurement,
+ kFirstGnssMeasurementTimeoutSeconds));
+ EXPECT_EQ(callback->measurement_cbq_.calledCount(), 1);
+ ASSERT_TRUE(lastMeasurement.measurements.size() > 0);
+ for (auto measurement : lastMeasurement.measurements) {
+ // Verify basebandCn0DbHz is valid.
+ ASSERT_TRUE(measurement.basebandCN0DbHz > 0.0 && measurement.basebandCN0DbHz <= 65.0);
+ }
+
+ iGnssMeasurement->close();
+}
+
+/*
+ * TestGnssSvInfoFields:
+ * Gets 1 location and a GnssSvInfo, and verifies
+ * 1. basebandCN0DbHz is valid.
+ */
+TEST_P(GnssHalTest, TestGnssSvInfoFields) {
+ gnss_cb_->location_cbq_.reset();
+ StartAndCheckFirstLocation();
+ int location_called_count = gnss_cb_->location_cbq_.calledCount();
+
+ // Tolerate 1 less sv status to handle edge cases in reporting.
+ int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
+ EXPECT_GE(sv_info_list_cbq_size, 0);
+ ALOGD("Observed %d GnssSvStatus, while awaiting one location (%d received)",
+ sv_info_list_cbq_size, location_called_count);
+
+ hidl_vec last_sv_info_list;
+ ASSERT_TRUE(gnss_cb_->sv_info_list_cbq_.retrieve(last_sv_info_list, 1));
+
+ bool nonZeroCn0Found = false;
+ for (auto sv_info : last_sv_info_list) {
+ ASSERT_TRUE(sv_info.basebandCN0DbHz >= 0.0 && sv_info.basebandCN0DbHz <= 65.0);
+ if (sv_info.basebandCN0DbHz > 0.0) {
+ nonZeroCn0Found = true;
+ }
+ }
+ // Assert at least one value is non-zero. Zero is ok in status as it's possibly
+ // reporting a searched but not found satellite.
+ ASSERT_TRUE(nonZeroCn0Found);
+ StopAndClearLocations();
+}
diff --git a/gnss/common/utils/default/Android.bp b/gnss/common/utils/default/Android.bp
index 4ea97fac67..577f6ae5e3 100644
--- a/gnss/common/utils/default/Android.bp
+++ b/gnss/common/utils/default/Android.bp
@@ -28,6 +28,10 @@ cc_library_static {
],
export_include_dirs: ["include"],
shared_libs: [
+ "libhidlbase",
+ "libutils",
"android.hardware.gnss@1.0",
+ "android.hardware.gnss@2.0",
+ "android.hardware.gnss@2.1",
],
}
diff --git a/gnss/common/utils/default/Utils.cpp b/gnss/common/utils/default/Utils.cpp
index b9a06e8d6d..6c6d696f3d 100644
--- a/gnss/common/utils/default/Utils.cpp
+++ b/gnss/common/utils/default/Utils.cpp
@@ -16,6 +16,7 @@
#include
#include
+#include
namespace android {
namespace hardware {
@@ -23,31 +24,188 @@ namespace gnss {
namespace common {
using GnssSvFlags = V1_0::IGnssCallback::GnssSvFlags;
+using GnssMeasurementFlags = V1_0::IGnssMeasurementCallback::GnssMeasurementFlags;
+using GnssMeasurementStateV2_0 = V2_0::IGnssMeasurementCallback::GnssMeasurementState;
+using ElapsedRealtime = V2_0::ElapsedRealtime;
+using ElapsedRealtimeFlags = V2_0::ElapsedRealtimeFlags;
+using GnssConstellationTypeV2_0 = V2_0::GnssConstellationType;
+using IGnssMeasurementCallbackV2_0 = V2_0::IGnssMeasurementCallback;
-GnssLocation Utils::getMockLocation() {
- GnssLocation location = {.gnssLocationFlags = 0xFF,
- .latitudeDegrees = kMockLatitudeDegrees,
- .longitudeDegrees = kMockLongitudeDegrees,
- .altitudeMeters = kMockAltitudeMeters,
- .speedMetersPerSec = kMockSpeedMetersPerSec,
- .bearingDegrees = kMockBearingDegrees,
- .horizontalAccuracyMeters = kMockHorizontalAccuracyMeters,
- .verticalAccuracyMeters = kMockVerticalAccuracyMeters,
- .speedAccuracyMetersPerSecond = kMockSpeedAccuracyMetersPerSecond,
- .bearingAccuracyDegrees = kMockBearingAccuracyDegrees,
- .timestamp = kMockTimestamp};
+GnssDataV2_1 Utils::getMockMeasurementV2_1() {
+ GnssDataV2_0 gnssDataV2_0 = Utils::getMockMeasurementV2_0();
+ V2_1::IGnssMeasurementCallback::GnssMeasurement gnssMeasurementV2_1 = {
+ .v2_0 = gnssDataV2_0.measurements[0],
+ .basebandCN0DbHz = 25.0,
+ };
+ hidl_vec measurements(1);
+ measurements[0] = gnssMeasurementV2_1;
+ GnssDataV2_1 gnssDataV2_1 = {
+ .measurements = measurements,
+ .clock = gnssDataV2_0.clock,
+ .elapsedRealtime = gnssDataV2_0.elapsedRealtime,
+ };
+ return gnssDataV2_1;
+}
+
+GnssDataV2_0 Utils::getMockMeasurementV2_0() {
+ V1_0::IGnssMeasurementCallback::GnssMeasurement measurement_1_0 = {
+ .flags = (uint32_t)GnssMeasurementFlags::HAS_CARRIER_FREQUENCY,
+ .svid = (int16_t)6,
+ .constellation = V1_0::GnssConstellationType::UNKNOWN,
+ .timeOffsetNs = 0.0,
+ .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 = "C",
+ .state = GnssMeasurementStateV2_0::STATE_CODE_LOCK |
+ GnssMeasurementStateV2_0::STATE_BIT_SYNC |
+ GnssMeasurementStateV2_0::STATE_SUBFRAME_SYNC |
+ GnssMeasurementStateV2_0::STATE_TOW_DECODED |
+ GnssMeasurementStateV2_0::STATE_GLO_STRING_SYNC |
+ GnssMeasurementStateV2_0::STATE_GLO_TOD_DECODED,
+ .constellation = GnssConstellationTypeV2_0::GLONASS,
+ };
+
+ hidl_vec 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};
+
+ ElapsedRealtime timestamp = {
+ .flags = ElapsedRealtimeFlags::HAS_TIMESTAMP_NS |
+ ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS,
+ .timestampNs = static_cast(::android::elapsedRealtimeNano()),
+ // This is an hardcoded value indicating a 1ms of uncertainty between the two clocks.
+ // In an actual implementation provide an estimate of the synchronization uncertainty
+ // or don't set the field.
+ .timeUncertaintyNs = 1000000};
+
+ GnssDataV2_0 gnssData = {
+ .measurements = measurements, .clock = clock, .elapsedRealtime = timestamp};
+ return gnssData;
+}
+
+V2_0::GnssLocation Utils::getMockLocationV2_0() {
+ const V2_0::ElapsedRealtime timestamp = {
+ .flags = V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS |
+ V2_0::ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS,
+ .timestampNs = static_cast(::android::elapsedRealtimeNano()),
+ // This is an hardcoded value indicating a 1ms of uncertainty between the two clocks.
+ // In an actual implementation provide an estimate of the synchronization uncertainty
+ // or don't set the field.
+ .timeUncertaintyNs = 1000000};
+
+ V2_0::GnssLocation location = {.v1_0 = Utils::getMockLocationV1_0(),
+ .elapsedRealtime = timestamp};
return location;
}
-GnssSvInfo Utils::getSvInfo(int16_t svid, GnssConstellationType type, float cN0DbHz,
- float elevationDegrees, float azimuthDegrees) {
- GnssSvInfo svInfo = {.svid = svid,
- .constellation = type,
- .cN0Dbhz = cN0DbHz,
- .elevationDegrees = elevationDegrees,
- .azimuthDegrees = azimuthDegrees,
- .svFlag = GnssSvFlags::USED_IN_FIX | GnssSvFlags::HAS_EPHEMERIS_DATA |
- GnssSvFlags::HAS_ALMANAC_DATA};
+V1_0::GnssLocation Utils::getMockLocationV1_0() {
+ V1_0::GnssLocation location = {
+ .gnssLocationFlags = 0xFF,
+ .latitudeDegrees = kMockLatitudeDegrees,
+ .longitudeDegrees = kMockLongitudeDegrees,
+ .altitudeMeters = kMockAltitudeMeters,
+ .speedMetersPerSec = kMockSpeedMetersPerSec,
+ .bearingDegrees = kMockBearingDegrees,
+ .horizontalAccuracyMeters = kMockHorizontalAccuracyMeters,
+ .verticalAccuracyMeters = kMockVerticalAccuracyMeters,
+ .speedAccuracyMetersPerSecond = kMockSpeedAccuracyMetersPerSecond,
+ .bearingAccuracyDegrees = kMockBearingAccuracyDegrees,
+ .timestamp = kMockTimestamp};
+ return location;
+}
+
+hidl_vec Utils::getMockSvInfoListV2_1() {
+ GnssSvInfoV1_0 gnssSvInfoV1_0 =
+ Utils::getMockSvInfoV1_0(3, V1_0::GnssConstellationType::GPS, 32.5, 59.1, 166.5);
+ GnssSvInfoV2_0 gnssSvInfoV2_0 =
+ Utils::getMockSvInfoV2_0(gnssSvInfoV1_0, V2_0::GnssConstellationType::GPS);
+ hidl_vec gnssSvInfoList = {
+ Utils::getMockSvInfoV2_1(gnssSvInfoV2_0, 27.5),
+ getMockSvInfoV2_1(
+ getMockSvInfoV2_0(getMockSvInfoV1_0(5, V1_0::GnssConstellationType::GPS, 27.0,
+ 29.0, 56.5),
+ V2_0::GnssConstellationType::GPS),
+ 22.0),
+ getMockSvInfoV2_1(
+ getMockSvInfoV2_0(getMockSvInfoV1_0(17, V1_0::GnssConstellationType::GPS, 30.5,
+ 71.0, 77.0),
+ V2_0::GnssConstellationType::GPS),
+ 25.5),
+ getMockSvInfoV2_1(
+ getMockSvInfoV2_0(getMockSvInfoV1_0(26, V1_0::GnssConstellationType::GPS, 24.1,
+ 28.0, 253.0),
+ V2_0::GnssConstellationType::GPS),
+ 19.1),
+ getMockSvInfoV2_1(
+ getMockSvInfoV2_0(getMockSvInfoV1_0(5, V1_0::GnssConstellationType::GLONASS,
+ 20.5, 11.5, 116.0),
+ V2_0::GnssConstellationType::GLONASS),
+ 15.5),
+ getMockSvInfoV2_1(
+ getMockSvInfoV2_0(getMockSvInfoV1_0(17, V1_0::GnssConstellationType::GLONASS,
+ 21.5, 28.5, 186.0),
+ V2_0::GnssConstellationType::GLONASS),
+ 16.5),
+ getMockSvInfoV2_1(
+ getMockSvInfoV2_0(getMockSvInfoV1_0(18, V1_0::GnssConstellationType::GLONASS,
+ 28.3, 38.8, 69.0),
+ V2_0::GnssConstellationType::GLONASS),
+ 25.3),
+ getMockSvInfoV2_1(
+ getMockSvInfoV2_0(getMockSvInfoV1_0(10, V1_0::GnssConstellationType::GLONASS,
+ 25.0, 66.0, 247.0),
+ V2_0::GnssConstellationType::GLONASS),
+ 20.0),
+ };
+ return gnssSvInfoList;
+}
+
+GnssSvInfoV2_1 Utils::getMockSvInfoV2_1(GnssSvInfoV2_0 gnssSvInfoV2_0, float basebandCN0DbHz) {
+ GnssSvInfoV2_1 gnssSvInfoV2_1 = {
+ .v2_0 = gnssSvInfoV2_0,
+ .basebandCN0DbHz = basebandCN0DbHz,
+ };
+ return gnssSvInfoV2_1;
+}
+
+GnssSvInfoV2_0 Utils::getMockSvInfoV2_0(GnssSvInfoV1_0 gnssSvInfoV1_0,
+ V2_0::GnssConstellationType type) {
+ GnssSvInfoV2_0 gnssSvInfoV2_0 = {
+ .v1_0 = gnssSvInfoV1_0,
+ .constellation = type,
+ };
+ return gnssSvInfoV2_0;
+}
+
+GnssSvInfoV1_0 Utils::getMockSvInfoV1_0(int16_t svid, V1_0::GnssConstellationType type,
+ float cN0DbHz, float elevationDegrees,
+ float azimuthDegrees) {
+ GnssSvInfoV1_0 svInfo = {.svid = svid,
+ .constellation = type,
+ .cN0Dbhz = cN0DbHz,
+ .elevationDegrees = elevationDegrees,
+ .azimuthDegrees = azimuthDegrees,
+ .svFlag = GnssSvFlags::USED_IN_FIX | GnssSvFlags::HAS_EPHEMERIS_DATA |
+ GnssSvFlags::HAS_ALMANAC_DATA};
return svInfo;
}
diff --git a/gnss/common/utils/default/include/Utils.h b/gnss/common/utils/default/include/Utils.h
index 47c88129f3..e0c61a41e1 100644
--- a/gnss/common/utils/default/include/Utils.h
+++ b/gnss/common/utils/default/include/Utils.h
@@ -18,20 +18,34 @@
#define android_hardware_gnss_common_default_Utils_H_
#include
+#include
+#include
-using GnssConstellationType = ::android::hardware::gnss::V1_0::GnssConstellationType;
-using GnssLocation = ::android::hardware::gnss::V1_0::GnssLocation;
-using GnssSvInfo = ::android::hardware::gnss::V1_0::IGnssCallback::GnssSvInfo;
+using ::android::hardware::hidl_vec;
namespace android {
namespace hardware {
namespace gnss {
namespace common {
+using GnssDataV2_0 = V2_0::IGnssMeasurementCallback::GnssData;
+using GnssDataV2_1 = V2_1::IGnssMeasurementCallback::GnssData;
+using GnssSvInfoV1_0 = V1_0::IGnssCallback::GnssSvInfo;
+using GnssSvInfoV2_0 = V2_0::IGnssCallback::GnssSvInfo;
+using GnssSvInfoV2_1 = V2_1::IGnssCallback::GnssSvInfo;
+
struct Utils {
- static GnssLocation getMockLocation();
- static GnssSvInfo getSvInfo(int16_t svid, GnssConstellationType type, float cN0DbHz,
- float elevationDegrees, float azimuthDegrees);
+ static GnssDataV2_0 getMockMeasurementV2_0();
+ static GnssDataV2_1 getMockMeasurementV2_1();
+ static V2_0::GnssLocation getMockLocationV2_0();
+ static V1_0::GnssLocation getMockLocationV1_0();
+ static hidl_vec getMockSvInfoListV2_1();
+ static GnssSvInfoV2_1 getMockSvInfoV2_1(GnssSvInfoV2_0 gnssSvInfoV2_0, float basebandCN0DbHz);
+ static GnssSvInfoV2_0 getMockSvInfoV2_0(GnssSvInfoV1_0 gnssSvInfoV1_0,
+ V2_0::GnssConstellationType type);
+ static GnssSvInfoV1_0 getMockSvInfoV1_0(int16_t svid, V1_0::GnssConstellationType type,
+ float cN0DbHz, float elevationDegrees,
+ float azimuthDegrees);
};
} // namespace common