Merge "Verify there are no more current calls" into qt-dev am: 1f12b5323a
am: 45fa5dacd9
Change-Id: Icedd28ef8734308638cd0d01e21d80fba765aeb9
diff --git a/gnss/1.1/vts/functional/gnss_hal_test.cpp b/gnss/1.1/vts/functional/gnss_hal_test.cpp
index 381ac1d..f3b376e 100644
--- a/gnss/1.1/vts/functional/gnss_hal_test.cpp
+++ b/gnss/1.1/vts/functional/gnss_hal_test.cpp
@@ -16,10 +16,16 @@
#define LOG_TAG "GnssHalTest"
+#include <android/hidl/manager/1.2/IServiceManager.h>
+#include <hidl/ServiceManagement.h>
+
#include <gnss_hal_test.h>
#include <chrono>
#include "Utils.h"
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+
using ::android::hardware::gnss::common::Utils;
// Implementations for the main test class for GNSS HAL
@@ -149,6 +155,28 @@
}
}
+bool GnssHalTest::IsGnssHalVersion_1_1() const {
+ using ::android::hidl::manager::V1_2::IServiceManager;
+ sp<IServiceManager> manager = ::android::hardware::defaultServiceManager1_2();
+
+ bool hasGnssHalVersion_1_1 = false;
+ manager->listManifestByInterface(
+ "android.hardware.gnss@1.1::IGnss",
+ [&hasGnssHalVersion_1_1](const hidl_vec<hidl_string>& registered) {
+ ASSERT_EQ(1, registered.size());
+ hasGnssHalVersion_1_1 = true;
+ });
+
+ bool hasGnssHalVersion_2_0 = false;
+ manager->listManifestByInterface(
+ "android.hardware.gnss@2.0::IGnss",
+ [&hasGnssHalVersion_2_0](const hidl_vec<hidl_string>& registered) {
+ hasGnssHalVersion_2_0 = registered.size() != 0;
+ });
+
+ return hasGnssHalVersion_1_1 && !hasGnssHalVersion_2_0;
+}
+
void GnssHalTest::notify() {
std::unique_lock<std::mutex> lock(mtx_);
notify_count_++;
diff --git a/gnss/1.1/vts/functional/gnss_hal_test.h b/gnss/1.1/vts/functional/gnss_hal_test.h
index 64478b5..84a9f84 100644
--- a/gnss/1.1/vts/functional/gnss_hal_test.h
+++ b/gnss/1.1/vts/functional/gnss_hal_test.h
@@ -145,6 +145,12 @@
*/
void SetPositionMode(const int min_interval_msec, const bool low_power_mode);
+ /*
+ * IsGnssHalVersion_1_1:
+ * returns true if the GNSS HAL version is exactly 1.1.
+ */
+ bool IsGnssHalVersion_1_1() const;
+
sp<IGnss> gnss_hal_; // GNSS HAL to call into
sp<IGnssCallback> gnss_cb_; // Primary callback interface
diff --git a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
index 4016a5a..ee236ba 100644
--- a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
@@ -66,6 +66,11 @@
* each received location.
*/
TEST_F(GnssHalTest, GetLocationLowPower) {
+ if (!IsGnssHalVersion_1_1()) {
+ ALOGI("Test GetLocationLowPower skipped. GNSS HAL version is greater than 1.1.");
+ return;
+ }
+
const int kMinIntervalMsec = 5000;
const int kLocationTimeoutSubsequentSec = (kMinIntervalMsec / 1000) * 2;
const int kNoLocationPeriodSec = (kMinIntervalMsec / 1000) / 2;
@@ -209,6 +214,11 @@
* formerly strongest satellite
*/
TEST_F(GnssHalTest, BlacklistIndividualSatellites) {
+ if (!IsGnssHalVersion_1_1()) {
+ ALOGI("Test BlacklistIndividualSatellites skipped. GNSS HAL version is greater than 1.1.");
+ return;
+ }
+
const int kLocationsToAwait = 3;
const int kRetriesToUnBlacklist = 10;
@@ -330,6 +340,11 @@
* 4a & b) Clean up by turning off location, and send in empty blacklist.
*/
TEST_F(GnssHalTest, BlacklistConstellation) {
+ if (!IsGnssHalVersion_1_1()) {
+ ALOGI("Test BlacklistConstellation skipped. GNSS HAL version is greater than 1.1.");
+ return;
+ }
+
const int kLocationsToAwait = 3;
StartAndCheckLocations(kLocationsToAwait);
diff --git a/gnss/2.0/vts/functional/VtsHalGnssV2_0TargetTest.cpp b/gnss/2.0/vts/functional/VtsHalGnssV2_0TargetTest.cpp
index a8e40ba..ae36c50 100644
--- a/gnss/2.0/vts/functional/VtsHalGnssV2_0TargetTest.cpp
+++ b/gnss/2.0/vts/functional/VtsHalGnssV2_0TargetTest.cpp
@@ -23,7 +23,6 @@
::testing::AddGlobalTestEnvironment(GnssHidlEnvironment::Instance());
::testing::InitGoogleTest(&argc, argv);
GnssHidlEnvironment::Instance()->init(&argc, argv);
- // TODO (b/122463165): Expand coverage to include 1.1 and 1.0 VTS tests.
int status = RUN_ALL_TESTS();
ALOGI("Test result = %d", status);
return status;
diff --git a/gnss/2.0/vts/functional/gnss_hal_test.cpp b/gnss/2.0/vts/functional/gnss_hal_test.cpp
index a9f858c..14ae43c 100644
--- a/gnss/2.0/vts/functional/gnss_hal_test.cpp
+++ b/gnss/2.0/vts/functional/gnss_hal_test.cpp
@@ -152,7 +152,7 @@
name_cbq_("name"),
capabilities_cbq_("capabilities"),
location_cbq_("location"),
- sv_info_cbq_("sv_info") {}
+ sv_info_list_cbq_("sv_info") {}
Return<void> GnssHalTest::GnssCallback::gnssSetSystemInfoCb(
const IGnssCallback_1_0::GnssSystemInfo& info) {
@@ -204,7 +204,7 @@
Return<void> GnssHalTest::GnssCallback::gnssSvStatusCb_2_0(
const hidl_vec<IGnssCallback_2_0::GnssSvInfo>& svInfoList) {
ALOGI("gnssSvStatusCb_2_0. Size = %d", (int)svInfoList.size());
- sv_info_cbq_.store(svInfoList);
+ sv_info_list_cbq_.store(svInfoList);
return Void();
}
diff --git a/gnss/2.0/vts/functional/gnss_hal_test.h b/gnss/2.0/vts/functional/gnss_hal_test.h
index 05e37d3..90a7866 100644
--- a/gnss/2.0/vts/functional/gnss_hal_test.h
+++ b/gnss/2.0/vts/functional/gnss_hal_test.h
@@ -23,6 +23,7 @@
#include <condition_variable>
#include <deque>
+#include <list>
#include <mutex>
using android::hardware::hidl_vec;
@@ -85,6 +86,14 @@
*/
bool retrieve(T& event, int timeout_seconds);
+ /*
+ * Removes parameter count number of callack events at the front of the queue, stores
+ * them in event_list parameter and returns the number of events retrieved. Waits up to
+ * timeout_seconds to retrieve each event. If timeout occurs, it returns the number of
+ * items retrieved which will be less than count.
+ */
+ int retrieve(list<T>& event_list, int count, int timeout_seconds);
+
/* Returns the number of events pending to be retrieved from the callback event queue. */
int size() const;
@@ -117,7 +126,7 @@
CallbackQueue<android::hardware::hidl_string> name_cbq_;
CallbackQueue<uint32_t> capabilities_cbq_;
CallbackQueue<GnssLocation_2_0> location_cbq_;
- CallbackQueue<hidl_vec<IGnssCallback_2_0::GnssSvInfo>> sv_info_cbq_;
+ CallbackQueue<hidl_vec<IGnssCallback_2_0::GnssSvInfo>> sv_info_list_cbq_;
GnssCallback();
virtual ~GnssCallback() = default;
@@ -265,6 +274,19 @@
}
template <class T>
+int GnssHalTest::CallbackQueue<T>::retrieve(list<T>& event_list, int count, int timeout_seconds) {
+ for (int i = 0; i < count; ++i) {
+ T event;
+ if (!retrieve(event, timeout_seconds)) {
+ return i;
+ }
+ event_list.push_back(event);
+ }
+
+ return count;
+}
+
+template <class T>
int GnssHalTest::CallbackQueue<T>::size() const {
std::unique_lock<std::recursive_mutex> lock(mtx_);
return events_.size();
diff --git a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
index 155afd6..39736cc 100644
--- a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
@@ -23,7 +23,10 @@
using android::hardware::hidl_string;
using android::hardware::hidl_vec;
+using GnssConstellationType_2_0 = android::hardware::gnss::V2_0::GnssConstellationType;
+using GnssConstellationType_1_0 = android::hardware::gnss::V1_0::GnssConstellationType;
using IGnssConfiguration_2_0 = android::hardware::gnss::V2_0::IGnssConfiguration;
+using IGnssConfiguration_1_1 = android::hardware::gnss::V1_1::IGnssConfiguration;
using IAGnssRil_2_0 = android::hardware::gnss::V2_0::IAGnssRil;
using IGnssMeasurement_2_0 = android::hardware::gnss::V2_0::IGnssMeasurement;
using IGnssMeasurement_1_1 = android::hardware::gnss::V1_1::IGnssMeasurement;
@@ -33,15 +36,12 @@
using IAGnss_2_0 = android::hardware::gnss::V2_0::IAGnss;
using IAGnss_1_0 = android::hardware::gnss::V1_0::IAGnss;
using IAGnssCallback_2_0 = android::hardware::gnss::V2_0::IAGnssCallback;
-using IGnssBatching_V1_0 = android::hardware::gnss::V1_0::IGnssBatching;
-using IGnssBatching_V2_0 = android::hardware::gnss::V2_0::IGnssBatching;
using android::hardware::gnss::common::Utils;
using android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections;
using android::hardware::gnss::measurement_corrections::V1_0::MeasurementCorrections;
using android::hardware::gnss::V1_0::IGnssNi;
using android::hardware::gnss::V2_0::ElapsedRealtimeFlags;
-using android::hardware::gnss::V2_0::GnssConstellationType;
using android::hardware::gnss::V2_0::IGnssCallback;
using android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl;
@@ -209,9 +209,9 @@
// Verify ConstellationType is valid.
ASSERT_TRUE(static_cast<uint8_t>(measurement.constellation) >=
- static_cast<uint8_t>(GnssConstellationType::UNKNOWN) &&
+ static_cast<uint8_t>(GnssConstellationType_2_0::UNKNOWN) &&
static_cast<uint8_t>(measurement.constellation) <=
- static_cast<uint8_t>(GnssConstellationType::IRNSS));
+ static_cast<uint8_t>(GnssConstellationType_2_0::IRNSS));
// Verify State is valid.
ASSERT_TRUE(
@@ -414,3 +414,423 @@
auto gnssBatching_2_0 = gnss_hal_->getExtensionGnssBatching_2_0();
ASSERT_TRUE(gnssBatching_2_0.isOk());
}
+
+/*
+ * 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_F(GnssHalTest, GetLocationLowPower) {
+ if (!(gnss_cb_->last_capabilities_ & IGnssCallback::Capabilities::LOW_POWER_MODE)) {
+ ALOGI("Test GetLocationLowPower skipped. LOW_POWER_MODE capability not supported.");
+ 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
+ gnss_cb_->location_cbq_.reset();
+ StartAndCheckLocations(kLocationsToCheck);
+ StopAndClearLocations();
+ gnss_cb_->location_cbq_.reset();
+
+ // Start of Low Power Mode test
+ SetPositionMode(kMinIntervalMsec, kLowPowerMode);
+
+ // Don't expect true - as without AGPS access
+ if (!StartAndCheckFirstLocation()) {
+ 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
+
+ gnss_cb_->location_cbq_.retrieve(gnss_cb_->last_location_, kNoLocationPeriodSec);
+ const int locationCalledCount = 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) && (locationCalledCount == 2)) {
+ CheckLocation(gnss_cb_->last_location_, true);
+ continue; // restart the quiet wait period after this too-fast location
+ }
+ EXPECT_LE(locationCalledCount, i);
+ if (locationCalledCount != i) {
+ ALOGW("GetLocationLowPower test - not enough locations received. %d vs. %d expected ",
+ locationCalledCount, i);
+ }
+
+ if (!gnss_cb_->location_cbq_.retrieve(
+ gnss_cb_->last_location_,
+ kLocationTimeoutSubsequentSec - kNoLocationPeriodSec)) {
+ ALOGW("GetLocationLowPower test - timeout awaiting location %d", i);
+ } else {
+ CheckLocation(gnss_cb_->last_location_, true);
+ }
+ }
+
+ StopAndClearLocations();
+}
+
+/*
+ * MapConstellationType:
+ * Given a GnssConstellationType_2_0 type constellation, maps to its equivalent
+ * GnssConstellationType_1_0 type constellation. For constellations that do not have
+ * an equivalent value, maps to GnssConstellationType_1_0::UNKNOWN
+ */
+GnssConstellationType_1_0 MapConstellationType(GnssConstellationType_2_0 constellation) {
+ switch (constellation) {
+ case GnssConstellationType_2_0::GPS:
+ return GnssConstellationType_1_0::GPS;
+ case GnssConstellationType_2_0::SBAS:
+ return GnssConstellationType_1_0::SBAS;
+ case GnssConstellationType_2_0::GLONASS:
+ return GnssConstellationType_1_0::GLONASS;
+ case GnssConstellationType_2_0::QZSS:
+ return GnssConstellationType_1_0::QZSS;
+ case GnssConstellationType_2_0::BEIDOU:
+ return GnssConstellationType_1_0::BEIDOU;
+ case GnssConstellationType_2_0::GALILEO:
+ return GnssConstellationType_1_0::GALILEO;
+ default:
+ return GnssConstellationType_1_0::UNKNOWN;
+ }
+}
+
+/*
+ * FindStrongFrequentNonGpsSource:
+ *
+ * Search through a GnssSvStatus list for the strongest non-GPS satellite observed enough times
+ *
+ * returns the strongest source,
+ * or a source with constellation == UNKNOWN if none are found sufficient times
+ */
+IGnssConfiguration_1_1::BlacklistedSource FindStrongFrequentNonGpsSource(
+ const list<hidl_vec<IGnssCallback_2_0::GnssSvInfo>>& sv_info_lists,
+ const int min_observations) {
+ struct ComparableBlacklistedSource {
+ IGnssConfiguration_1_1::BlacklistedSource id;
+
+ ComparableBlacklistedSource() {
+ id.constellation = GnssConstellationType_1_0::UNKNOWN;
+ id.svid = 0;
+ }
+
+ bool operator<(const ComparableBlacklistedSource& compare) const {
+ return ((id.svid < compare.id.svid) || ((id.svid == compare.id.svid) &&
+ (id.constellation < compare.id.constellation)));
+ }
+ };
+
+ struct SignalCounts {
+ int observations;
+ float max_cn0_dbhz;
+ };
+
+ std::map<ComparableBlacklistedSource, SignalCounts> mapSignals;
+
+ for (const auto& sv_info_list : sv_info_lists) {
+ for (IGnssCallback_2_0::GnssSvInfo sv_info : sv_info_list) {
+ if ((sv_info.v1_0.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX) &&
+ (sv_info.constellation != GnssConstellationType_2_0::IRNSS) &&
+ (sv_info.constellation != GnssConstellationType_2_0::GPS)) {
+ ComparableBlacklistedSource source;
+ source.id.svid = sv_info.v1_0.svid;
+ source.id.constellation = MapConstellationType(sv_info.constellation);
+
+ const auto& itSignal = mapSignals.find(source);
+ if (itSignal == mapSignals.end()) {
+ SignalCounts counts;
+ counts.observations = 1;
+ counts.max_cn0_dbhz = sv_info.v1_0.cN0Dbhz;
+ mapSignals.insert(
+ std::pair<ComparableBlacklistedSource, SignalCounts>(source, counts));
+ } else {
+ itSignal->second.observations++;
+ if (itSignal->second.max_cn0_dbhz < sv_info.v1_0.cN0Dbhz) {
+ itSignal->second.max_cn0_dbhz = sv_info.v1_0.cN0Dbhz;
+ }
+ }
+ }
+ }
+ }
+
+ float max_cn0_dbhz_with_sufficient_count = 0.;
+ int total_observation_count = 0;
+ int blacklisted_source_count_observation = 0;
+
+ ComparableBlacklistedSource source_to_blacklist; // initializes to zero = UNKNOWN constellation
+ for (auto const& pairSignal : mapSignals) {
+ total_observation_count += pairSignal.second.observations;
+ if ((pairSignal.second.observations >= min_observations) &&
+ (pairSignal.second.max_cn0_dbhz > max_cn0_dbhz_with_sufficient_count)) {
+ source_to_blacklist = pairSignal.first;
+ blacklisted_source_count_observation = pairSignal.second.observations;
+ max_cn0_dbhz_with_sufficient_count = pairSignal.second.max_cn0_dbhz;
+ }
+ }
+ ALOGD("Among %d observations, chose svid %d, constellation %d, "
+ "with %d observations at %.1f max CNo",
+ total_observation_count, source_to_blacklist.id.svid,
+ (int)source_to_blacklist.id.constellation, blacklisted_source_count_observation,
+ max_cn0_dbhz_with_sufficient_count);
+
+ return source_to_blacklist.id;
+}
+
+/*
+ * BlacklistIndividualSatellites:
+ *
+ * 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 blacklists 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 blacklist.
+ * 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_F(GnssHalTest, BlacklistIndividualSatellites) {
+ if (!(gnss_cb_->last_capabilities_ & IGnssCallback::Capabilities::SATELLITE_BLACKLIST)) {
+ ALOGI("Test BlacklistIndividualSatellites skipped. SATELLITE_BLACKLIST capability"
+ " not supported.");
+ return;
+ }
+
+ const int kLocationsToAwait = 3;
+ const int kRetriesToUnBlacklist = 10;
+
+ gnss_cb_->location_cbq_.reset();
+ StartAndCheckLocations(kLocationsToAwait);
+ 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 + 1, kLocationsToAwait);
+ ALOGD("Observed %d GnssSvStatus, 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 kGnssSvStatusTimeout = 2;
+ list<hidl_vec<IGnssCallback_2_0::GnssSvInfo>> sv_info_lists;
+ int count = gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_lists, sv_info_list_cbq_size,
+ kGnssSvStatusTimeout);
+ ASSERT_EQ(count, sv_info_list_cbq_size);
+
+ IGnssConfiguration_1_1::BlacklistedSource source_to_blacklist =
+ FindStrongFrequentNonGpsSource(sv_info_lists, kLocationsToAwait - 1);
+
+ if (source_to_blacklist.constellation == GnssConstellationType_1_0::UNKNOWN) {
+ // Cannot find a non-GPS satellite. Let the test pass.
+ return;
+ }
+
+ // Stop locations, blacklist the common SV
+ StopAndClearLocations();
+
+ auto gnss_configuration_hal_return = gnss_hal_->getExtensionGnssConfiguration_1_1();
+ ASSERT_TRUE(gnss_configuration_hal_return.isOk());
+ sp<IGnssConfiguration_1_1> gnss_configuration_hal = gnss_configuration_hal_return;
+ ASSERT_NE(gnss_configuration_hal, nullptr);
+
+ hidl_vec<IGnssConfiguration_1_1::BlacklistedSource> sources;
+ sources.resize(1);
+ sources[0] = source_to_blacklist;
+
+ auto result = gnss_configuration_hal->setBlacklist(sources);
+ ASSERT_TRUE(result.isOk());
+ EXPECT_TRUE(result);
+
+ // retry and ensure satellite not used
+ gnss_cb_->sv_info_list_cbq_.reset();
+
+ gnss_cb_->location_cbq_.reset();
+ StartAndCheckLocations(kLocationsToAwait);
+
+ // early exit if test is being run with insufficient signal
+ location_called_count = 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 = gnss_cb_->sv_info_list_cbq_.size();
+ EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
+ ALOGD("Observed %d GnssSvStatus, 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) {
+ hidl_vec<IGnssCallback_2_0::GnssSvInfo> sv_info_list;
+ gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_list, kGnssSvStatusTimeout);
+ for (IGnssCallback_2_0::GnssSvInfo sv_info : sv_info_list) {
+ auto constellation = MapConstellationType(sv_info.constellation);
+ EXPECT_FALSE((sv_info.v1_0.svid == source_to_blacklist.svid) &&
+ (constellation == source_to_blacklist.constellation) &&
+ (sv_info.v1_0.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX));
+ }
+ }
+
+ // clear blacklist and restart - this time updating the blacklist while location is still on
+ sources.resize(0);
+
+ result = gnss_configuration_hal->setBlacklist(sources);
+ ASSERT_TRUE(result.isOk());
+ EXPECT_TRUE(result);
+
+ bool strongest_sv_is_reobserved = false;
+ // do several loops awaiting a few locations, allowing non-immediate reacquisition strategies
+ int unblacklist_loops_remaining = kRetriesToUnBlacklist;
+ while (!strongest_sv_is_reobserved && (unblacklist_loops_remaining-- > 0)) {
+ StopAndClearLocations();
+ gnss_cb_->sv_info_list_cbq_.reset();
+
+ gnss_cb_->location_cbq_.reset();
+ StartAndCheckLocations(kLocationsToAwait);
+
+ // early exit loop if test is being run with insufficient signal
+ location_called_count = 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 = gnss_cb_->sv_info_list_cbq_.size();
+ EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
+ ALOGD("Clear blacklist, observed %d GnssSvStatus, while awaiting %d Locations"
+ ", tries remaining %d",
+ sv_info_list_cbq_size, kLocationsToAwait, unblacklist_loops_remaining);
+
+ for (int i = 0; i < sv_info_list_cbq_size; ++i) {
+ hidl_vec<IGnssCallback_2_0::GnssSvInfo> sv_info_list;
+ gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_list, kGnssSvStatusTimeout);
+ for (IGnssCallback_2_0::GnssSvInfo sv_info : sv_info_list) {
+ auto constellation = MapConstellationType(sv_info.constellation);
+ if ((sv_info.v1_0.svid == source_to_blacklist.svid) &&
+ (constellation == source_to_blacklist.constellation) &&
+ (sv_info.v1_0.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX)) {
+ strongest_sv_is_reobserved = true;
+ break;
+ }
+ }
+ if (strongest_sv_is_reobserved) break;
+ }
+ }
+ EXPECT_TRUE(strongest_sv_is_reobserved);
+ StopAndClearLocations();
+}
+
+/*
+ * BlacklistConstellation:
+ *
+ * 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 blacklist 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 blacklist.
+ */
+TEST_F(GnssHalTest, BlacklistConstellation) {
+ if (!(gnss_cb_->last_capabilities_ & IGnssCallback::Capabilities::SATELLITE_BLACKLIST)) {
+ ALOGI("Test BlacklistConstellation skipped. SATELLITE_BLACKLIST capability not supported.");
+ return;
+ }
+
+ const int kLocationsToAwait = 3;
+
+ gnss_cb_->location_cbq_.reset();
+ StartAndCheckLocations(kLocationsToAwait);
+ const 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 + 1, kLocationsToAwait);
+ ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations (%d received)",
+ sv_info_list_cbq_size, kLocationsToAwait, location_called_count);
+
+ // Find first non-GPS constellation to blacklist. Exclude IRNSS in GnssConstellationType_2_0
+ // as blacklisting of this constellation is not supported in gnss@2.0.
+ const int kGnssSvStatusTimeout = 2;
+ GnssConstellationType_1_0 constellation_to_blacklist = GnssConstellationType_1_0::UNKNOWN;
+ for (int i = 0; i < sv_info_list_cbq_size; ++i) {
+ hidl_vec<IGnssCallback_2_0::GnssSvInfo> sv_info_list;
+ gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_list, kGnssSvStatusTimeout);
+ for (IGnssCallback_2_0::GnssSvInfo sv_info : sv_info_list) {
+ if ((sv_info.v1_0.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX) &&
+ (sv_info.constellation != GnssConstellationType_2_0::UNKNOWN) &&
+ (sv_info.constellation != GnssConstellationType_2_0::IRNSS) &&
+ (sv_info.constellation != GnssConstellationType_2_0::GPS)) {
+ // found a non-GPS V1_0 constellation
+ constellation_to_blacklist = MapConstellationType(sv_info.constellation);
+ break;
+ }
+ }
+ if (constellation_to_blacklist != GnssConstellationType_1_0::UNKNOWN) {
+ break;
+ }
+ }
+
+ if (constellation_to_blacklist == GnssConstellationType_1_0::UNKNOWN) {
+ ALOGI("No non-GPS constellations found, constellation blacklist test less effective.");
+ // Proceed functionally to blacklist something.
+ constellation_to_blacklist = GnssConstellationType_1_0::GLONASS;
+ }
+ IGnssConfiguration_1_1::BlacklistedSource source_to_blacklist;
+ source_to_blacklist.constellation = constellation_to_blacklist;
+ source_to_blacklist.svid = 0; // documented wildcard for all satellites in this constellation
+
+ auto gnss_configuration_hal_return = gnss_hal_->getExtensionGnssConfiguration_1_1();
+ ASSERT_TRUE(gnss_configuration_hal_return.isOk());
+ sp<IGnssConfiguration_1_1> gnss_configuration_hal = gnss_configuration_hal_return;
+ ASSERT_NE(gnss_configuration_hal, nullptr);
+
+ hidl_vec<IGnssConfiguration_1_1::BlacklistedSource> sources;
+ sources.resize(1);
+ sources[0] = source_to_blacklist;
+
+ auto result = gnss_configuration_hal->setBlacklist(sources);
+ ASSERT_TRUE(result.isOk());
+ EXPECT_TRUE(result);
+
+ // retry and ensure constellation not used
+ gnss_cb_->sv_info_list_cbq_.reset();
+
+ gnss_cb_->location_cbq_.reset();
+ StartAndCheckLocations(kLocationsToAwait);
+
+ // Tolerate 1 less sv status to handle edge cases in reporting.
+ sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
+ EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
+ ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations", sv_info_list_cbq_size,
+ kLocationsToAwait);
+ for (int i = 0; i < sv_info_list_cbq_size; ++i) {
+ hidl_vec<IGnssCallback_2_0::GnssSvInfo> sv_info_list;
+ gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_list, kGnssSvStatusTimeout);
+ for (IGnssCallback_2_0::GnssSvInfo sv_info : sv_info_list) {
+ auto constellation = MapConstellationType(sv_info.constellation);
+ EXPECT_FALSE((constellation == source_to_blacklist.constellation) &&
+ (sv_info.v1_0.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX));
+ }
+ }
+
+ // clean up
+ StopAndClearLocations();
+ sources.resize(0);
+ result = gnss_configuration_hal->setBlacklist(sources);
+ ASSERT_TRUE(result.isOk());
+ EXPECT_TRUE(result);
+}
\ No newline at end of file
diff --git a/sensors/1.0/vts/functional/Android.bp b/sensors/1.0/vts/functional/Android.bp
index d4c5f32..444797d 100644
--- a/sensors/1.0/vts/functional/Android.bp
+++ b/sensors/1.0/vts/functional/Android.bp
@@ -16,6 +16,7 @@
cc_test {
name: "VtsHalSensorsV1_0TargetTest",
+ cflags: ["-DLOG_TAG=\"sensors_hidl_hal_test\""],
defaults: ["VtsHalTargetTestDefaults"],
srcs: [
"SensorsHidlEnvironmentV1_0.cpp",
diff --git a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
index 47308e1..5453ef6 100644
--- a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
+++ b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-#define LOG_TAG "sensors_hidl_hal_test"
-
#include "SensorsHidlEnvironmentV1_0.h"
#include "sensors-vts-utils/SensorsHidlTestBase.h"
diff --git a/sensors/2.0/vts/functional/Android.bp b/sensors/2.0/vts/functional/Android.bp
index 8e8413c..98f0eac 100644
--- a/sensors/2.0/vts/functional/Android.bp
+++ b/sensors/2.0/vts/functional/Android.bp
@@ -16,6 +16,7 @@
cc_test {
name: "VtsHalSensorsV2_0TargetTest",
+ cflags: ["-DLOG_TAG=\"sensors_hidl_hal_test\""],
defaults: ["VtsHalTargetTestDefaults"],
srcs: [
"SensorsHidlEnvironmentV2_0.cpp",
diff --git a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp
index 0525bdc..03fcc17 100644
--- a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp
+++ b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp
@@ -38,6 +38,13 @@
constexpr size_t SensorsHidlEnvironmentV2_0::MAX_RECEIVE_BUFFER_EVENT_COUNT;
+void SensorsHalDeathRecipient::serviceDied(
+ uint64_t /* cookie */,
+ const ::android::wp<::android::hidl::base::V1_0::IBase>& /* service */) {
+ ALOGE("Sensors HAL died (likely crashed) during test");
+ FAIL() << "Sensors HAL died during test";
+}
+
struct SensorsCallback : ISensorsCallback {
Return<void> onDynamicSensorsConnected(const hidl_vec<SensorInfo>& /* sensorInfos */) {
return Return<void>();
@@ -56,6 +63,7 @@
if (mSensors == nullptr) {
break;
}
+ mSensors->linkToDeath(mDeathRecipient, 0 /* cookie */);
// Initialize FMQs
mEventQueue = std::make_unique<EventMessageQueue>(MAX_RECEIVE_BUFFER_EVENT_COUNT,
diff --git a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.h b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.h
index 5e54530..b0dbd90 100644
--- a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.h
+++ b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.h
@@ -32,6 +32,13 @@
using ::android::hardware::MessageQueue;
class SensorsHidlTest;
+
+class SensorsHalDeathRecipient : public ::android::hardware::hidl_death_recipient {
+ virtual void serviceDied(
+ uint64_t cookie,
+ const ::android::wp<::android::hidl::base::V1_0::IBase>& service) override;
+};
+
class SensorsHidlEnvironmentV2_0 : public SensorsHidlEnvironmentBase {
public:
using Event = ::android::hardware::sensors::V1_0::Event;
@@ -84,6 +91,11 @@
sp<android::hardware::sensors::V2_0::ISensors> mSensors;
/**
+ * Monitors the HAL for crashes, triggering test failure if seen
+ */
+ sp<SensorsHalDeathRecipient> mDeathRecipient = new SensorsHalDeathRecipient();
+
+ /**
* Type used to simplify the creation of the Event FMQ
*/
typedef MessageQueue<Event, ::android::hardware::kSynchronizedReadWrite> EventMessageQueue;
diff --git a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
index 62c5334..6ff393d 100644
--- a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
+++ b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-#define LOG_TAG "sensors_hidl_hal_test"
-
#include "SensorsHidlEnvironmentV2_0.h"
#include "sensors-vts-utils/SensorsHidlTestBase.h"
#include "sensors-vts-utils/SensorsTestSharedMemory.h"
@@ -40,6 +38,10 @@
using ::android::hardware::sensors::V1_0::SensorStatus;
using ::android::hardware::sensors::V1_0::SharedMemType;
using ::android::hardware::sensors::V1_0::Vec3;
+using std::chrono::duration_cast;
+using std::chrono::microseconds;
+using std::chrono::milliseconds;
+using std::chrono::nanoseconds;
constexpr size_t kEventSize = static_cast<size_t>(SensorsEventFormatOffset::TOTAL_LENGTH);
@@ -69,9 +71,9 @@
}
void waitForFlushEvents(const std::vector<SensorInfo>& sensorsToWaitFor,
- int32_t numCallsToFlush, int64_t timeoutMs) {
+ int32_t numCallsToFlush, milliseconds timeout) {
std::unique_lock<std::recursive_mutex> lock(mFlushMutex);
- mFlushCV.wait_for(lock, std::chrono::milliseconds(timeoutMs),
+ mFlushCV.wait_for(lock, timeout,
[&] { return flushesReceived(sensorsToWaitFor, numCallsToFlush); });
}
@@ -80,10 +82,9 @@
return mEventMap[sensorHandle];
}
- void waitForEvents(const std::vector<SensorInfo>& sensorsToWaitFor, int32_t timeoutMs) {
+ void waitForEvents(const std::vector<SensorInfo>& sensorsToWaitFor, milliseconds timeout) {
std::unique_lock<std::recursive_mutex> lock(mEventMutex);
- mEventCV.wait_for(lock, std::chrono::milliseconds(timeoutMs),
- [&] { return eventsReceived(sensorsToWaitFor); });
+ mEventCV.wait_for(lock, timeout, [&] { return eventsReceived(sensorsToWaitFor); });
}
protected:
@@ -117,7 +118,13 @@
// The main test class for SENSORS HIDL HAL.
class SensorsHidlTest : public SensorsHidlTestBase {
- protected:
+ public:
+ virtual void SetUp() override {
+ // Ensure that we have a valid environment before performing tests
+ ASSERT_NE(getSensors(), nullptr);
+ }
+
+ protected:
SensorInfo defaultSensorByType(SensorType type) override;
std::vector<SensorInfo> getSensorsList();
// implementation wrapper
@@ -368,7 +375,7 @@
}
// Wait for events to be written back to the Event FMQ
- callback.waitForEvents(sensors, 1000 /* timeoutMs */);
+ callback.waitForEvents(sensors, milliseconds(1000) /* timeout */);
for (const auto& s : sensors) {
auto events = callback.getEvents(s.sensorHandle);
@@ -614,6 +621,9 @@
std::unique_ptr<SensorsHidlEnvironmentTest> newEnv =
std::make_unique<SensorsHidlEnvironmentTest>();
newEnv->HidlSetUp();
+ if (HasFatalFailure()) {
+ return; // Exit early if setting up the new environment failed
+ }
activateAllSensors(true);
// Verify that the old environment does not receive any events
@@ -626,8 +636,11 @@
newEnv->HidlTearDown();
// Restore the test environment for future tests
- SensorsHidlEnvironmentV2_0::Instance()->HidlTearDown();
- SensorsHidlEnvironmentV2_0::Instance()->HidlSetUp();
+ getEnvironment()->HidlTearDown();
+ getEnvironment()->HidlSetUp();
+ if (HasFatalFailure()) {
+ return; // Exit early if resetting the environment failed
+ }
// Ensure that the original environment is receiving events
activateAllSensors(true);
@@ -646,8 +659,11 @@
// Clear the active sensor handles so they are not disabled during TearDown
auto handles = mSensorHandles;
mSensorHandles.clear();
- getEnvironment()->TearDown();
- getEnvironment()->SetUp();
+ getEnvironment()->HidlTearDown();
+ getEnvironment()->HidlSetUp();
+ if (HasFatalFailure()) {
+ return; // Exit early if resetting the environment failed
+ }
// Verify no events are received until sensors are re-activated
ASSERT_EQ(collectEvents(kCollectionTimeoutUs, kNumEvents, getEnvironment()).size(), 0);
@@ -686,7 +702,7 @@
}
// Wait up to one second for the flush events
- callback.waitForFlushEvents(sensors, flushCalls, 1000 /* timeoutMs */);
+ callback.waitForFlushEvents(sensors, flushCalls, milliseconds(1000) /* timeout */);
// Deactivate all sensors after waiting for flush events so pending flush events are not
// abandoned by the HAL.
@@ -807,17 +823,18 @@
}
TEST_F(SensorsHidlTest, NoStaleEvents) {
- constexpr int64_t kFiveHundredMilliseconds = 500 * 1000;
- constexpr int64_t kOneSecond = 1000 * 1000;
+ constexpr milliseconds kFiveHundredMs(500);
+ constexpr milliseconds kOneSecond(1000);
// Register the callback to receive sensor events
EventCallback callback;
getEnvironment()->registerCallback(&callback);
const std::vector<SensorInfo> sensors = getSensorsList();
- int32_t maxMinDelay = 0;
+ milliseconds maxMinDelay(0);
for (const SensorInfo& sensor : getSensorsList()) {
- maxMinDelay = std::max(maxMinDelay, sensor.minDelay);
+ milliseconds minDelay = duration_cast<milliseconds>(microseconds(sensor.minDelay));
+ maxMinDelay = milliseconds(std::max(maxMinDelay.count(), minDelay.count()));
}
// Activate the sensors so that they start generating events
@@ -826,7 +843,7 @@
// According to the CDD, the first sample must be generated within 400ms + 2 * sample_time
// and the maximum reporting latency is 100ms + 2 * sample_time. Wait a sufficient amount
// of time to guarantee that a sample has arrived.
- callback.waitForEvents(sensors, kFiveHundredMilliseconds + (5 * maxMinDelay));
+ callback.waitForEvents(sensors, kFiveHundredMs + (5 * maxMinDelay));
activateAllSensors(false);
// Save the last received event for each sensor
@@ -838,21 +855,21 @@
}
// Allow some time to pass, reset the callback, then reactivate the sensors
- usleep(kOneSecond + (5 * maxMinDelay));
+ usleep(duration_cast<microseconds>(kOneSecond + (5 * maxMinDelay)).count());
callback.reset();
activateAllSensors(true);
- callback.waitForEvents(sensors, kFiveHundredMilliseconds + (5 * maxMinDelay));
+ callback.waitForEvents(sensors, kFiveHundredMs + (5 * maxMinDelay));
activateAllSensors(false);
for (const SensorInfo& sensor : sensors) {
// Ensure that the first event received is not stale by ensuring that its timestamp is
// sufficiently different from the previous event
const Event newEvent = callback.getEvents(sensor.sensorHandle).front();
- int64_t delta = newEvent.timestamp - lastEventTimestampMap[sensor.sensorHandle];
- ASSERT_GE(delta, kFiveHundredMilliseconds + (3 * sensor.minDelay));
+ milliseconds delta = duration_cast<milliseconds>(
+ nanoseconds(newEvent.timestamp - lastEventTimestampMap[sensor.sensorHandle]));
+ milliseconds sensorMinDelay = duration_cast<milliseconds>(microseconds(sensor.minDelay));
+ ASSERT_GE(delta, kFiveHundredMs + (3 * sensorMinDelay));
}
-
- getEnvironment()->unregisterCallback();
}
void SensorsHidlTest::checkRateLevel(const SensorInfo& sensor, int32_t directChannelHandle,
@@ -1030,8 +1047,11 @@
// Clear the active direct connections so they are not stopped during TearDown
auto handles = mDirectChannelHandles;
mDirectChannelHandles.clear();
- getEnvironment()->TearDown();
- getEnvironment()->SetUp();
+ getEnvironment()->HidlTearDown();
+ getEnvironment()->HidlSetUp();
+ if (HasFatalFailure()) {
+ return; // Exit early if resetting the environment failed
+ }
// Attempt to configure the direct channel and expect it to fail
configDirectReport(
diff --git a/sensors/common/vts/utils/Android.bp b/sensors/common/vts/utils/Android.bp
index 95df425..8da554a 100644
--- a/sensors/common/vts/utils/Android.bp
+++ b/sensors/common/vts/utils/Android.bp
@@ -16,6 +16,7 @@
cc_library_static {
name: "VtsHalSensorsTargetTestUtils",
+ cflags: ["-DLOG_TAG=\"sensors_hidl_hal_test\""],
srcs: [
"GrallocWrapper.cpp",
"SensorsHidlEnvironmentBase.cpp",
diff --git a/sensors/common/vts/utils/GrallocWrapper.cpp b/sensors/common/vts/utils/GrallocWrapper.cpp
index 7bed16d..222ef96 100644
--- a/sensors/common/vts/utils/GrallocWrapper.cpp
+++ b/sensors/common/vts/utils/GrallocWrapper.cpp
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-#define LOG_TAG "GrallocWrapper"
-
#include "GrallocWrapper.h"
#include <utils/Log.h>
@@ -35,8 +33,7 @@
mMapper = mapper2::IMapper::getService();
if (mMapper == nullptr) {
ALOGE("Failed to get mapper service");
- }
- if (mMapper->isRemote()) {
+ } else if (mMapper->isRemote()) {
ALOGE("Mapper is not in passthrough mode");
}
}