blob: aa8bdfdf16935d5e39a63be1361fb3f0585022d1 [file] [log] [blame]
/*
* Copyright (C) 2020 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 <android/hardware/gnss/IAGnss.h>
#include <android/hardware/gnss/IGnss.h>
#include <android/hardware/gnss/IGnssAntennaInfo.h>
#include <android/hardware/gnss/IGnssBatching.h>
#include <android/hardware/gnss/IGnssDebug.h>
#include <android/hardware/gnss/IGnssMeasurementCallback.h>
#include <android/hardware/gnss/IGnssMeasurementInterface.h>
#include <android/hardware/gnss/IGnssPowerIndication.h>
#include <android/hardware/gnss/IGnssPsds.h>
#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"
#include "GnssBatchingCallback.h"
#include "GnssGeofenceCallback.h"
#include "GnssMeasurementCallbackAidl.h"
#include "GnssNavigationMessageCallback.h"
#include "GnssPowerIndicationCallback.h"
#include "GnssVisibilityControlCallback.h"
#include "MeasurementCorrectionsCallback.h"
#include "Utils.h"
#include "gnss_hal_test.h"
using android::sp;
using android::hardware::gnss::BlocklistedSource;
using android::hardware::gnss::ElapsedRealtime;
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::GnssPowerStats;
using android::hardware::gnss::IAGnss;
using android::hardware::gnss::IAGnssRil;
using android::hardware::gnss::IGnss;
using android::hardware::gnss::IGnssAntennaInfo;
using android::hardware::gnss::IGnssAntennaInfoCallback;
using android::hardware::gnss::IGnssBatching;
using android::hardware::gnss::IGnssBatchingCallback;
using android::hardware::gnss::IGnssCallback;
using android::hardware::gnss::IGnssConfiguration;
using android::hardware::gnss::IGnssDebug;
using android::hardware::gnss::IGnssGeofence;
using android::hardware::gnss::IGnssGeofenceCallback;
using android::hardware::gnss::IGnssMeasurementCallback;
using android::hardware::gnss::IGnssMeasurementInterface;
using android::hardware::gnss::IGnssNavigationMessageInterface;
using android::hardware::gnss::IGnssPowerIndication;
using android::hardware::gnss::IGnssPsds;
using android::hardware::gnss::PsdsType;
using android::hardware::gnss::SatellitePvt;
using android::hardware::gnss::common::Utils;
using android::hardware::gnss::measurement_corrections::IMeasurementCorrectionsInterface;
using android::hardware::gnss::visibility_control::IGnssVisibilityControl;
using GnssConstellationTypeV2_0 = android::hardware::gnss::V2_0::GnssConstellationType;
static bool IsAutomotiveDevice() {
char buffer[PROPERTY_VALUE_MAX] = {0};
property_get("ro.hardware.type", buffer, "");
return strncmp(buffer, "automotive", PROPERTY_VALUE_MAX) == 0;
}
/*
* SetupTeardownCreateCleanup:
* Requests the gnss HAL then calls cleanup
*
* Empty test fixture to verify basic Setup & Teardown
*/
TEST_P(GnssHalTest, SetupTeardownCreateCleanup) {}
/*
* GetLocation:
* Turns on location, waits 75 second for at least 5 locations,
* and checks them for reasonable validity.
*/
TEST_P(GnssHalTest, GetLocations) {
if (aidl_gnss_hal_->getInterfaceVersion() <= 1) {
return;
}
const int kMinIntervalMsec = 500;
const int kLocationsToCheck = 5;
SetPositionMode(kMinIntervalMsec, /* low_power_mode= */ false);
StartAndCheckLocations(kLocationsToCheck);
StopAndClearLocations();
}
/*
* InjectDelete:
* Ensures that calls to inject and/or delete information state are handled.
*/
TEST_P(GnssHalTest, InjectDelete) {
if (aidl_gnss_hal_->getInterfaceVersion() <= 1) {
return;
}
// Confidently, well north of Alaska
auto status = aidl_gnss_hal_->injectLocation(Utils::getMockLocation(80.0, -170.0, 150.0));
ASSERT_TRUE(status.isOk());
// Fake time, but generally reasonable values (time in Aug. 2018)
status =
aidl_gnss_hal_->injectTime(/* timeMs= */ 1534567890123L,
/* timeReferenceMs= */ 123456L, /* uncertaintyMs= */ 10000L);
ASSERT_TRUE(status.isOk());
status = aidl_gnss_hal_->deleteAidingData(IGnss::GnssAidingData::POSITION);
ASSERT_TRUE(status.isOk());
status = aidl_gnss_hal_->deleteAidingData(IGnss::GnssAidingData::TIME);
ASSERT_TRUE(status.isOk());
// Ensure we can get a good location after a bad injection has been deleted
StartAndCheckFirstLocation(/* min_interval_msec= */ 1000, /* low_power_mode= */ false);
StopAndClearLocations();
}
/*
* InjectSeedLocation:
* Injects a seed location and ensures the injected seed location is not fused in the resulting
* GNSS location.
*/
TEST_P(GnssHalTest, InjectSeedLocation) {
if (aidl_gnss_hal_->getInterfaceVersion() <= 1) {
return;
}
// An arbitrary position in North Pacific Ocean (where no VTS labs will ever likely be located).
const double seedLatDegrees = 32.312894;
const double seedLngDegrees = -172.954117;
const float seedAccuracyMeters = 150.0;
auto status = aidl_gnss_hal_->injectLocation(
Utils::getMockLocation(seedLatDegrees, seedLngDegrees, seedAccuracyMeters));
ASSERT_TRUE(status.isOk());
StartAndCheckFirstLocation(/* min_interval_msec= */ 1000, /* low_power_mode= */ false);
// Ensure we don't get a location anywhere within 111km (1 degree of lat or lng) of the seed
// location.
EXPECT_TRUE(std::abs(aidl_gnss_cb_->last_location_.latitudeDegrees - seedLatDegrees) > 1.0 ||
std::abs(aidl_gnss_cb_->last_location_.longitudeDegrees - seedLngDegrees) > 1.0);
StopAndClearLocations();
status = aidl_gnss_hal_->deleteAidingData(IGnss::GnssAidingData::POSITION);
ASSERT_TRUE(status.isOk());
}
/*
* 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) {
return;
}
if (!IsAutomotiveDevice()) {
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());
}
/*
* GetLocationLowPower:
* Turns on location, waits for at least 5 locations allowing max of LOCATION_TIMEOUT_SUBSEQUENT_SEC
* between one location and the next. Also ensure that MIN_INTERVAL_MSEC is respected by waiting
* NO_LOCATION_PERIOD_SEC and verfiy that no location is received. Also perform validity checks on
* each received location.
*/
TEST_P(GnssHalTest, GetLocationLowPower) {
if (aidl_gnss_hal_->getInterfaceVersion() <= 1) {
return;
}
const int kMinIntervalMsec = 5000;
const int kLocationTimeoutSubsequentSec = (kMinIntervalMsec / 1000) * 2;
const int kNoLocationPeriodSec = (kMinIntervalMsec / 1000) / 2;
const int kLocationsToCheck = 5;
const bool kLowPowerMode = true;
// Warmup period - VTS doesn't have AGPS access via GnssLocationProvider
aidl_gnss_cb_->location_cbq_.reset();
StartAndCheckLocations(kLocationsToCheck);
StopAndClearLocations();
aidl_gnss_cb_->location_cbq_.reset();
// Start of Low Power Mode test
// Don't expect true - as without AGPS access
if (!StartAndCheckFirstLocation(kMinIntervalMsec, kLowPowerMode)) {
ALOGW("GetLocationLowPower test - no first low power location received.");
}
for (int i = 1; i < kLocationsToCheck; i++) {
// Verify that kMinIntervalMsec is respected by waiting kNoLocationPeriodSec and
// ensure that no location is received yet
aidl_gnss_cb_->location_cbq_.retrieve(aidl_gnss_cb_->last_location_, kNoLocationPeriodSec);
const int location_called_count = aidl_gnss_cb_->location_cbq_.calledCount();
// Tolerate (ignore) one extra location right after the first one
// to handle startup edge case scheduling limitations in some implementations
if ((i == 1) && (location_called_count == 2)) {
CheckLocation(aidl_gnss_cb_->last_location_, true);
continue; // restart the quiet wait period after this too-fast location
}
EXPECT_LE(location_called_count, i);
if (location_called_count != i) {
ALOGW("GetLocationLowPower test - not enough locations received. %d vs. %d expected ",
location_called_count, i);
}
if (!aidl_gnss_cb_->location_cbq_.retrieve(
aidl_gnss_cb_->last_location_,
kLocationTimeoutSubsequentSec - kNoLocationPeriodSec)) {
ALOGW("GetLocationLowPower test - timeout awaiting location %d", i);
} else {
CheckLocation(aidl_gnss_cb_->last_location_, true);
}
}
StopAndClearLocations();
}
/*
* InjectBestLocation
*
* Ensure successfully injecting a location.
*/
TEST_P(GnssHalTest, InjectBestLocation) {
if (aidl_gnss_hal_->getInterfaceVersion() <= 1) {
return;
}
StartAndCheckLocations(1);
GnssLocation gnssLocation = aidl_gnss_cb_->last_location_;
CheckLocation(gnssLocation, true);
auto status = aidl_gnss_hal_->injectBestLocation(gnssLocation);
ASSERT_TRUE(status.isOk());
status = aidl_gnss_hal_->deleteAidingData(IGnss::GnssAidingData::POSITION);
ASSERT_TRUE(status.isOk());
}
/*
* TestGnssSvInfoFields:
* Gets 1 location and a (non-empty) GnssSvInfo, and verifies basebandCN0DbHz is valid.
*/
TEST_P(GnssHalTest, TestGnssSvInfoFields) {
if (aidl_gnss_hal_->getInterfaceVersion() <= 1) {
return;
}
aidl_gnss_cb_->location_cbq_.reset();
aidl_gnss_cb_->sv_info_list_cbq_.reset();
StartAndCheckFirstLocation(/* min_interval_msec= */ 1000, /* low_power_mode= */ false);
int location_called_count = aidl_gnss_cb_->location_cbq_.calledCount();
ALOGD("Observed %d GnssSvStatus, while awaiting one location (%d received)",
aidl_gnss_cb_->sv_info_list_cbq_.size(), location_called_count);
// Wait for up to kNumSvInfoLists events for kTimeoutSeconds for each event.
int kTimeoutSeconds = 2;
int kNumSvInfoLists = 4;
std::list<std::vector<IGnssCallback::GnssSvInfo>> sv_info_lists;
std::vector<IGnssCallback::GnssSvInfo> last_sv_info_list;
do {
EXPECT_GT(aidl_gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_lists, kNumSvInfoLists,
kTimeoutSeconds),
0);
if (!sv_info_lists.empty()) {
last_sv_info_list = sv_info_lists.back();
ALOGD("last_sv_info size = %d", (int)last_sv_info_list.size());
}
} while (!sv_info_lists.empty() && last_sv_info_list.size() == 0);
bool nonZeroCn0Found = false;
for (auto sv_info : last_sv_info_list) {
EXPECT_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.
EXPECT_TRUE(nonZeroCn0Found);
StopAndClearLocations();
}
/*
* TestPsdsExtension:
* 1. Gets the PsdsExtension
* 2. Injects empty PSDS data and verifies that it returns an error.
*/
TEST_P(GnssHalTest, TestPsdsExtension) {
sp<IGnssPsds> iGnssPsds;
auto status = aidl_gnss_hal_->getExtensionPsds(&iGnssPsds);
if (status.isOk() && iGnssPsds != nullptr) {
status = iGnssPsds->injectPsdsData(PsdsType::LONG_TERM, std::vector<uint8_t>());
ASSERT_FALSE(status.isOk());
}
}
void CheckSatellitePvt(const SatellitePvt& satellitePvt, const int interfaceVersion) {
const double kMaxOrbitRadiusMeters = 43000000.0;
const double kMaxVelocityMps = 4000.0;
// The below values are determined using GPS ICD Table 20-1
const double kMinHardwareCodeBiasMeters = -17.869;
const double kMaxHardwareCodeBiasMeters = 17.729;
const double kMaxTimeCorrelationMeters = 3e6;
const double kMaxSatClkDriftMps = 1.117;
ASSERT_TRUE(satellitePvt.flags & SatellitePvt::HAS_POSITION_VELOCITY_CLOCK_INFO ||
satellitePvt.flags & SatellitePvt::HAS_IONO ||
satellitePvt.flags & SatellitePvt::HAS_TROPO);
if (satellitePvt.flags & SatellitePvt::HAS_POSITION_VELOCITY_CLOCK_INFO) {
ALOGD("Found HAS_POSITION_VELOCITY_CLOCK_INFO");
ASSERT_TRUE(satellitePvt.satPosEcef.posXMeters >= -kMaxOrbitRadiusMeters &&
satellitePvt.satPosEcef.posXMeters <= kMaxOrbitRadiusMeters);
ASSERT_TRUE(satellitePvt.satPosEcef.posYMeters >= -kMaxOrbitRadiusMeters &&
satellitePvt.satPosEcef.posYMeters <= kMaxOrbitRadiusMeters);
ASSERT_TRUE(satellitePvt.satPosEcef.posZMeters >= -kMaxOrbitRadiusMeters &&
satellitePvt.satPosEcef.posZMeters <= kMaxOrbitRadiusMeters);
ASSERT_TRUE(satellitePvt.satPosEcef.ureMeters > 0);
ASSERT_TRUE(satellitePvt.satVelEcef.velXMps >= -kMaxVelocityMps &&
satellitePvt.satVelEcef.velXMps <= kMaxVelocityMps);
ASSERT_TRUE(satellitePvt.satVelEcef.velYMps >= -kMaxVelocityMps &&
satellitePvt.satVelEcef.velYMps <= kMaxVelocityMps);
ASSERT_TRUE(satellitePvt.satVelEcef.velZMps >= -kMaxVelocityMps &&
satellitePvt.satVelEcef.velZMps <= kMaxVelocityMps);
ASSERT_TRUE(satellitePvt.satVelEcef.ureRateMps > 0);
ASSERT_TRUE(
satellitePvt.satClockInfo.satHardwareCodeBiasMeters > kMinHardwareCodeBiasMeters &&
satellitePvt.satClockInfo.satHardwareCodeBiasMeters < kMaxHardwareCodeBiasMeters);
ASSERT_TRUE(satellitePvt.satClockInfo.satTimeCorrectionMeters >
-kMaxTimeCorrelationMeters &&
satellitePvt.satClockInfo.satTimeCorrectionMeters < kMaxTimeCorrelationMeters);
ASSERT_TRUE(satellitePvt.satClockInfo.satClkDriftMps > -kMaxSatClkDriftMps &&
satellitePvt.satClockInfo.satClkDriftMps < kMaxSatClkDriftMps);
}
if (satellitePvt.flags & SatellitePvt::HAS_IONO) {
ALOGD("Found HAS_IONO");
ASSERT_TRUE(satellitePvt.ionoDelayMeters > 0 && satellitePvt.ionoDelayMeters < 100);
}
if (satellitePvt.flags & SatellitePvt::HAS_TROPO) {
ALOGD("Found HAS_TROPO");
ASSERT_TRUE(satellitePvt.tropoDelayMeters > 0 && satellitePvt.tropoDelayMeters < 100);
}
if (interfaceVersion >= 2) {
ASSERT_TRUE(satellitePvt.timeOfClockSeconds >= 0);
ASSERT_TRUE(satellitePvt.timeOfEphemerisSeconds >= 0);
// IODC has 10 bits
ASSERT_TRUE(satellitePvt.issueOfDataClock >= 0 && satellitePvt.issueOfDataClock <= 1023);
// IODE has 8 bits
ASSERT_TRUE(satellitePvt.issueOfDataEphemeris >= 0 &&
satellitePvt.issueOfDataEphemeris <= 255);
}
}
/*
* TestGnssMeasurementExtensionAndSatellitePvt:
* 1. Gets the GnssMeasurementExtension and verifies that it returns a non-null extension.
* 2. Sets a GnssMeasurementCallback, waits for a measurement, and verifies mandatory fields are
* valid.
* 3. If SatellitePvt is supported, waits for a measurement with SatellitePvt, and verifies the
* fields are valid.
*/
TEST_P(GnssHalTest, TestGnssMeasurementExtensionAndSatellitePvt) {
const bool kIsSatellitePvtSupported =
aidl_gnss_cb_->last_capabilities_ & (int)GnssCallbackAidl::CAPABILITY_SATELLITE_PVT;
ALOGD("SatellitePvt supported: %s", kIsSatellitePvtSupported ? "true" : "false");
const int kFirstGnssMeasurementTimeoutSeconds = 10;
const int kNumMeasurementEvents = 75;
sp<IGnssMeasurementInterface> iGnssMeasurement;
auto status = aidl_gnss_hal_->getExtensionGnssMeasurement(&iGnssMeasurement);
ASSERT_TRUE(status.isOk());
ASSERT_TRUE(iGnssMeasurement != nullptr);
auto callback = sp<GnssMeasurementCallbackAidl>::make();
status = iGnssMeasurement->setCallback(callback, /* enableFullTracking= */ true,
/* enableCorrVecOutputs */ false);
ASSERT_TRUE(status.isOk());
bool satellitePvtFound = false;
for (int i = 0; i < kNumMeasurementEvents; i++) {
if (i > 0 && (!kIsSatellitePvtSupported || satellitePvtFound)) {
break;
}
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);
if (measurement.flags & GnssMeasurement::HAS_SATELLITE_PVT &&
kIsSatellitePvtSupported == true) {
ALOGD("Found a measurement with SatellitePvt");
satellitePvtFound = true;
CheckSatellitePvt(measurement.satellitePvt, aidl_gnss_hal_->getInterfaceVersion());
}
}
}
if (kIsSatellitePvtSupported) {
ASSERT_TRUE(satellitePvtFound);
}
status = iGnssMeasurement->close();
ASSERT_TRUE(status.isOk());
}
/*
* TestCorrelationVector:
* 1. Gets the GnssMeasurementExtension and verifies that it returns a non-null extension.
* 2. Sets a GnssMeasurementCallback, waits for GnssMeasurements with CorrelationVector, and
* verifies fields are valid.
*/
TEST_P(GnssHalTest, TestCorrelationVector) {
const bool kIsCorrelationVectorSupported = aidl_gnss_cb_->last_capabilities_ &
(int)GnssCallbackAidl::CAPABILITY_CORRELATION_VECTOR;
const int kNumMeasurementEvents = 75;
// Pass the test if CorrelationVector is not supported
if (!kIsCorrelationVectorSupported) {
return;
}
const int kFirstGnssMeasurementTimeoutSeconds = 10;
sp<IGnssMeasurementInterface> iGnssMeasurement;
auto status = aidl_gnss_hal_->getExtensionGnssMeasurement(&iGnssMeasurement);
ASSERT_TRUE(status.isOk());
ASSERT_TRUE(iGnssMeasurement != nullptr);
auto callback = sp<GnssMeasurementCallbackAidl>::make();
status =
iGnssMeasurement->setCallback(callback, /* enableFullTracking= */ true,
/* enableCorrVecOutputs */ kIsCorrelationVectorSupported);
ASSERT_TRUE(status.isOk());
bool correlationVectorFound = false;
for (int i = 0; i < kNumMeasurementEvents; i++) {
// Pass the test if at least one CorrelationVector has been found.
if (correlationVectorFound) {
break;
}
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);
if (measurement.flags & GnssMeasurement::HAS_CORRELATION_VECTOR) {
correlationVectorFound = true;
ASSERT_TRUE(measurement.correlationVectors.size() > 0);
for (const auto& correlationVector : measurement.correlationVectors) {
ASSERT_GE(correlationVector.frequencyOffsetMps, 0);
ASSERT_GT(correlationVector.samplingWidthM, 0);
ASSERT_TRUE(correlationVector.magnitude.size() > 0);
for (const auto& magnitude : correlationVector.magnitude) {
ASSERT_TRUE(magnitude >= -32768 && magnitude <= 32767);
}
}
}
}
}
ASSERT_TRUE(correlationVectorFound);
status = iGnssMeasurement->close();
ASSERT_TRUE(status.isOk());
}
/*
* TestGnssPowerIndication
* 1. Gets the GnssPowerIndicationExtension.
* 2. Sets a GnssPowerIndicationCallback.
* 3. Requests and verifies the 1st GnssPowerStats is received.
* 4. Gets a location.
* 5. Requests the 2nd GnssPowerStats, and verifies it has larger values than the 1st one.
*/
TEST_P(GnssHalTest, TestGnssPowerIndication) {
// Set up gnssPowerIndication and callback
sp<IGnssPowerIndication> iGnssPowerIndication;
auto status = aidl_gnss_hal_->getExtensionGnssPowerIndication(&iGnssPowerIndication);
ASSERT_TRUE(status.isOk());
ASSERT_TRUE(iGnssPowerIndication != nullptr);
auto gnssPowerIndicationCallback = sp<GnssPowerIndicationCallback>::make();
status = iGnssPowerIndication->setCallback(gnssPowerIndicationCallback);
ASSERT_TRUE(status.isOk());
const int kTimeoutSec = 2;
EXPECT_TRUE(gnssPowerIndicationCallback->capabilities_cbq_.retrieve(
gnssPowerIndicationCallback->last_capabilities_, kTimeoutSec));
EXPECT_EQ(gnssPowerIndicationCallback->capabilities_cbq_.calledCount(), 1);
if (gnssPowerIndicationCallback->last_capabilities_ == 0) {
// Skipping the test since GnssPowerIndication is not supported.
return;
}
// Request and verify a GnssPowerStats is received
gnssPowerIndicationCallback->gnss_power_stats_cbq_.reset();
iGnssPowerIndication->requestGnssPowerStats();
EXPECT_TRUE(gnssPowerIndicationCallback->gnss_power_stats_cbq_.retrieve(
gnssPowerIndicationCallback->last_gnss_power_stats_, kTimeoutSec));
EXPECT_EQ(gnssPowerIndicationCallback->gnss_power_stats_cbq_.calledCount(), 1);
auto powerStats1 = gnssPowerIndicationCallback->last_gnss_power_stats_;
// Get a location and request another GnssPowerStats
if (aidl_gnss_hal_->getInterfaceVersion() <= 1) {
gnss_cb_->location_cbq_.reset();
} else {
aidl_gnss_cb_->location_cbq_.reset();
}
StartAndCheckFirstLocation(/* min_interval_msec= */ 1000, /* low_power_mode= */ false);
// Request and verify the 2nd GnssPowerStats has larger values than the 1st one
iGnssPowerIndication->requestGnssPowerStats();
EXPECT_TRUE(gnssPowerIndicationCallback->gnss_power_stats_cbq_.retrieve(
gnssPowerIndicationCallback->last_gnss_power_stats_, kTimeoutSec));
EXPECT_EQ(gnssPowerIndicationCallback->gnss_power_stats_cbq_.calledCount(), 2);
auto powerStats2 = gnssPowerIndicationCallback->last_gnss_power_stats_;
if ((gnssPowerIndicationCallback->last_capabilities_ &
(int)GnssPowerIndicationCallback::CAPABILITY_TOTAL)) {
// Elapsed realtime must increase
EXPECT_GT(powerStats2.elapsedRealtime.timestampNs, powerStats1.elapsedRealtime.timestampNs);
// Total energy must increase
EXPECT_GT(powerStats2.totalEnergyMilliJoule, powerStats1.totalEnergyMilliJoule);
}
// At least oone of singleband and multiband acquisition energy must increase
bool singlebandAcqEnergyIncreased = powerStats2.singlebandAcquisitionModeEnergyMilliJoule >
powerStats1.singlebandAcquisitionModeEnergyMilliJoule;
bool multibandAcqEnergyIncreased = powerStats2.multibandAcquisitionModeEnergyMilliJoule >
powerStats1.multibandAcquisitionModeEnergyMilliJoule;
if ((gnssPowerIndicationCallback->last_capabilities_ &
(int)GnssPowerIndicationCallback::CAPABILITY_SINGLEBAND_ACQUISITION) ||
(gnssPowerIndicationCallback->last_capabilities_ &
(int)GnssPowerIndicationCallback::CAPABILITY_MULTIBAND_ACQUISITION)) {
EXPECT_TRUE(singlebandAcqEnergyIncreased || multibandAcqEnergyIncreased);
}
// At least one of singleband and multiband tracking energy must increase
bool singlebandTrackingEnergyIncreased = powerStats2.singlebandTrackingModeEnergyMilliJoule >
powerStats1.singlebandTrackingModeEnergyMilliJoule;
bool multibandTrackingEnergyIncreased = powerStats2.multibandTrackingModeEnergyMilliJoule >
powerStats1.multibandTrackingModeEnergyMilliJoule;
if ((gnssPowerIndicationCallback->last_capabilities_ &
(int)GnssPowerIndicationCallback::CAPABILITY_SINGLEBAND_TRACKING) ||
(gnssPowerIndicationCallback->last_capabilities_ &
(int)GnssPowerIndicationCallback::CAPABILITY_MULTIBAND_TRACKING)) {
EXPECT_TRUE(singlebandTrackingEnergyIncreased || multibandTrackingEnergyIncreased);
}
// Clean up
StopAndClearLocations();
}
/*
* BlocklistIndividualSatellites:
*
* 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding
* GnssStatus for common satellites (strongest and one other.)
* 2a & b) Turns off location, and blocklists common satellites.
* 3) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding
* GnssStatus does not use those satellites.
* 4a & b) Turns off location, and send in empty blocklist.
* 5a) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding
* GnssStatus does re-use at least the previously strongest satellite
* 5b) Retry a few times, in case GNSS search strategy takes a while to reacquire even the
* formerly strongest satellite
*/
TEST_P(GnssHalTest, BlocklistIndividualSatellites) {
if (!(aidl_gnss_cb_->last_capabilities_ &
(int)GnssCallbackAidl::CAPABILITY_SATELLITE_BLOCKLIST)) {
ALOGI("Test BlocklistIndividualSatellites skipped. SATELLITE_BLOCKLIST capability not "
"supported.");
return;
}
const int kLocationsToAwait = 3;
const int kRetriesToUnBlocklist = 10;
if (aidl_gnss_hal_->getInterfaceVersion() <= 1) {
gnss_cb_->location_cbq_.reset();
} else {
aidl_gnss_cb_->location_cbq_.reset();
}
StartAndCheckLocations(kLocationsToAwait);
int location_called_count = (aidl_gnss_hal_->getInterfaceVersion() <= 1)
? gnss_cb_->location_cbq_.calledCount()
: aidl_gnss_cb_->location_cbq_.calledCount();
// Tolerate 1 less sv status to handle edge cases in reporting.
int sv_info_list_cbq_size = (aidl_gnss_hal_->getInterfaceVersion() <= 1)
? gnss_cb_->sv_info_list_cbq_.size()
: aidl_gnss_cb_->sv_info_list_cbq_.size();
EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations (%d received)",
sv_info_list_cbq_size, kLocationsToAwait, location_called_count);
/*
* Identify strongest SV seen at least kLocationsToAwait -1 times
* Why -1? To avoid test flakiness in case of (plausible) slight flakiness in strongest signal
* observability (one epoch RF null)
*/
const int kGnssSvInfoListTimeout = 2;
BlocklistedSource source_to_blocklist;
if (aidl_gnss_hal_->getInterfaceVersion() <= 1) {
std::list<hidl_vec<IGnssCallback_2_1::GnssSvInfo>> sv_info_vec_list;
int count = gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec_list, sv_info_list_cbq_size,
kGnssSvInfoListTimeout);
ASSERT_EQ(count, sv_info_list_cbq_size);
source_to_blocklist =
FindStrongFrequentNonGpsSource(sv_info_vec_list, kLocationsToAwait - 1);
} else {
std::list<std::vector<IGnssCallback::GnssSvInfo>> sv_info_vec_list;
int count = aidl_gnss_cb_->sv_info_list_cbq_.retrieve(
sv_info_vec_list, sv_info_list_cbq_size, kGnssSvInfoListTimeout);
ASSERT_EQ(count, sv_info_list_cbq_size);
source_to_blocklist =
FindStrongFrequentNonGpsSource(sv_info_vec_list, kLocationsToAwait - 1);
}
if (source_to_blocklist.constellation == GnssConstellationType::UNKNOWN) {
// Cannot find a non-GPS satellite. Let the test pass.
ALOGD("Cannot find a non-GPS satellite. Letting the test pass.");
return;
}
// Stop locations, blocklist the common SV
StopAndClearLocations();
sp<IGnssConfiguration> gnss_configuration_hal;
auto status = aidl_gnss_hal_->getExtensionGnssConfiguration(&gnss_configuration_hal);
ASSERT_TRUE(status.isOk());
ASSERT_NE(gnss_configuration_hal, nullptr);
std::vector<BlocklistedSource> sources;
sources.resize(1);
sources[0] = source_to_blocklist;
status = gnss_configuration_hal->setBlocklist(sources);
ASSERT_TRUE(status.isOk());
// retry and ensure satellite not used
if (aidl_gnss_hal_->getInterfaceVersion() <= 1) {
gnss_cb_->sv_info_list_cbq_.reset();
gnss_cb_->location_cbq_.reset();
} else {
aidl_gnss_cb_->sv_info_list_cbq_.reset();
aidl_gnss_cb_->location_cbq_.reset();
}
StartAndCheckLocations(kLocationsToAwait);
// early exit if test is being run with insufficient signal
location_called_count = (aidl_gnss_hal_->getInterfaceVersion() <= 1)
? gnss_cb_->location_cbq_.calledCount()
: aidl_gnss_cb_->location_cbq_.calledCount();
if (location_called_count == 0) {
ALOGE("0 Gnss locations received - ensure sufficient signal and retry");
}
ASSERT_TRUE(location_called_count > 0);
// Tolerate 1 less sv status to handle edge cases in reporting.
sv_info_list_cbq_size = (aidl_gnss_hal_->getInterfaceVersion() <= 1)
? gnss_cb_->sv_info_list_cbq_.size()
: aidl_gnss_cb_->sv_info_list_cbq_.size();
EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations (%d received)",
sv_info_list_cbq_size, kLocationsToAwait, location_called_count);
for (int i = 0; i < sv_info_list_cbq_size; ++i) {
if (aidl_gnss_hal_->getInterfaceVersion() <= 1) {
hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
auto& gnss_sv = sv_info_vec[iSv];
EXPECT_FALSE(
(gnss_sv.v2_0.v1_0.svid == source_to_blocklist.svid) &&
(static_cast<GnssConstellationType>(gnss_sv.v2_0.constellation) ==
source_to_blocklist.constellation) &&
(gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
}
} else {
std::vector<IGnssCallback::GnssSvInfo> sv_info_vec;
aidl_gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
auto& gnss_sv = sv_info_vec[iSv];
EXPECT_FALSE((gnss_sv.svid == source_to_blocklist.svid) &&
(gnss_sv.constellation == source_to_blocklist.constellation) &&
(gnss_sv.svFlag & (int)IGnssCallback::GnssSvFlags::USED_IN_FIX));
}
}
}
// clear blocklist and restart - this time updating the blocklist while location is still on
sources.resize(0);
status = gnss_configuration_hal->setBlocklist(sources);
ASSERT_TRUE(status.isOk());
bool strongest_sv_is_reobserved = false;
// do several loops awaiting a few locations, allowing non-immediate reacquisition strategies
int unblocklist_loops_remaining = kRetriesToUnBlocklist;
while (!strongest_sv_is_reobserved && (unblocklist_loops_remaining-- > 0)) {
StopAndClearLocations();
if (aidl_gnss_hal_->getInterfaceVersion() <= 1) {
gnss_cb_->sv_info_list_cbq_.reset();
gnss_cb_->location_cbq_.reset();
} else {
aidl_gnss_cb_->sv_info_list_cbq_.reset();
aidl_gnss_cb_->location_cbq_.reset();
}
StartAndCheckLocations(kLocationsToAwait);
// early exit loop if test is being run with insufficient signal
location_called_count = (aidl_gnss_hal_->getInterfaceVersion() <= 1)
? gnss_cb_->location_cbq_.calledCount()
: aidl_gnss_cb_->location_cbq_.calledCount();
if (location_called_count == 0) {
ALOGE("0 Gnss locations received - ensure sufficient signal and retry");
}
ASSERT_TRUE(location_called_count > 0);
// Tolerate 1 less sv status to handle edge cases in reporting.
sv_info_list_cbq_size = (aidl_gnss_hal_->getInterfaceVersion() <= 1)
? gnss_cb_->sv_info_list_cbq_.size()
: aidl_gnss_cb_->sv_info_list_cbq_.size();
EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
ALOGD("Clear blocklist, observed %d GnssSvInfo, while awaiting %d Locations"
", tries remaining %d",
sv_info_list_cbq_size, kLocationsToAwait, unblocklist_loops_remaining);
for (int i = 0; i < sv_info_list_cbq_size; ++i) {
if (aidl_gnss_hal_->getInterfaceVersion() <= 1) {
hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
auto& gnss_sv = sv_info_vec[iSv];
if ((gnss_sv.v2_0.v1_0.svid == source_to_blocklist.svid) &&
(static_cast<GnssConstellationType>(gnss_sv.v2_0.constellation) ==
source_to_blocklist.constellation) &&
(gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX)) {
strongest_sv_is_reobserved = true;
break;
}
}
} else {
std::vector<IGnssCallback::GnssSvInfo> sv_info_vec;
aidl_gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
auto& gnss_sv = sv_info_vec[iSv];
if ((gnss_sv.svid == source_to_blocklist.svid) &&
(gnss_sv.constellation == source_to_blocklist.constellation) &&
(gnss_sv.svFlag & (int)IGnssCallback::GnssSvFlags::USED_IN_FIX)) {
strongest_sv_is_reobserved = true;
break;
}
}
}
if (strongest_sv_is_reobserved) break;
}
}
EXPECT_TRUE(strongest_sv_is_reobserved);
StopAndClearLocations();
}
/*
* BlocklistConstellationLocationOff:
*
* 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding
* GnssStatus for any non-GPS constellations.
* 2a & b) Turns off location, and blocklist first non-GPS constellations.
* 3) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding
* GnssStatus does not use any constellation but GPS.
* 4a & b) Clean up by turning off location, and send in empty blocklist.
*/
TEST_P(GnssHalTest, BlocklistConstellationLocationOff) {
if (!(aidl_gnss_cb_->last_capabilities_ &
(int)GnssCallbackAidl::CAPABILITY_SATELLITE_BLOCKLIST)) {
ALOGI("Test BlocklistConstellationLocationOff skipped. SATELLITE_BLOCKLIST capability not "
"supported.");
return;
}
const int kLocationsToAwait = 3;
const int kGnssSvInfoListTimeout = 2;
// Find first non-GPS constellation to blocklist
GnssConstellationType constellation_to_blocklist = static_cast<GnssConstellationType>(
startLocationAndGetNonGpsConstellation(kLocationsToAwait, kGnssSvInfoListTimeout));
// Turns off location
StopAndClearLocations();
BlocklistedSource source_to_blocklist_1;
source_to_blocklist_1.constellation = constellation_to_blocklist;
source_to_blocklist_1.svid = 0; // documented wildcard for all satellites in this constellation
// IRNSS was added in 2.0. Always attempt to blocklist IRNSS to verify that the new enum is
// supported.
BlocklistedSource source_to_blocklist_2;
source_to_blocklist_2.constellation = GnssConstellationType::IRNSS;
source_to_blocklist_2.svid = 0; // documented wildcard for all satellites in this constellation
sp<IGnssConfiguration> gnss_configuration_hal;
auto status = aidl_gnss_hal_->getExtensionGnssConfiguration(&gnss_configuration_hal);
ASSERT_TRUE(status.isOk());
ASSERT_NE(gnss_configuration_hal, nullptr);
hidl_vec<BlocklistedSource> sources;
sources.resize(2);
sources[0] = source_to_blocklist_1;
sources[1] = source_to_blocklist_2;
status = gnss_configuration_hal->setBlocklist(sources);
ASSERT_TRUE(status.isOk());
// retry and ensure constellation not used
if (aidl_gnss_hal_->getInterfaceVersion() <= 1) {
gnss_cb_->sv_info_list_cbq_.reset();
gnss_cb_->location_cbq_.reset();
} else {
aidl_gnss_cb_->sv_info_list_cbq_.reset();
aidl_gnss_cb_->location_cbq_.reset();
}
StartAndCheckLocations(kLocationsToAwait);
// Tolerate 1 less sv status to handle edge cases in reporting.
int sv_info_list_cbq_size = (aidl_gnss_hal_->getInterfaceVersion() <= 1)
? gnss_cb_->sv_info_list_cbq_.size()
: aidl_gnss_cb_->sv_info_list_cbq_.size();
EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations", sv_info_list_cbq_size,
kLocationsToAwait);
for (int i = 0; i < sv_info_list_cbq_size; ++i) {
if (aidl_gnss_hal_->getInterfaceVersion() <= 1) {
hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
const auto& gnss_sv = sv_info_vec[iSv];
EXPECT_FALSE(
(static_cast<GnssConstellationType>(gnss_sv.v2_0.constellation) ==
source_to_blocklist_1.constellation) &&
(gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
EXPECT_FALSE(
(static_cast<GnssConstellationType>(gnss_sv.v2_0.constellation) ==
source_to_blocklist_2.constellation) &&
(gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
}
} else {
std::vector<IGnssCallback::GnssSvInfo> sv_info_vec;
aidl_gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
const auto& gnss_sv = sv_info_vec[iSv];
EXPECT_FALSE((gnss_sv.constellation == source_to_blocklist_1.constellation) &&
(gnss_sv.svFlag & (int)IGnssCallback::GnssSvFlags::USED_IN_FIX));
EXPECT_FALSE((gnss_sv.constellation == source_to_blocklist_2.constellation) &&
(gnss_sv.svFlag & (int)IGnssCallback::GnssSvFlags::USED_IN_FIX));
}
}
}
// clean up
StopAndClearLocations();
sources.resize(0);
status = gnss_configuration_hal->setBlocklist(sources);
ASSERT_TRUE(status.isOk());
}
/*
* BlocklistConstellationLocationOn:
*
* 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding
* GnssStatus for any non-GPS constellations.
* 2a & b) Blocklist first non-GPS constellation, and turn off location.
* 3) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding
* GnssStatus does not use any constellation but GPS.
* 4a & b) Clean up by turning off location, and send in empty blocklist.
*/
TEST_P(GnssHalTest, BlocklistConstellationLocationOn) {
if (!(aidl_gnss_cb_->last_capabilities_ &
(int)GnssCallbackAidl::CAPABILITY_SATELLITE_BLOCKLIST)) {
ALOGI("Test BlocklistConstellationLocationOn skipped. SATELLITE_BLOCKLIST capability not "
"supported.");
return;
}
const int kLocationsToAwait = 3;
const int kGnssSvInfoListTimeout = 2;
// Find first non-GPS constellation to blocklist
GnssConstellationType constellation_to_blocklist = static_cast<GnssConstellationType>(
startLocationAndGetNonGpsConstellation(kLocationsToAwait, kGnssSvInfoListTimeout));
BlocklistedSource source_to_blocklist_1;
source_to_blocklist_1.constellation = constellation_to_blocklist;
source_to_blocklist_1.svid = 0; // documented wildcard for all satellites in this constellation
// IRNSS was added in 2.0. Always attempt to blocklist IRNSS to verify that the new enum is
// supported.
BlocklistedSource source_to_blocklist_2;
source_to_blocklist_2.constellation = GnssConstellationType::IRNSS;
source_to_blocklist_2.svid = 0; // documented wildcard for all satellites in this constellation
sp<IGnssConfiguration> gnss_configuration_hal;
auto status = aidl_gnss_hal_->getExtensionGnssConfiguration(&gnss_configuration_hal);
ASSERT_TRUE(status.isOk());
ASSERT_NE(gnss_configuration_hal, nullptr);
hidl_vec<BlocklistedSource> sources;
sources.resize(2);
sources[0] = source_to_blocklist_1;
sources[1] = source_to_blocklist_2;
status = gnss_configuration_hal->setBlocklist(sources);
ASSERT_TRUE(status.isOk());
// Turns off location
StopAndClearLocations();
// retry and ensure constellation not used
if (aidl_gnss_hal_->getInterfaceVersion() <= 1) {
gnss_cb_->sv_info_list_cbq_.reset();
gnss_cb_->location_cbq_.reset();
} else {
aidl_gnss_cb_->sv_info_list_cbq_.reset();
aidl_gnss_cb_->location_cbq_.reset();
}
StartAndCheckLocations(kLocationsToAwait);
// Tolerate 1 less sv status to handle edge cases in reporting.
int sv_info_list_cbq_size = (aidl_gnss_hal_->getInterfaceVersion() <= 1)
? gnss_cb_->sv_info_list_cbq_.size()
: aidl_gnss_cb_->sv_info_list_cbq_.size();
EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations", sv_info_list_cbq_size,
kLocationsToAwait);
for (int i = 0; i < sv_info_list_cbq_size; ++i) {
if (aidl_gnss_hal_->getInterfaceVersion() <= 1) {
hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
const auto& gnss_sv = sv_info_vec[iSv];
EXPECT_FALSE(
(static_cast<GnssConstellationType>(gnss_sv.v2_0.constellation) ==
source_to_blocklist_1.constellation) &&
(gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
EXPECT_FALSE(
(static_cast<GnssConstellationType>(gnss_sv.v2_0.constellation) ==
source_to_blocklist_2.constellation) &&
(gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
}
} else {
std::vector<IGnssCallback::GnssSvInfo> sv_info_vec;
aidl_gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
const auto& gnss_sv = sv_info_vec[iSv];
EXPECT_FALSE((gnss_sv.constellation == source_to_blocklist_1.constellation) &&
(gnss_sv.svFlag & (int)IGnssCallback::GnssSvFlags::USED_IN_FIX));
EXPECT_FALSE((gnss_sv.constellation == source_to_blocklist_2.constellation) &&
(gnss_sv.svFlag & (int)IGnssCallback::GnssSvFlags::USED_IN_FIX));
}
}
}
// clean up
StopAndClearLocations();
sources.resize(0);
status = gnss_configuration_hal->setBlocklist(sources);
ASSERT_TRUE(status.isOk());
}
/*
* TestAllExtensions.
*/
TEST_P(GnssHalTest, TestAllExtensions) {
if (aidl_gnss_hal_->getInterfaceVersion() <= 1) {
return;
}
sp<IGnssBatching> iGnssBatching;
auto status = aidl_gnss_hal_->getExtensionGnssBatching(&iGnssBatching);
if (status.isOk() && iGnssBatching != nullptr) {
auto gnssBatchingCallback = sp<GnssBatchingCallback>::make();
status = iGnssBatching->init(gnssBatchingCallback);
ASSERT_TRUE(status.isOk());
status = iGnssBatching->cleanup();
ASSERT_TRUE(status.isOk());
}
sp<IGnssGeofence> iGnssGeofence;
status = aidl_gnss_hal_->getExtensionGnssGeofence(&iGnssGeofence);
if (status.isOk() && iGnssGeofence != nullptr) {
auto gnssGeofenceCallback = sp<GnssGeofenceCallback>::make();
status = iGnssGeofence->setCallback(gnssGeofenceCallback);
ASSERT_TRUE(status.isOk());
}
sp<IGnssNavigationMessageInterface> iGnssNavMsgIface;
status = aidl_gnss_hal_->getExtensionGnssNavigationMessage(&iGnssNavMsgIface);
if (status.isOk() && iGnssNavMsgIface != nullptr) {
auto gnssNavMsgCallback = sp<GnssNavigationMessageCallback>::make();
status = iGnssNavMsgIface->setCallback(gnssNavMsgCallback);
ASSERT_TRUE(status.isOk());
status = iGnssNavMsgIface->close();
ASSERT_TRUE(status.isOk());
}
}
/*
* TestAGnssExtension:
* 1. Gets the IAGnss extension.
* 2. Sets AGnssCallback.
* 3. Sets SUPL server host/port.
*/
TEST_P(GnssHalTest, TestAGnssExtension) {
if (aidl_gnss_hal_->getInterfaceVersion() <= 1) {
return;
}
sp<IAGnss> iAGnss;
auto status = aidl_gnss_hal_->getExtensionAGnss(&iAGnss);
ASSERT_TRUE(status.isOk());
ASSERT_TRUE(iAGnss != nullptr);
auto agnssCallback = sp<AGnssCallbackAidl>::make();
status = iAGnss->setCallback(agnssCallback);
ASSERT_TRUE(status.isOk());
// Set SUPL server host/port
status = iAGnss->setServer(AGnssType::SUPL, std::string("supl.google.com"), 7275);
ASSERT_TRUE(status.isOk());
}
/*
* TestAGnssRilExtension:
* 1. Gets the IAGnssRil extension.
* 2. Sets AGnssRilCallback.
* 3. Update network state to connected and then disconnected.
* 4. Sets reference location.
* 5. Injects empty NI message data and verifies that it returns an error.
*/
TEST_P(GnssHalTest, TestAGnssRilExtension) {
if (aidl_gnss_hal_->getInterfaceVersion() <= 1) {
return;
}
sp<IAGnssRil> iAGnssRil;
auto status = aidl_gnss_hal_->getExtensionAGnssRil(&iAGnssRil);
ASSERT_TRUE(status.isOk());
ASSERT_TRUE(iAGnssRil != nullptr);
auto agnssRilCallback = sp<AGnssRilCallbackAidl>::make();
status = iAGnssRil->setCallback(agnssRilCallback);
ASSERT_TRUE(status.isOk());
// Update GNSS HAL that a network has connected.
IAGnssRil::NetworkAttributes networkAttributes;
networkAttributes.networkHandle = 7700664333L;
networkAttributes.isConnected = true;
networkAttributes.capabilities = IAGnssRil::NETWORK_CAPABILITY_NOT_ROAMING;
networkAttributes.apn = "placeholder-apn";
status = iAGnssRil->updateNetworkState(networkAttributes);
ASSERT_TRUE(status.isOk());
// Update GNSS HAL that network has disconnected.
networkAttributes.isConnected = false;
status = iAGnssRil->updateNetworkState(networkAttributes);
ASSERT_TRUE(status.isOk());
// Set RefLocation
IAGnssRil::AGnssRefLocationCellID agnssReflocationCellId;
agnssReflocationCellId.type = IAGnssRil::AGnssRefLocationType::LTE_CELLID;
agnssReflocationCellId.mcc = 466;
agnssReflocationCellId.mnc = 97;
agnssReflocationCellId.lac = 46697;
agnssReflocationCellId.cid = 59168142;
agnssReflocationCellId.pcid = 420;
agnssReflocationCellId.tac = 11460;
IAGnssRil::AGnssRefLocation agnssReflocation;
agnssReflocation.type = IAGnssRil::AGnssRefLocationType::LTE_CELLID;
agnssReflocation.cellID = agnssReflocationCellId;
status = iAGnssRil->setRefLocation(agnssReflocation);
ASSERT_TRUE(status.isOk());
if (aidl_gnss_hal_->getInterfaceVersion() >= 3) {
status = iAGnssRil->injectNiSuplMessageData(std::vector<uint8_t>(), 0);
ASSERT_FALSE(status.isOk());
}
}
/*
* GnssDebugValuesSanityTest:
* Ensures that GnssDebug values make sense.
*/
TEST_P(GnssHalTest, GnssDebugValuesSanityTest) {
if (aidl_gnss_hal_->getInterfaceVersion() <= 1) {
return;
}
sp<IGnssDebug> iGnssDebug;
auto status = aidl_gnss_hal_->getExtensionGnssDebug(&iGnssDebug);
ASSERT_TRUE(status.isOk());
if (!IsAutomotiveDevice()) {
ASSERT_TRUE(iGnssDebug != nullptr);
IGnssDebug::DebugData data;
auto status = iGnssDebug->getDebugData(&data);
ASSERT_TRUE(status.isOk());
if (data.position.valid) {
ASSERT_TRUE(data.position.latitudeDegrees >= -90 &&
data.position.latitudeDegrees <= 90);
ASSERT_TRUE(data.position.longitudeDegrees >= -180 &&
data.position.longitudeDegrees <= 180);
ASSERT_TRUE(data.position.altitudeMeters >= -1000 && // Dead Sea: -414m
data.position.altitudeMeters <= 20000); // Mount Everest: 8850m
ASSERT_TRUE(data.position.speedMetersPerSec >= 0 &&
data.position.speedMetersPerSec <= 600);
ASSERT_TRUE(data.position.bearingDegrees >= -360 &&
data.position.bearingDegrees <= 360);
ASSERT_TRUE(data.position.horizontalAccuracyMeters > 0 &&
data.position.horizontalAccuracyMeters <= 20000000);
ASSERT_TRUE(data.position.verticalAccuracyMeters > 0 &&
data.position.verticalAccuracyMeters <= 20000);
ASSERT_TRUE(data.position.speedAccuracyMetersPerSecond > 0 &&
data.position.speedAccuracyMetersPerSecond <= 500);
ASSERT_TRUE(data.position.bearingAccuracyDegrees > 0 &&
data.position.bearingAccuracyDegrees <= 180);
ASSERT_TRUE(data.position.ageSeconds >= 0);
}
ASSERT_TRUE(data.time.timeEstimateMs >= 1483228800000); // Jan 01 2017 00:00:00 GMT.
ASSERT_TRUE(data.time.timeUncertaintyNs > 0);
ASSERT_TRUE(data.time.frequencyUncertaintyNsPerSec > 0 &&
data.time.frequencyUncertaintyNsPerSec <= 2.0e5); // 200 ppm
}
}
/*
* TestGnssVisibilityControlExtension:
* 1. Gets the IGnssVisibilityControl extension.
* 2. Sets GnssVisibilityControlCallback
* 3. Sets proxy apps
*/
TEST_P(GnssHalTest, TestGnssVisibilityControlExtension) {
if (aidl_gnss_hal_->getInterfaceVersion() <= 1) {
return;
}
sp<IGnssVisibilityControl> iGnssVisibilityControl;
auto status = aidl_gnss_hal_->getExtensionGnssVisibilityControl(&iGnssVisibilityControl);
ASSERT_TRUE(status.isOk());
ASSERT_TRUE(iGnssVisibilityControl != nullptr);
auto gnssVisibilityControlCallback = sp<GnssVisibilityControlCallback>::make();
status = iGnssVisibilityControl->setCallback(gnssVisibilityControlCallback);
ASSERT_TRUE(status.isOk());
std::vector<std::string> proxyApps{std::string("com.example.ims"),
std::string("com.example.mdt")};
status = iGnssVisibilityControl->enableNfwLocationAccess(proxyApps);
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 = 5;
sp<IGnssMeasurementInterface> iGnssMeasurement;
auto status = aidl_gnss_hal_->getExtensionGnssMeasurement(&iGnssMeasurement);
ASSERT_TRUE(status.isOk());
ASSERT_TRUE(iGnssMeasurement != nullptr);
auto callback = sp<GnssMeasurementCallbackAidl>::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.size() > 0);
for (const auto& gnssAgc : lastMeasurement.gnssAgcs) {
ASSERT_TRUE(gnssAgc.carrierFrequencyHz >= 0);
}
}
status = iGnssMeasurement->close();
ASSERT_TRUE(status.isOk());
}
/*
* TestGnssAntennaInfo:
* Sets a GnssAntennaInfoCallback, waits for report, and verifies
* 1. phaseCenterOffsetCoordinateMillimeters is valid
* 2. phaseCenterOffsetCoordinateUncertaintyMillimeters is valid.
* PhaseCenterVariationCorrections and SignalGainCorrections are optional.
*/
TEST_P(GnssHalTest, TestGnssAntennaInfo) {
if (aidl_gnss_hal_->getInterfaceVersion() <= 1) {
return;
}
const int kAntennaInfoTimeoutSeconds = 2;
sp<IGnssAntennaInfo> iGnssAntennaInfo;
auto status = aidl_gnss_hal_->getExtensionGnssAntennaInfo(&iGnssAntennaInfo);
ASSERT_TRUE(status.isOk());
if (!(aidl_gnss_cb_->last_capabilities_ & (int)GnssCallbackAidl::CAPABILITY_ANTENNA_INFO) ||
iGnssAntennaInfo == nullptr) {
ALOGD("GnssAntennaInfo AIDL is not supported.");
return;
}
auto callback = sp<GnssAntennaInfoCallbackAidl>::make();
status = iGnssAntennaInfo->setCallback(callback);
ASSERT_TRUE(status.isOk());
std::vector<IGnssAntennaInfoCallback::GnssAntennaInfo> antennaInfos;
ASSERT_TRUE(callback->antenna_info_cbq_.retrieve(antennaInfos, kAntennaInfoTimeoutSeconds));
EXPECT_EQ(callback->antenna_info_cbq_.calledCount(), 1);
ASSERT_TRUE(antennaInfos.size() > 0);
for (auto antennaInfo : antennaInfos) {
// Remaining fields are optional
if (!antennaInfo.phaseCenterVariationCorrectionMillimeters.empty()) {
int numRows = antennaInfo.phaseCenterVariationCorrectionMillimeters.size();
int numColumns = antennaInfo.phaseCenterVariationCorrectionMillimeters[0].row.size();
// Must have at least 1 row and 2 columns
ASSERT_TRUE(numRows >= 1 && numColumns >= 2);
// Corrections and uncertainties must have same dimensions
ASSERT_TRUE(antennaInfo.phaseCenterVariationCorrectionMillimeters.size() ==
antennaInfo.phaseCenterVariationCorrectionUncertaintyMillimeters.size());
ASSERT_TRUE(
antennaInfo.phaseCenterVariationCorrectionMillimeters[0].row.size() ==
antennaInfo.phaseCenterVariationCorrectionUncertaintyMillimeters[0].row.size());
// Must be rectangular
for (auto row : antennaInfo.phaseCenterVariationCorrectionMillimeters) {
ASSERT_TRUE(row.row.size() == numColumns);
}
for (auto row : antennaInfo.phaseCenterVariationCorrectionUncertaintyMillimeters) {
ASSERT_TRUE(row.row.size() == numColumns);
}
}
if (!antennaInfo.signalGainCorrectionDbi.empty()) {
int numRows = antennaInfo.signalGainCorrectionDbi.size();
int numColumns = antennaInfo.signalGainCorrectionUncertaintyDbi[0].row.size();
// Must have at least 1 row and 2 columns
ASSERT_TRUE(numRows >= 1 && numColumns >= 2);
// Corrections and uncertainties must have same dimensions
ASSERT_TRUE(antennaInfo.signalGainCorrectionDbi.size() ==
antennaInfo.signalGainCorrectionUncertaintyDbi.size());
ASSERT_TRUE(antennaInfo.signalGainCorrectionDbi[0].row.size() ==
antennaInfo.signalGainCorrectionUncertaintyDbi[0].row.size());
// Must be rectangular
for (auto row : antennaInfo.signalGainCorrectionDbi) {
ASSERT_TRUE(row.row.size() == numColumns);
}
for (auto row : antennaInfo.signalGainCorrectionUncertaintyDbi) {
ASSERT_TRUE(row.row.size() == numColumns);
}
}
}
iGnssAntennaInfo->close();
}
/*
* TestGnssMeasurementCorrections:
* If measurement corrections capability is supported, verifies that the measurement corrections
* capabilities are reported and the mandatory LOS_SATS or the EXCESS_PATH_LENGTH
* capability flag is set.
*/
TEST_P(GnssHalTest, TestGnssMeasurementCorrections) {
if (aidl_gnss_hal_->getInterfaceVersion() <= 1) {
return;
}
if (!(aidl_gnss_cb_->last_capabilities_ &
(int)GnssCallbackAidl::CAPABILITY_MEASUREMENT_CORRECTIONS)) {
return;
}
sp<IMeasurementCorrectionsInterface> iMeasurementCorrectionsAidl;
auto status = aidl_gnss_hal_->getExtensionMeasurementCorrections(&iMeasurementCorrectionsAidl);
ASSERT_TRUE(status.isOk());
ASSERT_TRUE(iMeasurementCorrectionsAidl != nullptr);
// Setup measurement corrections callback.
auto gnssMeasurementCorrectionsCallback = sp<MeasurementCorrectionsCallback>::make();
status = iMeasurementCorrectionsAidl->setCallback(gnssMeasurementCorrectionsCallback);
ASSERT_TRUE(status.isOk());
const int kTimeoutSec = 5;
EXPECT_TRUE(gnssMeasurementCorrectionsCallback->capabilities_cbq_.retrieve(
gnssMeasurementCorrectionsCallback->last_capabilities_, kTimeoutSec));
ASSERT_TRUE(gnssMeasurementCorrectionsCallback->capabilities_cbq_.calledCount() > 0);
ASSERT_TRUE((gnssMeasurementCorrectionsCallback->last_capabilities_ &
(MeasurementCorrectionsCallback::CAPABILITY_LOS_SATS |
MeasurementCorrectionsCallback::CAPABILITY_EXCESS_PATH_LENGTH)) != 0);
// Set a mock MeasurementCorrections.
status = iMeasurementCorrectionsAidl->setCorrections(
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 at intervals
* 2. Verify measurement are received at expected intervals
* 3. Verify status are reported at expected intervals
*/
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> measurementDeltas;
std::vector<int> svInfoListTimestampsDeltas;
collectMeasurementIntervals(callback, numEvents[i], /* timeoutSeconds= */ 10,
measurementDeltas);
if (aidl_gnss_hal_->getInterfaceVersion() >= 3) {
collectSvInfoListTimestamps(numEvents[i], /* timeoutSeconds= */ 10,
svInfoListTimestampsDeltas);
}
status = iGnssMeasurement->close();
ASSERT_TRUE(status.isOk());
assertMeanAndStdev(intervals[i], measurementDeltas);
if (aidl_gnss_hal_->getInterfaceVersion() >= 3) {
assertMeanAndStdev(intervals[i], svInfoListTimestampsDeltas);
EXPECT_TRUE(aidl_gnss_cb_->sv_info_list_cbq_.size() > 0);
}
}
}
/*
* TestGnssMeasurementIntervals_LocationOnBeforeMeasurement:
* 1. Start location at 1s.
* 2. Start measurement at 2s. Verify measurements are received at 1s.
* 3. Stop measurement. Stop location.
*/
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_LocationOnAfterMeasurement:
* 1. Start measurement at 2s
* 2. Start location at 1s. Verify measurements are received at 1s
* 3. Stop location. Verify measurements are received at 2s
* 4. Stop measurement
*/
TEST_P(GnssHalTest, TestGnssMeasurementIntervals_LocationOnAfterMeasurement) {
if (aidl_gnss_hal_->getInterfaceVersion() <= 1) {
return;
}
const int kFirstMeasTimeoutSec = 10;
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 measurement first and then start location
ALOGD("TestGnssMeasurementIntervals_LocationOnAfterMeasurement");
for (auto& intervalMs : intervals) {
auto callback = sp<GnssMeasurementCallbackAidl>::make();
startMeasurementWithInterval(intervalMs, iGnssMeasurement, callback);
// Start location and verify the measurements are received at 1Hz
StartAndCheckFirstLocation(locationIntervalMs, /* lowPowerMode= */ false);
std::vector<int> deltas;
collectMeasurementIntervals(callback, /*numEvents=*/10, kFirstMeasTimeoutSec, deltas);
assertMeanAndStdev(locationIntervalMs, deltas);
// Stop location request and verify the measurements are received at 2s intervals
StopAndClearLocations();
callback->gnss_data_cbq_.reset();
deltas.clear();
collectMeasurementIntervals(callback, /*numEvents=*/5, kFirstMeasTimeoutSec, deltas);
assertMeanAndStdev(intervalMs, deltas);
status = iGnssMeasurement->close();
ASSERT_TRUE(status.isOk());
}
}
/*
* TestGnssMeasurementIntervals_changeIntervals:
* This test ensures setCallback() can be called consecutively without close().
* 1. Start measurement with 20s interval and wait for 1 measurement.
* 2. Start measurement with 1s interval and wait for 5 measurements.
* Verify the measurements were received at 1Hz.
* 3. Start measurement with 2s interval and wait for 5 measurements.
* Verify the measurements were received at 2s intervals.
*/
TEST_P(GnssHalTest, TestGnssMeasurementIntervals_changeIntervals) {
if (aidl_gnss_hal_->getInterfaceVersion() <= 2) {
return;
}
const int kFirstGnssMeasurementTimeoutSeconds = 10;
sp<IGnssMeasurementInterface> iGnssMeasurement;
auto status = aidl_gnss_hal_->getExtensionGnssMeasurement(&iGnssMeasurement);
ASSERT_TRUE(status.isOk());
ASSERT_TRUE(iGnssMeasurement != nullptr);
auto callback = sp<GnssMeasurementCallbackAidl>::make();
std::vector<int> deltas;
// setCallback at 20s interval and wait for 1 measurement
startMeasurementWithInterval(20000, iGnssMeasurement, callback);
collectMeasurementIntervals(callback, /* numEvents= */ 1, kFirstGnssMeasurementTimeoutSeconds,
deltas);
// setCallback at 1s interval and wait for 5 measurements
callback->gnss_data_cbq_.reset();
deltas.clear();
startMeasurementWithInterval(1000, iGnssMeasurement, callback);
collectMeasurementIntervals(callback, /* numEvents= */ 5, kFirstGnssMeasurementTimeoutSeconds,
deltas);
// verify the measurements were received at 1Hz
assertMeanAndStdev(1000, deltas);
// setCallback at 2s interval and wait for 5 measurements
callback->gnss_data_cbq_.reset();
deltas.clear();
startMeasurementWithInterval(2000, iGnssMeasurement, callback);
collectMeasurementIntervals(callback, /* numEvents= */ 5, kFirstGnssMeasurementTimeoutSeconds,
deltas);
// verify the measurements were received at 2s intervals
assertMeanAndStdev(2000, deltas);
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<bool> isFullTrackingList({true, false, true});
sp<IGnssMeasurementInterface> iGnssMeasurement;
auto status = aidl_gnss_hal_->getExtensionGnssMeasurement(&iGnssMeasurement);
ASSERT_TRUE(status.isOk());
ASSERT_TRUE(iGnssMeasurement != nullptr);
ALOGD("TestGnssMeasurementIsFullTracking");
auto callback = sp<GnssMeasurementCallbackAidl>::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());
}
/*
* TestAccumulatedDeltaRange:
* 1. Gets the GnssMeasurementExtension and verifies that it returns a non-null extension.
* 2. Start measurement with 1s interval and wait for up to 15 measurements.
* 3. Verify at least one measurement has a valid AccumulatedDeltaRange state.
*/
TEST_P(GnssHalTest, TestAccumulatedDeltaRange) {
if (aidl_gnss_hal_->getInterfaceVersion() <= 2) {
return;
}
if ((aidl_gnss_cb_->last_capabilities_ & IGnssCallback::CAPABILITY_ACCUMULATED_DELTA_RANGE) ==
0) {
return;
}
ALOGD("TestAccumulatedDeltaRange");
auto callback = sp<GnssMeasurementCallbackAidl>::make();
sp<IGnssMeasurementInterface> iGnssMeasurement;
auto status = aidl_gnss_hal_->getExtensionGnssMeasurement(&iGnssMeasurement);
ASSERT_TRUE(status.isOk());
ASSERT_TRUE(iGnssMeasurement != nullptr);
IGnssMeasurementInterface::Options options;
options.intervalMs = 1000;
options.enableFullTracking = true;
status = iGnssMeasurement->setCallbackWithOptions(callback, options);
ASSERT_TRUE(status.isOk());
bool accumulatedDeltaRangeFound = false;
const int kNumMeasurementEvents = 15;
// setCallback at 1s interval and wait for 15 measurements
for (int i = 0; i < kNumMeasurementEvents; i++) {
GnssData lastGnssData;
ASSERT_TRUE(callback->gnss_data_cbq_.retrieve(lastGnssData, 10));
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) {
if ((measurement.accumulatedDeltaRangeState & measurement.ADR_STATE_VALID) > 0) {
accumulatedDeltaRangeFound = true;
break;
}
}
if (accumulatedDeltaRangeFound) break;
}
ASSERT_TRUE(accumulatedDeltaRangeFound);
status = iGnssMeasurement->close();
ASSERT_TRUE(status.isOk());
}